Beispiel #1
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
}
Beispiel #2
0
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
}
Beispiel #3
0
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.")
}
Beispiel #4
0
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()
		}
	}
}
Beispiel #5
0
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.")
}