diff --git a/blockdag/accept.go b/blockdag/accept.go index 84812424d..dd0923ad6 100644 --- a/blockdag/accept.go +++ b/blockdag/accept.go @@ -28,13 +28,13 @@ func (dag *BlockDAG) maybeAcceptBlock(block *util.Block, flags BehaviorFlags) er return err } - selectedParent := parents.first() //TODO (Ori): This is wrong, done only for compilation + bluestParent := parents.bluest() blockHeight := parents.maxHeight() + 1 block.SetHeight(blockHeight) // The block must pass all of the validation rules which depend on the // position of the block within the block DAG. - err = dag.checkBlockContext(block, parents, selectedParent, flags) + err = dag.checkBlockContext(block, parents, bluestParent, flags) if err != nil { return err } diff --git a/blockdag/blockset.go b/blockdag/blockset.go index 8a0506f29..9d48f2a6b 100644 --- a/blockdag/blockset.go +++ b/blockdag/blockset.go @@ -125,15 +125,6 @@ func (bs blockSet) hashes() []daghash.Hash { return hashes } -// first returns the first block in this set or nil if this set is empty. -func (bs blockSet) first() *blockNode { //TODO: (Ori) This is wrong. Done only for compilation. We should probably get rid of this method - for _, block := range bs { - return block - } - - return nil -} - func (bs blockSet) String() string { nodeStrs := make([]string, 0, len(bs)) for _, node := range bs { @@ -152,3 +143,17 @@ func (bs blockSet) anyChildInSet(block *blockNode) bool { return false } + +func (bs blockSet) bluest() *blockNode { + var bluestNode *blockNode + var maxScore uint64 + for _, node := range bs { + if bluestNode == nil || + node.blueScore > maxScore || + (node.blueScore == maxScore && daghash.Less(&bluestNode.hash, &node.hash)) { + bluestNode = node + maxScore = node.blueScore + } + } + return bluestNode +} diff --git a/blockdag/validate.go b/blockdag/validate.go index b398160e2..70f4f1f66 100644 --- a/blockdag/validate.go +++ b/blockdag/validate.go @@ -624,13 +624,13 @@ func checkSerializedHeight(coinbaseTx *util.Tx, wantHeight int32) error { // the checkpoints are not performed. // // This function MUST be called with the chain state lock held (for writes). -func (dag *BlockDAG) checkBlockHeaderContext(header *wire.BlockHeader, selectedParent *blockNode, blockHeight int32, flags BehaviorFlags) error { +func (dag *BlockDAG) checkBlockHeaderContext(header *wire.BlockHeader, bluestParent *blockNode, blockHeight int32, flags BehaviorFlags) error { fastAdd := flags&BFFastAdd == BFFastAdd if !fastAdd { // Ensure the difficulty specified in the block header matches // the calculated difficulty based on the previous block and // difficulty retarget rules. - expectedDifficulty, err := dag.calcNextRequiredDifficulty(selectedParent, + expectedDifficulty, err := dag.calcNextRequiredDifficulty(bluestParent, header.Timestamp) if err != nil { return err @@ -644,7 +644,7 @@ func (dag *BlockDAG) checkBlockHeaderContext(header *wire.BlockHeader, selectedP // Ensure the timestamp for the block header is after the // median time of the last several blocks (medianTimeBlocks). - medianTime := selectedParent.CalcPastMedianTime() + medianTime := bluestParent.CalcPastMedianTime() if !header.Timestamp.After(medianTime) { str := "block timestamp of %v is not after expected %v" str = fmt.Sprintf(str, header.Timestamp, medianTime) @@ -725,21 +725,22 @@ func validateParents(blockHeader *wire.BlockHeader, parents blockSet) error { // for how the flags modify its behavior. // // This function MUST be called with the chain state lock held (for writes). -func (dag *BlockDAG) checkBlockContext(block *util.Block, parents blockSet, selectedParent *blockNode, flags BehaviorFlags) error { +func (dag *BlockDAG) checkBlockContext(block *util.Block, parents blockSet, bluestParent *blockNode, flags BehaviorFlags) error { err := validateParents(&block.MsgBlock().Header, parents) if err != nil { return err } + // Perform all block header related validation checks. header := &block.MsgBlock().Header - err = dag.checkBlockHeaderContext(header, selectedParent, block.Height(), flags) + err = dag.checkBlockHeaderContext(header, bluestParent, block.Height(), flags) if err != nil { return err } fastAdd := flags&BFFastAdd == BFFastAdd if !fastAdd { - blockTime := selectedParent.CalcPastMedianTime() + blockTime := bluestParent.CalcPastMedianTime() // Ensure all transactions in the block are finalized. for _, tx := range block.Transactions() {