示例#1
0
// This function either appends a new block at the end of the existing chain
// in which case it also applies all the transactions to the unspent database.
// If the block does is not the heighest, it is added to the chain, but maked
// as an orphan - its transaction will be verified only if the chain would swap
// to its branch later on.
func (ch *Chain) AcceptBlock(bl *btc.Block) (e error) {

	prevblk, ok := ch.BlockIndex[btc.NewUint256(bl.ParentHash()).BIdx()]
	if !ok {
		panic("This should not happen")
	}

	// create new BlockTreeNode
	cur := new(BlockTreeNode)
	cur.BlockHash = bl.Hash
	cur.Parent = prevblk
	cur.Height = prevblk.Height + 1
	cur.TxCount = uint32(bl.TxCount)
	copy(cur.BlockHeader[:], bl.Raw[:80])

	// Add this block to the block index
	ch.BlockIndexAccess.Lock()
	prevblk.addChild(cur)
	ch.BlockIndex[cur.BlockHash.BIdx()] = cur
	ch.BlockIndexAccess.Unlock()

	if ch.BlockTreeEnd == prevblk {
		// The head of out chain - apply the transactions
		var changes *BlockChanges
		changes, e = ch.ProcessBlockTransactions(bl, cur.Height)
		if e != nil {
			// ProcessBlockTransactions failed, so trash the block.
			println("ProcessBlockTransactions ", cur.BlockHash.String(), cur.Height, e.Error())
			ch.BlockIndexAccess.Lock()
			cur.Parent.delChild(cur)
			delete(ch.BlockIndex, cur.BlockHash.BIdx())
			ch.BlockIndexAccess.Unlock()
		} else {
			// ProcessBlockTransactions succeeded, so save the block as "trusted".
			bl.Trusted = true
			ch.Blocks.BlockAdd(cur.Height, bl)
			// Apply the block's trabnsactions to the unspent database:
			changes.LastKnownHeight = bl.LastKnownHeight
			ch.Unspent.CommitBlockTxs(changes, bl.Hash.Hash[:])
			if !ch.DoNotSync {
				ch.Blocks.Sync()
			}
			ch.BlockTreeEnd = cur // Advance the head
		}
	} else {
		// The block's parent is not the current head of the chain...

		// Save the block, though do not makt it as "trusted" just yet
		ch.Blocks.BlockAdd(cur.Height, bl)

		// If it has a bigger height than the current head,
		// ... move the coin state into a new branch.
		if cur.Height > ch.BlockTreeEnd.Height {
			ch.MoveToBlock(cur)
		}
	}

	return
}
示例#2
0
文件: blks.go 项目: rollyleal/gocoin
func get_blocks() {
	var bl *btc.Block

	DlStartTime = time.Now()
	BlocksMutex.Lock()
	BlocksComplete = TheBlockChain.BlockTreeEnd.Height
	CurrentBlockHeight := BlocksComplete + 1
	BlocksMutex.Unlock()

	TheBlockChain.DoNotSync = true

	tickSec := time.Tick(time.Second)
	tickDrop := time.Tick(DROP_PEER_EVERY_SEC * time.Second)
	tickStat := time.Tick(6 * time.Second)

	for !GlobalExit() && CurrentBlockHeight <= LastBlockHeight {
		select {
		case <-tickSec:
			cc := open_connection_count()
			if cc > MaxNetworkConns {
				drop_slowest_peers()
			} else if cc < MaxNetworkConns {
				add_new_connections()
			}

		case <-tickStat:
			print_stats()
			usif_prompt()

		case <-tickDrop:
			if open_connection_count() >= MaxNetworkConns {
				drop_slowest_peers()
			}

		case bl = <-BlockQueue:
			bl.Trusted = CurrentBlockHeight <= TrustUpTo
			if OnlyStoreBlocks {
				TheBlockChain.Blocks.BlockAdd(CurrentBlockHeight, bl)
			} else {
				er, _, _ := TheBlockChain.CheckBlock(bl)
				if er != nil {
					fmt.Println("CheckBlock:", er.Error())
					return
				} else {
					bl.LastKnownHeight = CurrentBlockHeight + uint32(len(BlockQueue))
					TheBlockChain.AcceptBlock(bl)
				}
			}
			atomic.StoreUint32(&LastStoredBlock, CurrentBlockHeight)
			atomic.AddUint64(&DlBytesProcessed, uint64(len(bl.Raw)))
			CurrentBlockHeight++

		case <-time.After(100 * time.Millisecond):
			COUNTER("IDLE")
			TheBlockChain.Unspent.Idle()
		}
	}
	TheBlockChain.Sync()
}
示例#3
0
func (ch *Chain) CommitBlock(bl *btc.Block, cur *BlockTreeNode) (e error) {
	cur.BlockSize = uint32(len(bl.Raw))
	cur.TxCount = uint32(bl.TxCount)
	if ch.BlockTreeEnd == cur.Parent {
		// The head of out chain - apply the transactions
		var changes *BlockChanges
		changes, e = ch.ProcessBlockTransactions(bl, cur.Height, bl.LastKnownHeight)
		if e != nil {
			// ProcessBlockTransactions failed, so trash the block.
			println("ProcessBlockTransactionsA", cur.BlockHash.String(), cur.Height, e.Error())
			ch.BlockIndexAccess.Lock()
			cur.Parent.delChild(cur)
			delete(ch.BlockIndex, cur.BlockHash.BIdx())
			ch.BlockIndexAccess.Unlock()
		} else {
			cur.SigopsCost = bl.SigopsCost
			// ProcessBlockTransactions succeeded, so save the block as "trusted".
			bl.Trusted = true
			ch.Blocks.BlockAdd(cur.Height, bl)
			// Apply the block's trabnsactions to the unspent database:
			ch.Unspent.CommitBlockTxs(changes, bl.Hash.Hash[:])
			if !ch.DoNotSync {
				ch.Blocks.Sync()
			}
			ch.BlockTreeEnd = cur // Advance the head
		}
	} else {
		// The block's parent is not the current head of the chain...

		// Save the block, though do not makt it as "trusted" just yet
		ch.Blocks.BlockAdd(cur.Height, bl)

		// If it has a bigger height than the current head,
		// ... move the coin state into a new branch.
		if cur.Height > ch.BlockTreeEnd.Height {
			ch.MoveToBlock(cur)
			if ch.BlockTreeEnd != cur {
				e = errors.New("CommitBlock: MoveToBlock failed")
			}
		}
	}

	return
}
示例#4
0
func import_blockchain(dir string) {
	BlockDatabase := blockdb.NewBlockDB(dir, Magic)
	chain := chain.NewChain(GocoinHomeDir, 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.Save()
	chain.Close()
	fmt.Println("Database saved. No more imports should be needed.")
}
示例#5
0
文件: blks.go 项目: vancsj/gocoin
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()
		}
	}
}