2015-08-26 06:03:18 +02:00
|
|
|
// Copyright (c) 2013-2016 The btcsuite developers
|
2013-07-18 16:49:28 +02:00
|
|
|
// Use of this source code is governed by an ISC
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2015-01-30 21:54:30 +01:00
|
|
|
package blockchain
|
2013-07-18 16:49:28 +02:00
|
|
|
|
2015-04-19 20:34:42 +02:00
|
|
|
import "github.com/btcsuite/btcutil"
|
2013-07-18 16:49:28 +02:00
|
|
|
|
|
|
|
// maybeAcceptBlock potentially accepts a block into the memory block chain.
|
|
|
|
// It performs several validation checks which depend on its position within
|
|
|
|
// the block chain before adding it. The block is expected to have already gone
|
|
|
|
// through ProcessBlock before calling this function with it.
|
2014-06-26 22:50:13 +02:00
|
|
|
//
|
|
|
|
// The flags modify the behavior of this function as follows:
|
2014-06-29 22:11:13 +02:00
|
|
|
// - BFDryRun: The memory chain index will not be pruned and no accept
|
|
|
|
// notification will be sent since the block is not being accepted.
|
2015-04-19 20:34:42 +02:00
|
|
|
//
|
|
|
|
// The flags are also passed to checkBlockContext and connectBestChain. See
|
|
|
|
// their documentation for how the flags modify their behavior.
|
2015-08-26 06:03:18 +02:00
|
|
|
//
|
|
|
|
// This function MUST be called with the chain state lock held (for writes).
|
2014-06-26 22:50:13 +02:00
|
|
|
func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block, flags BehaviorFlags) error {
|
2014-06-29 22:11:13 +02:00
|
|
|
dryRun := flags&BFDryRun == BFDryRun
|
2014-06-26 22:50:13 +02:00
|
|
|
|
2013-07-18 16:49:28 +02:00
|
|
|
// Get a block node for the block previous to this one. Will be nil
|
|
|
|
// if this is the genesis block.
|
|
|
|
prevNode, err := b.getPrevNodeFromBlock(block)
|
|
|
|
if err != nil {
|
2013-07-24 19:31:14 +02:00
|
|
|
log.Errorf("getPrevNodeFromBlock: %v", err)
|
2013-07-18 16:49:28 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2013-10-11 17:24:13 +02:00
|
|
|
// The height of this block is one more than the referenced previous
|
|
|
|
// block.
|
2015-08-08 04:20:49 +02:00
|
|
|
blockHeight := int32(0)
|
2013-07-18 16:49:28 +02:00
|
|
|
if prevNode != nil {
|
|
|
|
blockHeight = prevNode.height + 1
|
|
|
|
}
|
2013-07-29 23:58:48 +02:00
|
|
|
block.SetHeight(blockHeight)
|
2013-07-18 16:49:28 +02:00
|
|
|
|
2015-04-19 20:34:42 +02:00
|
|
|
// The block must pass all of the validation rules which depend on the
|
|
|
|
// position of the block within the block chain.
|
|
|
|
err = b.checkBlockContext(block, prevNode, flags)
|
2014-02-21 20:02:59 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2013-07-18 16:49:28 +02:00
|
|
|
|
2014-01-28 20:45:49 +01:00
|
|
|
// Prune block nodes which are no longer needed before creating
|
|
|
|
// a new node.
|
2014-06-29 22:11:13 +02:00
|
|
|
if !dryRun {
|
|
|
|
err = b.pruneBlockNodes()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2013-08-01 18:31:42 +02:00
|
|
|
}
|
|
|
|
|
2013-07-18 16:49:28 +02:00
|
|
|
// Create a new block node for the block and add it to the in-memory
|
|
|
|
// block chain (could be either a side chain or the main chain).
|
2015-04-19 20:34:42 +02:00
|
|
|
blockHeader := &block.MsgBlock().Header
|
2016-08-08 21:04:33 +02:00
|
|
|
newNode := newBlockNode(blockHeader, block.Hash(), blockHeight)
|
2013-07-18 16:49:28 +02:00
|
|
|
if prevNode != nil {
|
|
|
|
newNode.parent = prevNode
|
|
|
|
newNode.height = blockHeight
|
|
|
|
newNode.workSum.Add(prevNode.workSum, newNode.workSum)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Connect the passed block to the chain while respecting proper chain
|
|
|
|
// selection according to the chain with the most proof of work. This
|
|
|
|
// also handles validation of the transaction scripts.
|
2014-06-26 22:50:13 +02:00
|
|
|
err = b.connectBestChain(newNode, block, flags)
|
2013-07-18 16:49:28 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Notify the caller that the new block was accepted into the block
|
|
|
|
// chain. The caller would typically want to react by relaying the
|
|
|
|
// inventory to other peers.
|
2014-06-29 22:11:13 +02:00
|
|
|
if !dryRun {
|
2015-08-26 06:03:18 +02:00
|
|
|
b.chainLock.Unlock()
|
2014-06-29 22:11:13 +02:00
|
|
|
b.sendNotification(NTBlockAccepted, block)
|
2015-08-26 06:03:18 +02:00
|
|
|
b.chainLock.Lock()
|
2014-06-29 22:11:13 +02:00
|
|
|
}
|
2013-07-18 16:49:28 +02:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|