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 }
func chkblock(bl *btc.Block) (er error) { // Check timestamp (must not be higher than now +2 hours) if int64(bl.BlockTime()) > time.Now().Unix()+2*60*60 { er = errors.New("CheckBlock() : block timestamp too far in the future") return } if prv, pres := MemBlockChain.BlockIndex[bl.Hash.BIdx()]; pres { if prv.Parent == nil { // This is genesis block er = errors.New("Genesis") return } else { return } } prevblk, ok := MemBlockChain.BlockIndex[btc.NewUint256(bl.ParentHash()).BIdx()] if !ok { er = errors.New("CheckBlock: " + bl.Hash.String() + " parent not found") return } // Check proof of work gnwr := MemBlockChain.GetNextWorkRequired(prevblk, bl.BlockTime()) if bl.Bits() != gnwr { if !Testnet || ((prevblk.Height+1)%2016) != 0 { er = errors.New(fmt.Sprint("CheckBlock: Incorrect proof of work at block", prevblk.Height+1)) } } cur := new(btc.BlockTreeNode) cur.BlockHash = bl.Hash cur.Parent = prevblk cur.Height = prevblk.Height + 1 cur.TxCount = uint32(bl.TxCount) copy(cur.BlockHeader[:], bl.Raw[:80]) prevblk.Childs = append(prevblk.Childs, cur) MemBlockChain.BlockIndex[cur.BlockHash.BIdx()] = cur LastBlock.Mutex.Lock() if cur.Height > LastBlock.node.Height { LastBlock.node = cur } LastBlock.Mutex.Unlock() return }
func import_blockchain(dir string) { trust := !textui.AskYesNo("Do you want to verify scripts while importing (will be slow)?") BlockDatabase := blockdb.NewBlockDB(dir, common.Magic) chain := btc.NewChain(common.GocoinHomeDir, common.GenesisBlock, false) var bl *btc.Block var er error var dat []byte var totbytes, perbytes uint64 chain.DoNotSync = true fmt.Println("Be patient while importing Satoshi's database... ") start := time.Now().UnixNano() prv := start for { now := time.Now().UnixNano() if now-prv >= 10e9 { stat(now-start, now-prv, totbytes, perbytes, chain.BlockTreeEnd.Height) prv = now // show progress each 10 seconds perbytes = 0 } dat, er = BlockDatabase.FetchNextBlock() if dat == nil || er != nil { println("END of DB file") break } bl, er = btc.NewBlock(dat[:]) if er != nil { println("Block inconsistent:", er.Error()) break } bl.Trusted = trust er, _, _ = chain.CheckBlock(bl) if er != nil { if er.Error() != "Genesis" { println("CheckBlock failed:", er.Error()) //os.Exit(1) // Such a thing should not happen, so let's better abort here. } continue } er = chain.AcceptBlock(bl) if er != nil { println("AcceptBlock failed:", er.Error()) //os.Exit(1) // Such a thing should not happen, so let's better abort here. } totbytes += uint64(len(bl.Raw)) perbytes += uint64(len(bl.Raw)) } stop := time.Now().UnixNano() stat(stop-start, stop-prv, totbytes, perbytes, chain.BlockTreeEnd.Height) fmt.Println("Satoshi's database import finished in", (stop-start)/1e9, "seconds") fmt.Println("Now saving the new database...") chain.Sync() chain.Save() chain.Close() fmt.Println("Database saved. No more imports should be needed.") fmt.Println("It is advised to close and restart the node now, to free some mem.") }
func get_blocks() { var bl *btc.Block BlocksInProgress = make(map[[32]byte]*one_bip) BlocksCached = make(map[uint32]*btc.Block) //fmt.Println("opening connections") DlStartTime = time.Now() BlocksComplete = TheBlockChain.BlockTreeEnd.Height BlocksIndex = BlocksComplete SetDoBlocks(true) ct := time.Now().Unix() lastdrop := ct laststat := ct TheBlockChain.DoNotSync = true var blks2do []*btc.Block for GetDoBlocks() { BlocksMutex.Lock() if BlocksComplete >= LastBlockHeight { BlocksMutex.Unlock() break } for { bl = BlocksCached[BlocksComplete+1] if bl == nil { break } BlocksComplete++ if BlocksComplete > BlocksIndex { BlocksIndex = BlocksComplete } bl.Trusted = BlocksComplete <= TrustUpTo if OnlyStoreBlocks { TheBlockChain.Blocks.BlockAdd(BlocksComplete, bl) } else { blks2do = append(blks2do, bl) } atomic.AddUint64(&DlBytesProcesses, uint64(len(bl.Raw))) delete(BlocksCached, BlocksComplete) BlocksCachedSize -= uint(len(bl.Raw)) } BlocksMutex.Unlock() if len(blks2do) > 0 { for idx := range blks2do { er, _, _ := TheBlockChain.CheckBlock(blks2do[idx]) if er != nil { fmt.Println(er.Error()) return } blks2do[idx].LastKnownHeight = BlocksComplete TheBlockChain.AcceptBlock(blks2do[idx]) } blks2do = nil } else { TheBlockChain.Unspent.Idle() COUNTER("IDLE") } time.Sleep(1e8) ct = time.Now().Unix() if open_connection_count() > MaxNetworkConns { drop_slowest_peers() } else { // drop slowest peers once for awhile occ := MaxNetworkConns if occ > 0 { occ = 1200 / occ // For 20 open connections: drop one per minute if occ < 3 { occ = 3 // .. drop not more often then once sper 3 seconds } if ct-lastdrop > int64(occ) { lastdrop = ct drop_slowest_peers() } } } add_new_connections() if ct-laststat >= 5 { laststat = ct print_stats() usif_prompt() } } }
func import_blockchain(dir string) { trust := !ask_yes_no("Go you want to verify scripts while importing (will be slow)?") BlockDatabase := blockdb.NewBlockDB(dir, Magic) chain := btc.NewChain(GocoinHomeDir, GenesisBlock, false) var bl *btc.Block var er error var dat []byte var totbytes uint64 chain.DoNotSync = true fmt.Println("Be patient while importing Satoshi's database... ") start := time.Now().UnixNano() prv := start for { now := time.Now().UnixNano() if now-prv >= 10e9 { prv = now // show progress each 10 seconds stat(now-start, totbytes, chain.BlockTreeEnd.Height) } dat, er = BlockDatabase.FetchNextBlock() if dat == nil || er != nil { println("END of DB file") break } bl, er = btc.NewBlock(dat[:]) if er != nil { println("Block inconsistent:", er.Error()) break } bl.Trusted = trust er, _, _ = chain.CheckBlock(bl) if er != nil { println("CheckBlock failed:", er.Error()) continue } er = chain.AcceptBlock(bl) if er != nil { println("AcceptBlock failed:", er.Error()) continue } totbytes += uint64(len(bl.Raw)) } stop := time.Now().UnixNano() stat(stop-start, totbytes, chain.BlockTreeEnd.Height) fmt.Println("Satoshi's database import finished in", (stop-start)/1e9, "seconds") fmt.Println("Now saving the new database...") chain.Sync() chain.Close() fmt.Println("Database saved. No more imports should be needed.") }