1

In the bitcoin v0.9.3 source: https://github.com/bitcoin/bitcoin/blob/v0.9.3/src/main.cpp

ConnectBlock() calls CheckBlock() as one of the first things it does. https://github.com/bitcoin/bitcoin/blob/v0.9.3/src/main.cpp#L1756. And CheckBlock() does a count of the signature operations that doesn't include counting P2SH sig ops in the inputs.

But then ConnectBlock() goes on to do it's own nSigOps count, this time including the P2SH sig ops (https://github.com/bitcoin/bitcoin/blob/v0.9.3/src/main.cpp#L1810).

Why doesn't CheckBlock() just include the P2SH sig op count to avoid code duplication between the two methods? Is it for efficiency? Or maybe backwards compatibility?

Thanks!

1 Answer 1

2

There's something unintuitive about Bitcoin transaction SigOp counting. Normally, the signature count of a block is calculated by looking at the scriptPubKey of each transaction and counting how many OP_CHECKSIG operations it contains. In other words, the SigOp count is gotten by looking at how many outputs you create, not how many inputs you redeem.

However, you obviously can't see how many operations a P2SH script does by looking at its hash. Instead, the transaction that spends the P2SH script "pays" for it.

The somewhat awkward thing is that you can't tell if a scriptSig is spending a P2SH output unless you look up the outpoint it's spending.

Why doesn't CheckBlock() just include the P2SH sig op count to avoid code duplication between the two methods?

I don't think it's for backwards compatibility. While ConnectBlock doesn't count P2SH SigOps for transactions that appear to be P2SH but aren't, that logic could be implemented in CheckBlock instead.

I don't think it's for efficiency. Rejecting blocks with too many SigOps isn't very common, since it takes about seven thousand dollars of electricity to make a block. I suspect that you could remove the SigOp check from CheckBlock for a very minor performance increase.

I think it's partially because it would be irritating to change. Getting the P2SH SigOp count requires access to the CCoinViewCache object, which isn't passed to CheckBlock.

3
  • Thanks, the use of the CCoinViewCache was what I was missing. Don't want to bog the CheckBlock() quick checks down with this slower check.
    – morsecoder
    Dec 31, 2014 at 15:30
  • Also, why bother counting the scriptPubKeys' signature operations, shouldn't the sig op count be just the approximate count of signature operations to validate the block? And scriptPubKeys of a block don't necessarily need to be validated that block, the previous scriptPubKeys and the inputs do need to be validated.
    – morsecoder
    Dec 31, 2014 at 17:28
  • @StephenM347 I agree, that would have made more sense. I don't know why they did it that way.
    – Nick ODell
    Dec 31, 2014 at 21:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.