From ad275b34a8d6e34f1fbd36eb2ed0e4e350e69322 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 26 Jun 2014 15:50:13 -0500 Subject: [PATCH] Add a new behavior flag to disable the pow check. This commit adds a new behavior flag, BFNoPoWCheck which allows the caller to indicate the check which ensures a block hashes to a value less than required target should not be performed. --- process.go | 7 ++++++- validate.go | 55 ++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 46 insertions(+), 16 deletions(-) diff --git a/process.go b/process.go index bb5d452f..5d3d0b7e 100644 --- a/process.go +++ b/process.go @@ -21,6 +21,11 @@ const ( // checkpoint. This is primarily used for headers-first mode. BFFastAdd BehaviorFlags = 1 << iota + // BFNoPoWCheck may be set to indicate the proof of work check which + // ensures a block hashes to a value less than the required target will + // not be performed. + BFNoPoWCheck + // BFNone is a convenience value to specifically indicate no flags. BFNone BehaviorFlags = 0 ) @@ -125,7 +130,7 @@ func (b *BlockChain) ProcessBlock(block *btcutil.Block, flags BehaviorFlags) (bo } // Perform preliminary sanity checks on the block and its transactions. - err = CheckBlockSanity(block, b.netParams.PowLimit) + err = checkBlockSanity(block, b.netParams.PowLimit, flags) if err != nil { return false, err } diff --git a/validate.go b/validate.go index 188ad511..c253fd19 100644 --- a/validate.go +++ b/validate.go @@ -268,10 +268,15 @@ func CheckTransactionSanity(tx *btcutil.Tx) error { return nil } -// CheckProofOfWork ensures the block header bits which indicate the target +// checkProofOfWork ensures the block header bits which indicate the target // difficulty is in min/max range and that the block hash is less than the // target difficulty as claimed. -func CheckProofOfWork(block *btcutil.Block, powLimit *big.Int) error { +// +// +// The flags modify the behavior of this function as follows: +// - BFNoPoWCheck: The check to ensure the block hash is less than the target +// difficulty is not performed. +func checkProofOfWork(block *btcutil.Block, powLimit *big.Int, flags BehaviorFlags) error { // The target difficulty must be larger than zero. target := CompactToBig(block.MsgBlock().Header.Bits) if target.Sign() <= 0 { @@ -287,21 +292,32 @@ func CheckProofOfWork(block *btcutil.Block, powLimit *big.Int) error { return ruleError(ErrUnexpectedDifficulty, str) } - // The block hash must be less than the claimed target. - blockHash, err := block.Sha() - if err != nil { - return err - } - hashNum := ShaHashToBig(blockHash) - if hashNum.Cmp(target) > 0 { - str := fmt.Sprintf("block hash of %064x is higher than "+ - "expected max of %064x", hashNum, target) - return ruleError(ErrHighHash, str) + // The block hash must be less than the claimed target unless the flag + // to avoid proof of work checks is set. + if flags&BFNoPoWCheck != BFNoPoWCheck { + // The block hash must be less than the claimed target. + blockHash, err := block.Sha() + if err != nil { + return err + } + hashNum := ShaHashToBig(blockHash) + if hashNum.Cmp(target) > 0 { + str := fmt.Sprintf("block hash of %064x is higher than "+ + "expected max of %064x", hashNum, target) + return ruleError(ErrHighHash, str) + } } return nil } +// CheckProofOfWork ensures the block header bits which indicate the target +// difficulty is in min/max range and that the block hash is less than the +// target difficulty as claimed. +func CheckProofOfWork(block *btcutil.Block, powLimit *big.Int) error { + return checkProofOfWork(block, powLimit, BFNone) +} + // CountSigOps returns the number of signature operations for all transaction // input and output scripts in the provided transaction. This uses the // quicker, but imprecise, signature operation counting mechanism from @@ -392,9 +408,12 @@ func CountP2SHSigOps(tx *btcutil.Tx, isCoinBaseTx bool, txStore TxStore) (int, e return totalSigOps, nil } -// CheckBlockSanity performs some preliminary checks on a block to ensure it is +// checkBlockSanity performs some preliminary checks on a block to ensure it is // sane before continuing with block processing. These checks are context free. -func CheckBlockSanity(block *btcutil.Block, powLimit *big.Int) error { +// +// The flags do not modify the behavior of this function directly, however they +// are needed to pass along to checkProofOfWork. +func checkBlockSanity(block *btcutil.Block, powLimit *big.Int, flags BehaviorFlags) error { // NOTE: bitcoind does size limits checking here, but the size limits // have already been checked by btcwire for incoming blocks. Also, // btcwire checks the size limits on send too, so there is no need @@ -403,7 +422,7 @@ func CheckBlockSanity(block *btcutil.Block, powLimit *big.Int) error { // Ensure the proof of work bits in the block header is in min/max range // and the block hash is less than the target value described by the // bits. - err := CheckProofOfWork(block, powLimit) + err := checkProofOfWork(block, powLimit, flags) if err != nil { return err } @@ -506,6 +525,12 @@ func CheckBlockSanity(block *btcutil.Block, powLimit *big.Int) error { return nil } +// CheckBlockSanity performs some preliminary checks on a block to ensure it is +// sane before continuing with block processing. These checks are context free. +func CheckBlockSanity(block *btcutil.Block, powLimit *big.Int) error { + return checkBlockSanity(block, powLimit, BFNone) +} + // checkSerializedHeight checks if the signature script in the passed // transaction starts with the serialized block height of wantHeight. func checkSerializedHeight(coinbaseTx *btcutil.Tx, wantHeight int64) error {