本文整理汇总了Golang中github.com/piotrnar/gocoin/lib/btc.Block类的典型用法代码示例。如果您正苦于以下问题:Golang Block类的具体用法?Golang Block怎么用?Golang Block使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了Block类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Golang代码示例。
示例1: AcceptBlock
// 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: get_blocks
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: AcceptHeader
// Make sure to call this function with ch.BlockIndexAccess locked
func (ch *Chain) AcceptHeader(bl *btc.Block) (cur *BlockTreeNode) {
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
copy(cur.BlockHeader[:], bl.Raw[:80])
// Add this block to the block index
prevblk.addChild(cur)
ch.BlockIndex[cur.BlockHash.BIdx()] = cur
return
}
示例4: chkblock
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
}
MemBlockChainMutex.Lock()
if prv, pres := MemBlockChain.BlockIndex[bl.Hash.BIdx()]; pres {
MemBlockChainMutex.Unlock()
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 {
MemBlockChainMutex.Unlock()
er = errors.New(fmt.Sprint("CheckBlock: Incorrect proof of work at block", prevblk.Height+1))
return
}
}
cur := new(chain.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
MemBlockChainMutex.Unlock()
LastBlock.Mutex.Lock()
if cur.Height > LastBlock.node.Height {
LastBlock.node = cur
}
LastBlock.Mutex.Unlock()
return
}
示例5: CommitBlock
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
}
示例6: commitTxs
// This isusually the most time consuming process when applying a new block
func (ch *Chain) commitTxs(bl *btc.Block, changes *BlockChanges) (e error) {
sumblockin := btc.GetBlockReward(changes.Height)
var txoutsum, txinsum, sumblockout uint64
// Add each tx outs from the current block to the temporary pool
blUnsp := make(map[[32]byte][]*btc.TxOut, len(bl.Txs))
for i := range bl.Txs {
outs := make([]*btc.TxOut, len(bl.Txs[i].TxOut))
for j := range bl.Txs[i].TxOut {
bl.Txs[i].TxOut[j].BlockHeight = changes.Height
outs[j] = bl.Txs[i].TxOut[j]
}
blUnsp[bl.Txs[i].Hash.Hash] = outs
}
// create a channnel to receive results from VerifyScript threads:
done := make(chan bool, sys.UseThreads)
for i := range bl.Txs {
txoutsum, txinsum = 0, 0
// Check each tx for a valid input, except from the first one
if i > 0 {
tx_trusted := bl.Trusted
if !tx_trusted && TrustedTxChecker != nil && TrustedTxChecker(bl.Txs[i].Hash) {
tx_trusted = true
}
scripts_ok := true
for j := 0; j < sys.UseThreads; j++ {
done <- true
}
for j := 0; j < len(bl.Txs[i].TxIn); /*&& e==nil*/ j++ {
inp := &bl.Txs[i].TxIn[j].Input
if _, ok := changes.DeledTxs[*inp]; ok {
println("txin", inp.String(), "already spent in this block")
e = errors.New("Input spent more then once in same block")
break
}
tout := ch.PickUnspent(inp)
if tout == nil {
t, ok := blUnsp[inp.Hash]
if !ok {
e = errors.New("Unknown input TxID: " + btc.NewUint256(inp.Hash[:]).String())
break
}
if inp.Vout >= uint32(len(t)) {
println("Vout too big", len(t), inp.String())
e = errors.New("Vout too big")
break
}
if t[inp.Vout] == nil {
println("Vout already spent", inp.String())
e = errors.New("Vout already spent")
break
}
tout = t[inp.Vout]
t[inp.Vout] = nil // and now mark it as spent:
}
if !(<-done) {
println("VerifyScript error 1")
scripts_ok = false
break
}
if tx_trusted {
done <- true
} else {
go func(sig []byte, prv []byte, i int, tx *btc.Tx) {
done <- script.VerifyTxScript(sig, prv, i, tx, bl.BlockTime() >= BIP16SwitchTime)
}(bl.Txs[i].TxIn[j].ScriptSig, tout.Pk_script, j, bl.Txs[i])
}
// Verify Transaction script:
txinsum += tout.Value
changes.DeledTxs[*inp] = tout
}
if scripts_ok {
scripts_ok = <-done
}
for j := 1; j < sys.UseThreads; j++ {
if !(<-done) {
println("VerifyScript error 2")
scripts_ok = false
}
}
if len(done) != 0 {
panic("ASSERT: The channel should be empty gere")
}
if !scripts_ok {
return errors.New("VerifyScripts failed")
//.........这里部分代码省略.........
示例7: commitTxs
// This isusually the most time consuming process when applying a new block
func (ch *Chain) commitTxs(bl *btc.Block, changes *BlockChanges) (e error) {
sumblockin := btc.GetBlockReward(changes.Height)
var txoutsum, txinsum, sumblockout uint64
if int(changes.Height)+UnwindBufferMaxHistory >= int(changes.LastKnownHeight) {
changes.UndoData = make(map[[32]byte]*QdbRec)
}
// Add each tx outs from the current block to the temporary pool
blUnsp := make(map[[32]byte][]*btc.TxOut, 4*len(bl.Txs))
for i := range bl.Txs {
outs := make([]*btc.TxOut, len(bl.Txs[i].TxOut))
copy(outs, bl.Txs[i].TxOut)
blUnsp[bl.Txs[i].Hash.Hash] = outs
}
// create a channnel to receive results from VerifyScript threads:
done := make(chan bool, sys.UseThreads)
now := changes.Height == 381 && false
//println("pr", changes.Height)
for i := range bl.Txs {
txoutsum, txinsum = 0, 0
// Check each tx for a valid input, except from the first one
if i > 0 {
tx_trusted := bl.Trusted
if !tx_trusted && TrustedTxChecker != nil && TrustedTxChecker(bl.Txs[i].Hash) {
tx_trusted = true
}
scripts_ok := true
for j := 0; j < sys.UseThreads; j++ {
done <- true
}
for j := 0; j < len(bl.Txs[i].TxIn); /*&& e==nil*/ j++ {
inp := &bl.Txs[i].TxIn[j].Input
spendrec, waspent := changes.DeledTxs[inp.Hash]
if waspent && spendrec[inp.Vout] {
println("txin", inp.String(), "already spent in this block")
e = errors.New("Input spent more then once in same block")
break
}
tout := ch.PickUnspent(inp)
if tout == nil {
t, ok := blUnsp[inp.Hash]
if !ok {
e = errors.New("Unknown input TxID: " + btc.NewUint256(inp.Hash[:]).String())
break
}
if inp.Vout >= uint32(len(t)) {
println("Vout too big", len(t), inp.String())
e = errors.New("Vout too big")
break
}
if t[inp.Vout] == nil {
println("Vout already spent", inp.String())
e = errors.New("Vout already spent")
break
}
if t[inp.Vout].WasCoinbase {
e = errors.New("Cannot spend block's own coinbase in TxID: " + btc.NewUint256(inp.Hash[:]).String())
break
}
tout = t[inp.Vout]
t[inp.Vout] = nil // and now mark it as spent:
} else {
if tout.WasCoinbase && changes.Height-tout.BlockHeight < COINBASE_MATURITY {
e = errors.New("Trying to spend prematured coinbase: " + btc.NewUint256(inp.Hash[:]).String())
break
}
// it is confirmed already so delete it later
if !waspent {
spendrec = make([]bool, tout.VoutCount)
changes.DeledTxs[inp.Hash] = spendrec
}
spendrec[inp.Vout] = true
if changes.UndoData != nil {
var urec *QdbRec
urec = changes.UndoData[inp.Hash]
if urec == nil {
urec = new(QdbRec)
urec.TxID = inp.Hash
urec.Coinbase = tout.WasCoinbase
urec.InBlock = tout.BlockHeight
urec.Outs = make([]*QdbTxOut, tout.VoutCount)
changes.UndoData[inp.Hash] = urec
}
tmp := new(QdbTxOut)
tmp.Value = tout.Value
tmp.PKScr = make([]byte, len(tout.Pk_script))
//.........这里部分代码省略.........
示例8: commitTxs
// This isusually the most time consuming process when applying a new block
func (ch *Chain) commitTxs(bl *btc.Block, changes *BlockChanges) (e error) {
sumblockin := btc.GetBlockReward(changes.Height)
var txoutsum, txinsum, sumblockout uint64
if changes.Height+ch.Unspent.UnwindBufLen >= changes.LastKnownHeight {
changes.UndoData = make(map[[32]byte]*QdbRec)
}
blUnsp := make(map[[32]byte][]*btc.TxOut, 4*len(bl.Txs))
var wg sync.WaitGroup
var ver_err_cnt uint32
for i := range bl.Txs {
txoutsum, txinsum = 0, 0
bl.SigopsCost += uint32(btc.WITNESS_SCALE_FACTOR * bl.Txs[i].GetLegacySigOpCount())
// Check each tx for a valid input, except from the first one
if i > 0 {
tx_trusted := bl.Trusted
if !tx_trusted && TrustedTxChecker != nil && TrustedTxChecker(bl.Txs[i].Hash) {
tx_trusted = true
}
for j := 0; j < len(bl.Txs[i].TxIn); j++ {
inp := &bl.Txs[i].TxIn[j].Input
spendrec, waspent := changes.DeledTxs[inp.Hash]
if waspent && spendrec[inp.Vout] {
println("txin", inp.String(), "already spent in this block")
e = errors.New("Input spent more then once in same block")
return
}
tout := ch.PickUnspent(inp)
if tout == nil {
t, ok := blUnsp[inp.Hash]
if !ok {
e = errors.New("Unknown input TxID: " + btc.NewUint256(inp.Hash[:]).String())
return
}
if inp.Vout >= uint32(len(t)) {
println("Vout too big", len(t), inp.String())
e = errors.New("Vout too big")
return
}
if t[inp.Vout] == nil {
println("Vout already spent", inp.String())
e = errors.New("Vout already spent")
return
}
if t[inp.Vout].WasCoinbase {
e = errors.New("Cannot spend block's own coinbase in TxID: " + btc.NewUint256(inp.Hash[:]).String())
return
}
tout = t[inp.Vout]
t[inp.Vout] = nil // and now mark it as spent:
} else {
if tout.WasCoinbase && changes.Height-tout.BlockHeight < COINBASE_MATURITY {
e = errors.New("Trying to spend prematured coinbase: " + btc.NewUint256(inp.Hash[:]).String())
return
}
// it is confirmed already so delete it later
if !waspent {
spendrec = make([]bool, tout.VoutCount)
changes.DeledTxs[inp.Hash] = spendrec
}
spendrec[inp.Vout] = true
if changes.UndoData != nil {
var urec *QdbRec
urec = changes.UndoData[inp.Hash]
if urec == nil {
urec = new(QdbRec)
urec.TxID = inp.Hash
urec.Coinbase = tout.WasCoinbase
urec.InBlock = tout.BlockHeight
urec.Outs = make([]*QdbTxOut, tout.VoutCount)
changes.UndoData[inp.Hash] = urec
}
tmp := new(QdbTxOut)
tmp.Value = tout.Value
tmp.PKScr = make([]byte, len(tout.Pk_script))
copy(tmp.PKScr, tout.Pk_script)
urec.Outs[inp.Vout] = tmp
}
}
if !tx_trusted { // run VerifyTxScript() in a parallel task
wg.Add(1)
go func(prv []byte, amount uint64, i int, tx *btc.Tx) {
if !script.VerifyTxScript(prv, amount, i, tx, bl.VerifyFlags) {
atomic.AddUint32(&ver_err_cnt, 1)
}
wg.Done()
}(tout.Pk_script, tout.Value, j, bl.Txs[i])
//.........这里部分代码省略.........
示例9: LocalAcceptBlock
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])
/*
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.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(), 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
}
示例10: CheckBlock
func (ch *Chain) CheckBlock(bl *btc.Block) (er error, dos bool, maybelater bool) {
// Size limits
if len(bl.Raw) < 81 || len(bl.Raw) > btc.MAX_BLOCK_SIZE {
er = errors.New("CheckBlock() : size limits failed")
dos = true
return
}
// 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")
dos = true
return
}
if prv, pres := ch.BlockIndex[bl.Hash.BIdx()]; pres {
if prv.Parent == nil {
// This is genesis block
er = errors.New("Genesis")
return
} else {
er = errors.New("CheckBlock: " + bl.Hash.String() + " already in")
return
}
}
prevblk, ok := ch.BlockIndex[btc.NewUint256(bl.ParentHash()).BIdx()]
if !ok {
er = errors.New("CheckBlock: " + bl.Hash.String() + " parent not found")
maybelater = true
return
}
// Reject the block if it reaches into the chain deeper than our unwind buffer
if prevblk != ch.BlockTreeEnd && int(ch.BlockTreeEnd.Height)-int(prevblk.Height+1) >= MovingCheckopintDepth {
er = errors.New(fmt.Sprint("CheckBlock: btc.Block ", bl.Hash.String(),
" hooks too deep into the chain: ", prevblk.Height+1, "/", ch.BlockTreeEnd.Height, " ",
btc.NewUint256(bl.ParentHash()).String()))
return
}
// Check proof of work
gnwr := ch.GetNextWorkRequired(prevblk, bl.BlockTime())
if bl.Bits() != gnwr {
println("AcceptBlock() : incorrect proof of work ", bl.Bits, " at block", prevblk.Height+1,
" exp:", gnwr)
// Here is a "solution" for whatever shit there is in testnet3, that nobody can explain me:
if !ch.testnet() || ((prevblk.Height+1)%2016) != 0 {
er = errors.New("CheckBlock: incorrect proof of work")
dos = true
return
}
}
if bl.Txs == nil {
er = bl.BuildTxList()
if er != nil {
dos = true
return
}
}
if !bl.Trusted {
// This is a stupid check, but well, we need to be satoshi compatible
if len(bl.Txs) == 0 || !bl.Txs[0].IsCoinBase() {
er = errors.New("CheckBlock() : first tx is not coinbase: " + bl.Hash.String())
dos = true
return
}
// Check Merkle Root - that's importnant
if !bytes.Equal(btc.GetMerkel(bl.Txs), bl.MerkleRoot()) {
er = errors.New("CheckBlock() : Merkle Root mismatch")
dos = true
return
}
// Check transactions - this is the most time consuming task
for i := 0; i < len(bl.Txs); i++ {
er = bl.Txs[i].CheckTransaction()
if er != nil {
er = errors.New("CheckBlock() : CheckTransaction failed: " + er.Error())
dos = true
return
}
if !bl.Txs[i].IsFinal(prevblk.Height+1, bl.BlockTime()) {
er = errors.New("CheckBlock() : Contains transaction that is not final")
return
}
}
}
return
}
示例11: CheckBlock
func (ch *Chain) CheckBlock(bl *btc.Block) (er error, dos bool, maybelater bool) {
// Size limits
if len(bl.Raw) < 81 || len(bl.Raw) > btc.MAX_BLOCK_SIZE {
er = errors.New("CheckBlock() : size limits failed")
dos = true
return
}
if bl.Version() == 0 {
er = errors.New("CheckBlock() : Block version 0 not allowed")
dos = true
return
}
// 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")
dos = true
return
}
if prv, pres := ch.BlockIndex[bl.Hash.BIdx()]; pres {
if prv.Parent == nil {
// This is genesis block
er = errors.New("Genesis")
return
} else {
er = errors.New("CheckBlock: " + bl.Hash.String() + " already in")
return
}
}
prevblk, ok := ch.BlockIndex[btc.NewUint256(bl.ParentHash()).BIdx()]
if !ok {
er = errors.New("CheckBlock: " + bl.Hash.String() + " parent not found")
maybelater = true
return
}
height := prevblk.Height + 1
// Reject the block if it reaches into the chain deeper than our unwind buffer
if prevblk != ch.BlockTreeEnd && int(ch.BlockTreeEnd.Height)-int(height) >= MovingCheckopintDepth {
er = errors.New(fmt.Sprint("CheckBlock: btc.Block ", bl.Hash.String(),
" hooks too deep into the chain: ", height, "/", ch.BlockTreeEnd.Height, " ",
btc.NewUint256(bl.ParentHash()).String()))
return
}
// Check proof of work
gnwr := ch.GetNextWorkRequired(prevblk, bl.BlockTime())
if bl.Bits() != gnwr {
println("AcceptBlock() : incorrect proof of work ", bl.Bits, " at block", height, " exp:", gnwr)
// Here is a "solution" for whatever shit there is in testnet3, that nobody can explain me:
if !ch.testnet() || (height%2016) != 0 {
er = errors.New("CheckBlock: incorrect proof of work")
dos = true
return
}
}
// Count block versions within the Majority Window
var majority_v2, majority_v3 uint
n := prevblk
for cnt := uint(0); cnt < ch.Consensus.Window && n != nil; cnt++ {
ver := binary.LittleEndian.Uint32(n.BlockHeader[0:4])
if ver >= 2 {
majority_v2++
if ver >= 3 {
majority_v3++
}
}
n = n.Parent
}
if bl.Version() < 2 && majority_v2 >= ch.Consensus.RejectBlock {
er = errors.New("CheckBlock() : Rejected nVersion=1 block")
dos = true
return
}
if bl.Version() < 3 && majority_v3 >= ch.Consensus.RejectBlock {
er = errors.New("CheckBlock() : Rejected nVersion=2 block")
dos = true
return
}
if bl.Txs == nil {
er = bl.BuildTxList()
if er != nil {
dos = true
return
}
}
if !bl.Trusted {
if bl.Version() >= 2 && majority_v2 >= ch.Consensus.EnforceUpgrade {
var exp []byte
if height >= 0x800000 {
//.........这里部分代码省略.........
示例12: import_blockchain
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.")
}
示例13: PostCheckBlock
func (ch *Chain) PostCheckBlock(bl *btc.Block) (er error) {
// Size limits
if len(bl.Raw) < 81 {
er = errors.New("CheckBlock() : size limits failed low - RPC_Result:bad-blk-length")
return
}
if bl.Txs == nil {
er = bl.BuildTxList()
if er != nil {
return
}
if len(bl.OldData) > btc.MAX_BLOCK_SIZE {
er = errors.New("CheckBlock() : size limits failed high - RPC_Result:bad-blk-length")
return
}
}
if !bl.Trusted {
// We need to be satoshi compatible
if len(bl.Txs) == 0 || !bl.Txs[0].IsCoinBase() {
er = errors.New("CheckBlock() : first tx is not coinbase: " + bl.Hash.String() + " - RPC_Result:bad-cb-missing")
return
}
// Enforce rule that the coinbase starts with serialized block height
if bl.Height >= ch.Consensus.BIP34Height {
var exp [6]byte
var exp_len int
binary.LittleEndian.PutUint32(exp[1:5], bl.Height)
for exp_len = 5; exp_len > 1; exp_len-- {
if exp[exp_len] != 0 || exp[exp_len-1] >= 0x80 {
break
}
}
exp[0] = byte(exp_len)
exp_len++
if !bytes.HasPrefix(bl.Txs[0].TxIn[0].ScriptSig, exp[:exp_len]) {
er = errors.New("CheckBlock() : Unexpected block number in coinbase: " + bl.Hash.String() + " - RPC_Result:bad-cb-height")
return
}
}
// And again...
for i := 1; i < len(bl.Txs); i++ {
if bl.Txs[i].IsCoinBase() {
er = errors.New("CheckBlock() : more than one coinbase: " + bl.Hash.String() + " - RPC_Result:bad-cb-multiple")
return
}
}
// Check Merkle Root - that's importnant
merkle, mutated := btc.GetMerkle(bl.Txs)
if mutated {
er = errors.New("CheckBlock(): duplicate transaction - RPC_Result:bad-txns-duplicate")
return
}
if !bytes.Equal(merkle, bl.MerkleRoot()) {
er = errors.New("CheckBlock() : Merkle Root mismatch - RPC_Result:bad-txnmrklroot")
return
}
}
if bl.BlockTime() >= BIP16SwitchTime {
bl.VerifyFlags = script.VER_P2SH
} else {
bl.VerifyFlags = 0
}
if bl.Height >= ch.Consensus.BIP66Height {
bl.VerifyFlags |= script.VER_DERSIG
}
if bl.Height >= ch.Consensus.BIP65Height {
bl.VerifyFlags |= script.VER_CLTV
}
if ch.Consensus.Enforce_CSV != 0 && bl.Height >= ch.Consensus.Enforce_CSV {
bl.VerifyFlags |= script.VER_CSV
}
if ch.Consensus.Enforce_SEGWIT != 0 && bl.Height >= ch.Consensus.Enforce_SEGWIT {
bl.VerifyFlags |= script.VER_WITNESS | script.VER_NULLDUMMY
}
if !bl.Trusted {
var blockTime uint32
var had_witness bool
if (bl.VerifyFlags & script.VER_CSV) != 0 {
blockTime = bl.MedianPastTime
} else {
blockTime = bl.BlockTime()
}
// Verify merkle root of witness data
if (bl.VerifyFlags & script.VER_WITNESS) != 0 {
var i int
//.........这里部分代码省略.........
示例14: PreCheckBlock
func (ch *Chain) PreCheckBlock(bl *btc.Block) (er error, dos bool, maybelater bool) {
// Size limits
if len(bl.Raw) < 81 {
er = errors.New("CheckBlock() : size limits failed - RPC_Result:bad-blk-length")
dos = true
return
}
if bl.Version() == 0 {
er = errors.New("CheckBlock() : Block version 0 not allowed - RPC_Result:bad-version")
dos = true
return
}
// Check proof-of-work
if !btc.CheckProofOfWork(bl.Hash, bl.Bits()) {
er = errors.New("CheckBlock() : proof of work failed - RPC_Result:high-hash")
dos = true
return
}
// 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 - RPC_Result:time-too-new")
dos = true
return
}
if prv, pres := ch.BlockIndex[bl.Hash.BIdx()]; pres {
if prv.Parent == nil {
// This is genesis block
er = errors.New("Genesis")
return
} else {
er = errors.New("CheckBlock: " + bl.Hash.String() + " already in - RPC_Result:duplicate")
return
}
}
prevblk, ok := ch.BlockIndex[btc.NewUint256(bl.ParentHash()).BIdx()]
if !ok {
er = errors.New("CheckBlock: " + bl.Hash.String() + " parent not found - RPC_Result:bad-prevblk")
maybelater = true
return
}
bl.Height = prevblk.Height + 1
// Reject the block if it reaches into the chain deeper than our unwind buffer
if prevblk != ch.BlockTreeEnd && int(ch.BlockTreeEnd.Height)-int(bl.Height) >= MovingCheckopintDepth {
er = errors.New(fmt.Sprint("CheckBlock: btc.Block ", bl.Hash.String(),
" hooks too deep into the chain: ", bl.Height, "/", ch.BlockTreeEnd.Height, " ",
btc.NewUint256(bl.ParentHash()).String(), " - RPC_Result:bad-prevblk"))
return
}
// Check proof of work
gnwr := ch.GetNextWorkRequired(prevblk, bl.BlockTime())
if bl.Bits() != gnwr {
er = errors.New("CheckBlock: incorrect proof of work - RPC_Result:bad-diffbits")
dos = true
return
}
// Check timestamp against prev
bl.MedianPastTime = prevblk.GetMedianTimePast()
if bl.BlockTime() <= bl.MedianPastTime {
er = errors.New("CheckBlock: block's timestamp is too early - RPC_Result:time-too-old")
dos = true
return
}
if bl.Version() < 2 && bl.Height >= ch.Consensus.BIP34Height ||
bl.Version() < 3 && bl.Height >= ch.Consensus.BIP66Height ||
bl.Version() < 4 && bl.Height >= ch.Consensus.BIP65Height {
// bad block version
erstr := fmt.Sprintf("0x%08x", bl.Version())
er = errors.New("CheckBlock() : Rejected Version=" + erstr + " blolck - RPC_Result:bad-version(" + erstr + ")")
dos = true
return
}
return
}
示例15: get_blocks
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()
}
}
}