Пример #1
0
func main() {
	fmt.Println("Gocoin blockchain downloader version", lib.Version)
	parse_command_line()
	setup_runtime_vars()

	if len(GocoinHomeDir) > 0 && GocoinHomeDir[len(GocoinHomeDir)-1] != os.PathSeparator {
		GocoinHomeDir += string(os.PathSeparator)
	}
	if Testnet {
		GocoinHomeDir += "tstnet" + string(os.PathSeparator)
		Magic = [4]byte{0x0B, 0x11, 0x09, 0x07}
		GenesisBlock = btc.NewUint256FromString("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943")
		fmt.Println("Using testnet3")
	} else {
		GocoinHomeDir += "btcnet" + string(os.PathSeparator)
	}
	fmt.Println("GocoinHomeDir:", GocoinHomeDir)

	sys.LockDatabaseDir(GocoinHomeDir)
	defer sys.UnlockDatabaseDir()

	peersdb.Testnet = Testnet
	peersdb.InitPeers(GocoinHomeDir)

	StartTime = time.Now()
	if open_blockchain() {
		fmt.Printf("Blockchain opening aborted\n")
		return
	}
	fmt.Println("Blockchain open in", time.Now().Sub(StartTime))

	go do_usif()

	download_headers()
	if GlobalExit() {
		TheBlockChain.Close()
		return
	}

	var HighestTrustedBlock *btc.Uint256
	if LastTrustedBlock == "all" {
		HighestTrustedBlock = TheBlockChain.BlockTreeEnd.BlockHash
		fmt.Println("Assume all blocks trusted")
	} else if LastTrustedBlock == "auto" {
		if LastBlockHeight > 6 {
			use := LastBlockHeight - 6
			ha := BlocksToGet[use]
			HighestTrustedBlock = btc.NewUint256(ha[:])
			fmt.Println("Assume last trusted block as", HighestTrustedBlock.String(), "at", use)
		} else {
			fmt.Println("-t=auto ignored since LastBlockHeight is only", LastBlockHeight)
		}
	} else if LastTrustedBlock != "" {
		HighestTrustedBlock = btc.NewUint256FromString(LastTrustedBlock)
	}
	if HighestTrustedBlock != nil {
		for k, h := range BlocksToGet {
			if bytes.Equal(h[:], HighestTrustedBlock.Hash[:]) {
				TrustUpTo = k
				break
			}
		}
	} else {
		fmt.Println("WARNING: The trusted block not found (it will be very slow).")
	}

	for n := TheBlockChain.BlockTreeEnd; n != nil && n.Height > TheBlockChain.BlockTreeEnd.Height-BSLEN; n = n.Parent {
		blocksize_update(int(n.BlockSize))
	}

	fmt.Println("Downloading blocks - BlocksToGet:", len(BlocksToGet), "  avg_size:", avg_block_size())
	usif_prompt()
	StartTime = time.Now()
	get_blocks()
	fmt.Println("Up to block", TheBlockChain.BlockTreeEnd.Height, "in", time.Now().Sub(StartTime).String())
	close_all_connections()

	peersdb.ClosePeerDB()

	StartTime = time.Now()
	fmt.Print("All blocks done - defrag unspent")
	qdb.SetDefragPercent(100)
	for {
		if !TheBlockChain.Unspent.Idle() {
			break
		}
		fmt.Print(".")
	}
	fmt.Println("\nDefrag unspent done in", time.Now().Sub(StartTime).String())
	TheBlockChain.Close()

	return
}
Пример #2
0
func host_init() {
	var e error
	BtcRootDir := sys.BitcoinHome()

	if common.CFG.Datadir == "" {
		common.GocoinHomeDir = BtcRootDir + "gocoin" + string(os.PathSeparator)
	} else {
		common.GocoinHomeDir = common.CFG.Datadir + string(os.PathSeparator)
	}

	common.Testnet = common.CFG.Testnet // So chaging this value would will only affect the behaviour after restart
	if common.CFG.Testnet {             // testnet3
		common.GenesisBlock = btc.NewUint256FromString("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943")
		common.Magic = [4]byte{0x0B, 0x11, 0x09, 0x07}
		common.GocoinHomeDir += "tstnet" + string(os.PathSeparator)
		BtcRootDir += "testnet3" + string(os.PathSeparator)
		network.AlertPubKey, _ = hex.DecodeString("04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a")
		common.MaxPeersNeeded = 100
	} else {
		common.GenesisBlock = btc.NewUint256FromString("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")
		common.Magic = [4]byte{0xF9, 0xBE, 0xB4, 0xD9}
		common.GocoinHomeDir += "btcnet" + string(os.PathSeparator)
		network.AlertPubKey, _ = hex.DecodeString("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284")
		common.MaxPeersNeeded = 1000
	}

	// Lock the folder
	os.MkdirAll(common.GocoinHomeDir, 0770)
	os.MkdirAll(common.GocoinHomeDir+"wallet", 0770)
	sys.LockDatabaseDir(common.GocoinHomeDir)

	fi, e := os.Stat(common.GocoinHomeDir + "blockchain.dat")
	if e != nil {
		os.RemoveAll(common.GocoinHomeDir)
		fmt.Println("You seem to be running Gocoin for the fist time on this PC")
		fi, e = os.Stat(BtcRootDir + "blocks/blk00000.dat")
		if e == nil && fi.Size() > 1024*1024 {
			fmt.Println("There is a database from Satoshi client on your disk...")
			if textui.AskYesNo("Do you want to import this database into Gocoin?") {
				import_blockchain(BtcRootDir + "blocks")
			}
		}
	}

	// Create default wallet file if does not exist
	default_wallet_fn := common.GocoinHomeDir + "wallet" + string(os.PathSeparator) + wallet.DefaultFileName
	fi, _ = os.Stat(default_wallet_fn)
	if fi == nil || fi.IsDir() {
		fmt.Println(default_wallet_fn, "not found")

		old_wallet_location := common.GocoinHomeDir + "wallet.txt"
		// If there is wallet.txt rename it to default.
		fi, _ := os.Stat(old_wallet_location)
		if fi != nil && !fi.IsDir() {
			fmt.Println("Taking wallet.txt as", default_wallet_fn)
			os.Rename(old_wallet_location, default_wallet_fn)
		} else {
			fmt.Println("Creating empty default wallet at", default_wallet_fn)
			ioutil.WriteFile(default_wallet_fn, []byte(fmt.Sprintln("# Put your wallet's public addresses here")), 0660)
		}
	}

	// cache the current balance of all the addresses from the current wallet files
	wallet.LoadAllWallets()

	fmt.Println("Loading UTXO database while checking balance of", len(wallet.MyWallet.Addrs),
		"addresses... (press Ctrl-C to interrupt)")

	__exit := make(chan bool)
	__done := make(chan bool)
	go func() {
		for {
			select {
			case s := <-killchan:
				fmt.Println(s)
				chain.AbortNow = true
			case <-__exit:
				__done <- true
				return
			}
		}
	}()

	ext := &chain.NewChanOpts{NotifyTxAdd: wallet.TxNotifyAdd,
		NotifyTxDel: wallet.TxNotifyDel, LoadWalk: wallet.NewUTXO}

	sta := time.Now().UnixNano()
	common.BlockChain = chain.NewChainExt(common.GocoinHomeDir, common.GenesisBlock, common.FLAG.Rescan, ext)
	sto := time.Now().UnixNano()
	if chain.AbortNow {
		fmt.Printf("Blockchain opening aborted after %.3f seconds\n", float64(sto-sta)/1e9)
		common.BlockChain.Close()
		sys.UnlockDatabaseDir()
		os.Exit(1)
	}
	wallet.ChainInitDone()
	al, sy := sys.MemUsed()
	fmt.Printf("Blockchain open in %.3f seconds.  %d + %d MB of RAM used (%d)\n",
		float64(sto-sta)/1e9, al>>20, qdb.ExtraMemoryConsumed>>20, sy>>20)
	common.StartTime = time.Now()
	__exit <- true
	_ = <-__done

	// ... and now load the dafault wallet
	wallet.LoadWallet(default_wallet_fn)
	if wallet.MyWallet != nil {
		wallet.UpdateBalance()
		fmt.Print(wallet.DumpBalance(wallet.MyBalance, nil, false, true))
	}
}
Пример #3
0
func main() {
	var ptr *byte
	if unsafe.Sizeof(ptr) < 8 {
		fmt.Println("WARNING: Gocoin client shall be build for 64-bit arch. It will likely crash now.")
	}

	fmt.Println("Gocoin client version", lib.Version)
	runtime.GOMAXPROCS(runtime.NumCPU()) // It seems that Go does not do it by default

	// Disable Ctrl+C
	signal.Notify(killchan, os.Interrupt, os.Kill)
	defer func() {
		if r := recover(); r != nil {
			err, ok := r.(error)
			if !ok {
				err = fmt.Errorf("pkg: %v", r)
			}
			fmt.Println("main panic recovered:", err.Error())
			fmt.Println(string(debug.Stack()))
			network.NetCloseAll()
			common.CloseBlockChain()
			peersdb.ClosePeerDB()
			sys.UnlockDatabaseDir()
			os.Exit(1)
		}
	}()

	common.InitConfig()
	host_init() // This will create the DB lock file and keep it open

	peersTick := time.Tick(5 * time.Minute)
	txPoolTick := time.Tick(time.Minute)
	netTick := time.Tick(time.Second)

	peersdb.Testnet = common.Testnet
	peersdb.ConnectOnly = common.CFG.ConnectOnly
	peersdb.Services = common.Services
	peersdb.InitPeers(common.GocoinHomeDir)

	common.Last.Block = common.BlockChain.BlockTreeEnd
	common.Last.Time = time.Unix(int64(common.Last.Block.Timestamp()), 0)
	if common.Last.Time.After(time.Now()) {
		common.Last.Time = time.Now()
	}

	for k, v := range common.BlockChain.BlockIndex {
		network.ReceivedBlocks[k] = &network.OneReceivedBlock{Time: time.Unix(int64(v.Timestamp()), 0)}
	}

	if common.CFG.TextUI.Enabled {
		go textui.MainThread()
	}

	if common.CFG.WebUI.Interface != "" {
		fmt.Println("Starting WebUI at", common.CFG.WebUI.Interface, "...")
		go webui.ServerThread(common.CFG.WebUI.Interface)
	}

	for !usif.Exit_now {
		common.CountSafe("MainThreadLoops")
		for retryCachedBlocks {
			retryCachedBlocks = retry_cached_blocks()
			// We have done one per loop - now do something else if pending...
			if len(network.NetBlocks) > 0 || len(usif.UiChannel) > 0 {
				break
			}
		}

		common.Busy("")

		select {
		case s := <-killchan:
			fmt.Println("Got signal:", s)
			usif.Exit_now = true
			continue

		case newbl := <-network.NetBlocks:
			common.CountSafe("MainNetBlock")
			HandleNetBlock(newbl)

		case newtx := <-network.NetTxs:
			common.CountSafe("MainNetTx")
			network.HandleNetTx(newtx, false)

		case newal := <-network.NetAlerts:
			common.CountSafe("MainNetAlert")
			fmt.Println("\007" + newal)
			textui.ShowPrompt()

		case <-netTick:
			common.CountSafe("MainNetTick")
			network.NetworkTick()

		case cmd := <-usif.UiChannel:
			common.CountSafe("MainUICmd")
			common.Busy("UI command")
			cmd.Handler(cmd.Param)
			cmd.Done.Done()
			continue

		case <-peersTick:
			peersdb.ExpirePeers()

		case <-txPoolTick:
			network.ExpireTxs()

		case <-time.After(time.Second / 2):
			common.CountSafe("MainThreadTouts")
			if !retryCachedBlocks {
				common.Busy("common.BlockChain.Idle()")
				if common.BlockChain.Idle() {
					common.CountSafe("ChainIdleUsed")
				}
			}
			continue
		}
	}

	network.NetCloseAll()
	peersdb.ClosePeerDB()

	if usif.DefragBlocksDB != 0 {
		defrag_db()
	}

	common.CloseBlockChain()
	sys.UnlockDatabaseDir()
}