// validHeader does some early, low computation verification on the block. func (cs *State) validHeader(b types.Block) error { // Grab the parent of the block and verify the ID of the child meets the // target. This is done as early as possible to enforce that any // block-related DoS must use blocks that have sufficient work. parent, exists := cs.blockMap[b.ParentID] if !exists { return ErrOrphan } if !b.CheckTarget(parent.childTarget) { return ErrMissedTarget } // Check that the block is below the size limit. if uint64(len(encoding.Marshal(b))) > types.BlockSizeLimit { return ErrLargeBlock } // Check that the timestamp is not in 'the past', where the past is defined // by earliestChildTimestamp. if parent.earliestChildTimestamp() > b.Timestamp { return ErrEarlyTimestamp } // If the block is in the extreme future, return an error and do nothing // more with the block. There is an assumption that by the time the extreme // future arrives, this block will no longer be a part of the longest fork // because it will have been ignored by all of the miners. if b.Timestamp > types.CurrentTimestamp()+types.ExtremeFutureThreshold { return ErrExtremeFutureTimestamp } // Verify that the miner payouts are valid. if !b.CheckMinerPayouts(parent.height + 1) { return ErrBadMinerPayouts } // If the block is in the near future, but too far to be acceptable, then // the block will be saved and added to the consensus set after it is no // longer too far in the future. This is the last check because it's an // expensive check, and not worth performing if the payouts are incorrect. if b.Timestamp > types.CurrentTimestamp()+types.FutureThreshold { go func() { time.Sleep(time.Duration(b.Timestamp-(types.CurrentTimestamp()+types.FutureThreshold)) * time.Second) lockID := cs.mu.Lock() defer cs.mu.Unlock(lockID) cs.acceptBlock(b) // NOTE: Error is not handled. }() return ErrFutureTimestamp } return nil }
// validHeader does some early, low computation verification on the block. func (cs *ConsensusSet) validHeader(tx *bolt.Tx, b types.Block) error { // See if the block is known already. id := b.ID() _, exists := cs.dosBlocks[id] if exists { return errDoSBlock } // Check if the block is already known. blockMap := tx.Bucket(BlockMap) if blockMap.Get(id[:]) != nil { return modules.ErrBlockKnown } // Check for the parent. parentBytes := blockMap.Get(b.ParentID[:]) if parentBytes == nil { return errOrphan } var parent processedBlock err := encoding.Unmarshal(parentBytes, &parent) if err != nil { return err } // Check that the target of the new block is sufficient. if !b.CheckTarget(parent.ChildTarget) { return modules.ErrBlockUnsolved } // Check that the timestamp is not too far in the past to be // acceptable. if earliestChildTimestamp(blockMap, &parent) > b.Timestamp { return errEarlyTimestamp } // Check that the block is below the size limit. if uint64(len(encoding.Marshal(b))) > types.BlockSizeLimit { return errLargeBlock } // If the block is in the extreme future, return an error and do nothing // more with the block. There is an assumption that by the time the extreme // future arrives, this block will no longer be a part of the longest fork // because it will have been ignored by all of the miners. if b.Timestamp > types.CurrentTimestamp()+types.ExtremeFutureThreshold { return errExtremeFutureTimestamp } // Verify that the miner payouts are valid. if !b.CheckMinerPayouts(parent.Height + 1) { return errBadMinerPayouts } // If the block is in the near future, but too far to be acceptable, then // the block will be saved and added to the consensus set after it is no // longer too far in the future. This is the last check because it's an // expensive check, and not worth performing if the payouts are incorrect. if b.Timestamp > types.CurrentTimestamp()+types.FutureThreshold { go func() { time.Sleep(time.Duration(b.Timestamp-(types.CurrentTimestamp()+types.FutureThreshold)) * time.Second) cs.AcceptBlock(b) // NOTE: Error is not handled. }() return errFutureTimestamp } return nil }