github.com/dashpay/godash@v0.0.0-20160726055534-e038a21e0e3d/blockchain/accept.go (about) 1 // Copyright (c) 2013-2016 The btcsuite developers 2 // Copyright (c) 2016 The Dash developers 3 // Use of this source code is governed by an ISC 4 // license that can be found in the LICENSE file. 5 6 package blockchain 7 8 import "github.com/dashpay/godashutil" 9 10 // maybeAcceptBlock potentially accepts a block into the memory block chain. 11 // It performs several validation checks which depend on its position within 12 // the block chain before adding it. The block is expected to have already gone 13 // through ProcessBlock before calling this function with it. 14 // 15 // The flags modify the behavior of this function as follows: 16 // - BFDryRun: The memory chain index will not be pruned and no accept 17 // notification will be sent since the block is not being accepted. 18 // 19 // The flags are also passed to checkBlockContext and connectBestChain. See 20 // their documentation for how the flags modify their behavior. 21 // 22 // This function MUST be called with the chain state lock held (for writes). 23 func (b *BlockChain) maybeAcceptBlock(block *godashutil.Block, flags BehaviorFlags) error { 24 dryRun := flags&BFDryRun == BFDryRun 25 26 // Get a block node for the block previous to this one. Will be nil 27 // if this is the genesis block. 28 prevNode, err := b.getPrevNodeFromBlock(block) 29 if err != nil { 30 log.Errorf("getPrevNodeFromBlock: %v", err) 31 return err 32 } 33 34 // The height of this block is one more than the referenced previous 35 // block. 36 blockHeight := int32(0) 37 if prevNode != nil { 38 blockHeight = prevNode.height + 1 39 } 40 block.SetHeight(blockHeight) 41 42 // The block must pass all of the validation rules which depend on the 43 // position of the block within the block chain. 44 err = b.checkBlockContext(block, prevNode, flags) 45 if err != nil { 46 return err 47 } 48 49 // Prune block nodes which are no longer needed before creating 50 // a new node. 51 if !dryRun { 52 err = b.pruneBlockNodes() 53 if err != nil { 54 return err 55 } 56 } 57 58 // Create a new block node for the block and add it to the in-memory 59 // block chain (could be either a side chain or the main chain). 60 blockHeader := &block.MsgBlock().Header 61 newNode := newBlockNode(blockHeader, block.Sha(), blockHeight) 62 if prevNode != nil { 63 newNode.parent = prevNode 64 newNode.height = blockHeight 65 newNode.workSum.Add(prevNode.workSum, newNode.workSum) 66 } 67 68 // Connect the passed block to the chain while respecting proper chain 69 // selection according to the chain with the most proof of work. This 70 // also handles validation of the transaction scripts. 71 err = b.connectBestChain(newNode, block, flags) 72 if err != nil { 73 return err 74 } 75 76 // Notify the caller that the new block was accepted into the block 77 // chain. The caller would typically want to react by relaying the 78 // inventory to other peers. 79 if !dryRun { 80 b.chainLock.Unlock() 81 b.sendNotification(NTBlockAccepted, block) 82 b.chainLock.Lock() 83 } 84 85 return nil 86 }