Exemple #1
0
// Called from the blockchain thread
func HandleNetBlock(newbl *network.BlockRcvd) {
	common.CountSafe("HandleNetBlock")
	bl := newbl.Block
	common.Busy("CheckBlock " + bl.Hash.String())
	e, dos, maybelater := common.BlockChain.CheckBlock(bl)
	if e != nil {
		if maybelater {
			network.AddBlockToCache(bl, newbl.Conn)
		} else {
			fmt.Println(dos, e.Error())
			if dos {
				newbl.Conn.DoS("CheckBlock")
			}
		}
	} else {
		common.Busy("LocalAcceptBlock " + bl.Hash.String())
		e = LocalAcceptBlock(bl, newbl.Conn)
		if e == nil {
			retryCachedBlocks = retry_cached_blocks()
		} else {
			fmt.Println("AcceptBlock:", e.Error())
			newbl.Conn.DoS("LocalAcceptBl")
		}
	}
}
Exemple #2
0
func retry_cached_blocks() bool {
	if len(network.CachedBlocks) == 0 {
		return false
	}
	accepted_cnt := 0
	for k, v := range network.CachedBlocks {
		common.Busy("Cache.CheckBlock " + v.Block.Hash.String())
		e, dos, maybelater := common.BlockChain.CheckBlock(v.Block)
		if e == nil {
			common.Busy("Cache.AcceptBlock " + v.Block.Hash.String())
			e := LocalAcceptBlock(v.Block, v.Conn)
			if e == nil {
				//fmt.Println("*** Old block accepted", common.BlockChain.BlockTreeEnd.Height)
				common.CountSafe("BlocksFromCache")
				delete(network.CachedBlocks, k)
				accepted_cnt++
				break // One at a time should be enough
			} else {
				fmt.Println("retry AcceptBlock:", e.Error())
				v.Conn.DoS("BadCachedBlock1")
				delete(network.CachedBlocks, k)
			}
		} else {
			if !maybelater {
				fmt.Println("retry CheckBlock:", e.Error())
				common.CountSafe("BadCachedBlocks")
				if dos {
					v.Conn.DoS("BadCachedBlock2")
				}
				delete(network.CachedBlocks, k)
			}
		}
	}
	return accepted_cnt > 0 && len(network.CachedBlocks) > 0
}
Exemple #3
0
func retry_cached_blocks() bool {
	var idx int
	common.CountSafe("RedoCachedBlks")
	for idx < len(network.CachedBlocks) {
		newbl := network.CachedBlocks[idx]
		if CheckParentDiscarded(newbl.BlockTreeNode) {
			common.CountSafe("DiscardCachedBlock")
			network.CachedBlocks = append(network.CachedBlocks[:idx], network.CachedBlocks[idx+1:]...)
			return len(network.CachedBlocks) > 0
		}
		if common.BlockChain.HasAllParents(newbl.BlockTreeNode) {
			common.Busy("Cache.LocalAcceptBlock " + newbl.Block.Hash.String())
			e := LocalAcceptBlock(newbl)
			if e != nil {
				fmt.Println("AcceptBlock:", e.Error())
				newbl.Conn.DoS("LocalAcceptBl")
			}
			if usif.Exit_now {
				return false
			}
			// remove it from cache
			network.CachedBlocks = append(network.CachedBlocks[:idx], network.CachedBlocks[idx+1:]...)
			return len(network.CachedBlocks) > 0
		} else {
			idx++
		}
	}
	return false
}
Exemple #4
0
// Freshly mined block - do the inv and beeps... TODO: combine it with the other code
func new_block_mined(bl *btc.Block, conn *network.OneConnection) {
	common.Busy("NetRouteInv")
	network.NetRouteInv(2, bl.Hash, conn)

	if common.CFG.Beeps.NewBlock {
		fmt.Println("\007Received block", common.BlockChain.BlockTreeEnd.Height)
		textui.ShowPrompt()
	}

	if common.CFG.Beeps.MinerID != "" {
		//_, rawtxlen := btc.NewTx(bl[bl.TxOffset:])
		if bytes.Contains(bl.Txs[0].Serialize(), []byte(common.CFG.Beeps.MinerID)) {
			fmt.Println("\007Mined by '"+common.CFG.Beeps.MinerID+"':", bl.Hash)
			textui.ShowPrompt()
		}
	}

	if common.CFG.Beeps.ActiveFork && common.Last.Block == common.BlockChain.BlockTreeEnd {
		// Last block has not changed, so it must have been an orphaned block
		bln := common.BlockChain.BlockIndex[bl.Hash.BIdx()]
		commonNode := common.Last.Block.FirstCommonParent(bln)
		forkDepth := bln.Height - commonNode.Height
		fmt.Println("Orphaned block:", bln.Height, bl.Hash.String(), bln.BlockSize>>10, "KB")
		if forkDepth > 1 {
			fmt.Println("\007\007\007WARNING: the fork is", forkDepth, "blocks deep")
		}
		textui.ShowPrompt()
	}
}
Exemple #5
0
// Called from the blockchain thread
func HandleNetBlock(newbl *network.BlockRcvd) {
	if CheckParentDiscarded(newbl.BlockTreeNode) {
		common.CountSafe("DiscardFreshBlockA")
		retryCachedBlocks = len(network.CachedBlocks) > 0
		return
	}

	if !common.BlockChain.HasAllParents(newbl.BlockTreeNode) {
		// it's not linking - keep it for later
		network.CachedBlocks = append(network.CachedBlocks, newbl)
		common.CountSafe("BlockPostone")
		return
	}

	common.Busy("LocalAcceptBlock " + newbl.Hash.String())
	e := LocalAcceptBlock(newbl)
	if e != nil {
		common.CountSafe("DiscardFreshBlockB")
		fmt.Println("AcceptBlock:", e.Error())
		newbl.Conn.DoS("LocalAcceptBl")
	} else {
		//println("block", newbl.Block.Height, "accepted")
		retryCachedBlocks = retry_cached_blocks()
	}
}
Exemple #6
0
func LocalAcceptBlock(bl *btc.Block, from *network.OneConnection) (e error) {
	sta := time.Now()
	e = common.BlockChain.AcceptBlock(bl)
	if e == nil {
		network.MutexRcv.Lock()
		network.ReceivedBlocks[bl.Hash.BIdx()].TmAccept = time.Now().Sub(sta)
		network.MutexRcv.Unlock()

		for i := 1; i < len(bl.Txs); i++ {
			network.TxMined(bl.Txs[i].Hash)
		}

		if int64(bl.BlockTime) > time.Now().Add(-10*time.Minute).Unix() {
			// Freshly mined block - do the inv and beeps...
			common.Busy("NetRouteInv")
			network.NetRouteInv(2, bl.Hash, from)

			if common.CFG.Beeps.NewBlock {
				fmt.Println("\007Received block", common.BlockChain.BlockTreeEnd.Height)
				textui.ShowPrompt()
			}

			if common.MinedByUs(bl.Raw) {
				fmt.Println("\007Mined by '"+common.CFG.Beeps.MinerID+"':", bl.Hash)
				textui.ShowPrompt()
			}

			if common.CFG.Beeps.ActiveFork && common.Last.Block == common.BlockChain.BlockTreeEnd {
				// Last block has not changed, so it must have been an orphaned block
				bln := common.BlockChain.BlockIndex[bl.Hash.BIdx()]
				commonNode := common.Last.Block.FirstCommonParent(bln)
				forkDepth := bln.Height - commonNode.Height
				fmt.Println("Orphaned block:", bln.Height, bl.Hash.String())
				if forkDepth > 1 {
					fmt.Println("\007\007\007WARNING: the fork is", forkDepth, "blocks deep")
				}
				textui.ShowPrompt()
			}

			if wallet.BalanceChanged && common.CFG.Beeps.NewBalance {
				fmt.Print("\007")
			}
		}

		common.Last.Mutex.Lock()
		common.Last.Time = time.Now()
		common.Last.Block = common.BlockChain.BlockTreeEnd
		common.Last.Mutex.Unlock()

		if wallet.BalanceChanged {
			wallet.BalanceChanged = false
			fmt.Println("Your balance has just changed")
			fmt.Print(wallet.DumpBalance(nil, false))
			textui.ShowPrompt()
		}
	} else {
		fmt.Println("Warning: AcceptBlock failed. If the block was valid, you may need to rebuild the unspent DB (-r)")
	}
	return
}
Exemple #7
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", btc.SourcesTag)
	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()
			network.ClosePeerDB()
			utils.UnlockDatabaseDir()
			os.Exit(1)
		}
	}()

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

	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.FetchAllBalances()

	// ... 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))
	}

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

	network.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:
			HandleNetBlock(newbl)

		case newtx := <-network.NetTxs:
			network.HandleNetTx(newtx, false)

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

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

		case <-peersTick:
			network.ExpirePeers()

		case <-txPoolTick:
			network.ExpireTxs()

		case <-netTick:
			network.NetworkTick()

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

		common.CountSafe("NetMessagesGot")
	}

	network.NetCloseAll()
	network.ClosePeerDB()

	if usif.DefragBlocksDB {
		defrag_db()
	}

	common.CloseBlockChain()
	utils.UnlockDatabaseDir()
}
Exemple #8
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", gocoin.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(false)
			peersdb.ClosePeerDB()
			sys.UnlockDatabaseDir()
			os.Exit(1)
		}
	}()

	common.InitConfig()

	if common.FLAG.VolatileUTXO {
		fmt.Println("WARNING! Using UTXO database in a volatile mode. Make sure to close the client properly (do not kill it!)")
	}

	if common.FLAG.TrustAll {
		fmt.Println("WARNING! Assuming all scripts inside new blocks to PASS. Verify the last block's hash when finished.")
	}

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

	if common.FLAG.UndoBlocks > 0 {
		usif.Exit_now = true
	}

	if common.FLAG.Rescan && common.FLAG.VolatileUTXO {

		fmt.Println("UTXO database rebuilt complete in the volatile mode, so flush DB to disk and exit...")

	} else if !usif.Exit_now {

		common.RecalcAverageBlockSize(true)

		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)
		if common.FLAG.UnbanAllPeers {
			var keys []qdb.KeyType
			var vals [][]byte
			peersdb.PeerDB.Browse(func(k qdb.KeyType, v []byte) uint32 {
				peer := utils.NewPeer(v)
				if peer.Banned != 0 {
					fmt.Println("Unban", peer.NetAddr.String())
					peer.Banned = 0
					keys = append(keys, k)
					vals = append(vals, peer.Bytes())
				}
				return 0
			})
			for i := range keys {
				peersdb.PeerDB.Put(keys[i], vals[i])
			}

			fmt.Println(len(keys), "peerts un-baned")
		}

		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{TmStart: time.Unix(int64(v.Timestamp()), 0)}
		}
		network.LastCommitedHeader = common.Last.Block

		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)
		}

		if common.CFG.RPC.Enabled {
			go rpcapi.StartServer(common.RPCPort())
		}

		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 rpcbl := <-rpcapi.RpcBlocks:
				common.CountSafe("RPCNewBlock")
				common.Busy("HandleRpcBlock()")
				HandleRpcBlock(rpcbl)

			case rec := <-usif.LocksChan:
				common.CountSafe("MainLocks")
				common.Busy("LockedByRequest")
				rec.In.Done()
				rec.Out.Wait()
				continue

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

			case <-syncNow:
				common.CountSafe("MainChainSync")
				common.Busy("BlockChain.Sync()")
				common.BlockChain.Sync()

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

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

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

			case <-peersTick:
				common.Busy("peersdb.ExpirePeers()")
				peersdb.ExpirePeers()

			case <-txPoolTick:
				common.Busy("network.ExpireTxs()")
				network.ExpireTxs()

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

		network.NetCloseAll()
	}

	if usif.DefragUTXO {
		fmt.Println("Closing blockchain while defragmenting UTXO")
	} else {
		fmt.Println("Closing blockchain")
	}
	sta := time.Now()
	common.CloseBlockChain(usif.DefragUTXO)
	fmt.Println("Blockchain closed in", time.Now().Sub(sta).String())
	peersdb.ClosePeerDB()
	sys.UnlockDatabaseDir()
}
Exemple #9
0
func main() {
	if btc.EC_Verify == nil {
		fmt.Println("WARNING: EC_Verify acceleration disabled. Enable EC_Verify wrapper if possible.")
	}
	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", btc.SourcesTag)
	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()
			network.ClosePeerDB()
			utils.UnlockDatabaseDir()
			os.Exit(1)
		}
	}()

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

	// Clean up the DB lock file on exit

	// cache the current balance of all the addresses from the current wallet files
	wallet.FetchAllBalances()
	// ... and now switch to the dafault wallet
	wallet.LoadWallet(common.GocoinHomeDir + "wallet" + string(os.PathSeparator) + "DEFAULT")
	if wallet.MyWallet == nil {
		wallet.LoadWallet(common.GocoinHomeDir + "wallet.txt")
	}
	if wallet.MyWallet != nil {
		wallet.UpdateBalance()
		fmt.Print(wallet.DumpBalance(nil, false))
	}

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

	network.InitPeers(common.GocoinHomeDir)

	common.Last.Block = common.BlockChain.BlockTreeEnd
	common.Last.Time = time.Unix(int64(common.Last.Block.Timestamp), 0)

	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:
			HandleNetBlock(newbl)

		case newtx := <-network.NetTxs:
			network.HandleNetTx(newtx, false)

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

		case <-peersTick:
			network.ExpirePeers()

		case <-txPoolTick:
			network.ExpireTxs()

		case <-netTick:
			network.NetworkTick()

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

		common.CountSafe("NetMessagesGot")
	}

	network.NetCloseAll()
	network.ClosePeerDB()

	if usif.DefragBlocksDB {
		defrag_db()
	}

	common.CloseBlockChain()
	utils.UnlockDatabaseDir()
}
Exemple #10
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()
}
Exemple #11
0
func LocalAcceptBlock(bl *btc.Block, from *network.OneConnection) (e error) {
	sta := time.Now()
	e = common.BlockChain.AcceptBlock(bl)
	if e == nil {
		network.MutexRcv.Lock()
		network.ReceivedBlocks[bl.Hash.BIdx()].TmAccept = time.Now().Sub(sta)
		network.MutexRcv.Unlock()

		for i := 1; i < len(bl.Txs); i++ {
			network.TxMined(bl.Txs[i])
			/* dupa
			if msg:=contains_message(bl.Txs[i]); msg!=nil {
				for xx:=range msg {
					if msg[xx]<' ' || msg[xx]>127 {
						msg[xx] = '.'
					}
				}
				fmt.Println("TX", bl.Txs[i].Hash.String(), "says:", "'" + string(msg) + "'")
				textui.ShowPrompt()
			}
			*/
		}

		if int64(bl.BlockTime()) > time.Now().Add(-10*time.Minute).Unix() {
			// Freshly mined block - do the inv and beeps...
			common.Busy("NetRouteInv")
			network.NetRouteInv(2, bl.Hash, from)

			if common.CFG.Beeps.NewBlock {
				fmt.Println("\007Received block", common.BlockChain.BlockTreeEnd.Height)
				textui.ShowPrompt()
			}

			if common.CFG.Beeps.MinerID != "" {
				//_, rawtxlen := btc.NewTx(bl[bl.TxOffset:])
				if bytes.Contains(bl.Txs[0].Serialize(), []byte(common.CFG.Beeps.MinerID)) {
					fmt.Println("\007Mined by '"+common.CFG.Beeps.MinerID+"':", bl.Hash)
					textui.ShowPrompt()
				}
			}

			if common.CFG.Beeps.ActiveFork && common.Last.Block == common.BlockChain.BlockTreeEnd {
				// Last block has not changed, so it must have been an orphaned block
				bln := common.BlockChain.BlockIndex[bl.Hash.BIdx()]
				commonNode := common.Last.Block.FirstCommonParent(bln)
				forkDepth := bln.Height - commonNode.Height
				fmt.Println("Orphaned block:", bln.Height, bl.Hash.String(), bln.BlockSize>>10, "KB")
				if forkDepth > 1 {
					fmt.Println("\007\007\007WARNING: the fork is", forkDepth, "blocks deep")
				}
				textui.ShowPrompt()
			}

			if wallet.BalanceChanged && common.CFG.Beeps.NewBalance {
				fmt.Print("\007")
			}
		}

		common.Last.Mutex.Lock()
		common.Last.Time = time.Now()
		common.Last.Block = common.BlockChain.BlockTreeEnd
		common.Last.Mutex.Unlock()

		if wallet.BalanceChanged {
			wallet.BalanceChanged = false
			fmt.Println("Your balance has just changed")
			fmt.Print(wallet.DumpBalance(wallet.MyBalance, nil, false, true))
			textui.ShowPrompt()
		}
	} else {
		fmt.Println("Warning: AcceptBlock failed. If the block was valid, you may need to rebuild the unspent DB (-r)")
	}
	return
}