diff options
author | fanquake <fanquake@gmail.com> | 2020-04-30 18:06:51 +0800 |
---|---|---|
committer | fanquake <fanquake@gmail.com> | 2020-04-30 18:50:26 +0800 |
commit | 64673b1037d60d5f2c9818085ff4d77b883ed44b (patch) | |
tree | bbf245d2938208f83b24a7e6191d949e84a8836a | |
parent | afed2e98b0e3a059adf0b1f88ce2551e3b09733c (diff) | |
parent | 692f8307fc1449299b90182e7d79efb81a55d7ab (diff) |
Merge #18780: validation: add const for minimum witness commitment size
692f8307fc1449299b90182e7d79efb81a55d7ab test: add test for witness commitment index (fanquake)
06442549f8b725f46c1c727e9eb6fde6b843503c validation: Add minimum witness commitment size constant (fanquake)
Pull request description:
https://github.com/bitcoin/bitcoin/commit/16101de5f33be494019a3f81755e204d00c22347: Per [BIP 141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#Commitment_structure), the witness commitment structure is at least 38 bytes,
OP_RETURN (0x6a) + 36 (0x24) + 4 byte header (0xaa21a9ed) + 32 byte
SHA256 hash. It can be longer, however any additional data has no
consensus meaning.
https://github.com/bitcoin/bitcoin/commit/54f8c48d6ac973024df35c4db038791b7958a51d: As per BIP 141, if there is more than 1 pubkey that matches the witness
commitment structure, the one with the highest output index should be
chosen. This adds a sanity check that we are doing that, which will fail
if anyone tries to "optimize" GetWitnessCommitmentIndex() by returning
early.
ACKs for top commit:
MarcoFalke:
ACK 692f8307fc1449299b90182e7d79efb81a55d7ab 🌵
jonatack:
Code review ACK 692f830
ajtowns:
ACK 692f8307fc1449299b90182e7d79efb81a55d7ab
jnewbery:
utACK 692f8307fc1449299b90182e7d79efb81a55d7ab
laanwj:
ACK 692f8307fc1449299b90182e7d79efb81a55d7ab
Tree-SHA512: 7af3fe4b8a52fea2cdd0aec95f7bb935351a77b73d934bc88d6625a3503311b2a062cba5190b2228f97caa76840db3889032d910fc8e318ca8e7810a8afbafa0
-rw-r--r-- | src/test/validation_block_tests.cpp | 34 | ||||
-rw-r--r-- | src/validation.cpp | 11 | ||||
-rw-r--r-- | src/validation.h | 2 |
3 files changed, 45 insertions, 2 deletions
diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp index b8af869b8e..c345f1eafb 100644 --- a/src/test/validation_block_tests.cpp +++ b/src/test/validation_block_tests.cpp @@ -340,4 +340,38 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg) rpc_thread.join(); } } + +BOOST_AUTO_TEST_CASE(witness_commitment_index) +{ + CScript pubKey; + pubKey << 1 << OP_TRUE; + auto ptemplate = BlockAssembler(*m_node.mempool, Params()).CreateNewBlock(pubKey); + CBlock pblock = ptemplate->block; + + CTxOut witness; + witness.scriptPubKey.resize(MINIMUM_WITNESS_COMMITMENT); + witness.scriptPubKey[0] = OP_RETURN; + witness.scriptPubKey[1] = 0x24; + witness.scriptPubKey[2] = 0xaa; + witness.scriptPubKey[3] = 0x21; + witness.scriptPubKey[4] = 0xa9; + witness.scriptPubKey[5] = 0xed; + + // A witness larger than the minimum size is still valid + CTxOut min_plus_one = witness; + min_plus_one.scriptPubKey.resize(MINIMUM_WITNESS_COMMITMENT + 1); + + CTxOut invalid = witness; + invalid.scriptPubKey[0] = OP_VERIFY; + + CMutableTransaction txCoinbase(*pblock.vtx[0]); + txCoinbase.vout.resize(4); + txCoinbase.vout[0] = witness; + txCoinbase.vout[1] = witness; + txCoinbase.vout[2] = min_plus_one; + txCoinbase.vout[3] = invalid; + pblock.vtx[0] = MakeTransactionRef(std::move(txCoinbase)); + + BOOST_CHECK_EQUAL(GetWitnessCommitmentIndex(pblock), 2); +} BOOST_AUTO_TEST_SUITE_END() diff --git a/src/validation.cpp b/src/validation.cpp index d18803b342..259397051c 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3386,7 +3386,14 @@ int GetWitnessCommitmentIndex(const CBlock& block) int commitpos = -1; if (!block.vtx.empty()) { for (size_t o = 0; o < block.vtx[0]->vout.size(); o++) { - if (block.vtx[0]->vout[o].scriptPubKey.size() >= 38 && block.vtx[0]->vout[o].scriptPubKey[0] == OP_RETURN && block.vtx[0]->vout[o].scriptPubKey[1] == 0x24 && block.vtx[0]->vout[o].scriptPubKey[2] == 0xaa && block.vtx[0]->vout[o].scriptPubKey[3] == 0x21 && block.vtx[0]->vout[o].scriptPubKey[4] == 0xa9 && block.vtx[0]->vout[o].scriptPubKey[5] == 0xed) { + const CTxOut& vout = block.vtx[0]->vout[o]; + if (vout.scriptPubKey.size() >= MINIMUM_WITNESS_COMMITMENT && + vout.scriptPubKey[0] == OP_RETURN && + vout.scriptPubKey[1] == 0x24 && + vout.scriptPubKey[2] == 0xaa && + vout.scriptPubKey[3] == 0x21 && + vout.scriptPubKey[4] == 0xa9 && + vout.scriptPubKey[5] == 0xed) { commitpos = o; } } @@ -3417,7 +3424,7 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc CHash256().Write(witnessroot.begin(), 32).Write(ret.data(), 32).Finalize(witnessroot.begin()); CTxOut out; out.nValue = 0; - out.scriptPubKey.resize(38); + out.scriptPubKey.resize(MINIMUM_WITNESS_COMMITMENT); out.scriptPubKey[0] = OP_RETURN; out.scriptPubKey[1] = 0x24; out.scriptPubKey[2] = 0xaa; diff --git a/src/validation.h b/src/validation.h index 91b1ba6497..0169362768 100644 --- a/src/validation.h +++ b/src/validation.h @@ -92,6 +92,8 @@ static const unsigned int DEFAULT_CHECKLEVEL = 3; // one 128MB block file + added 15% undo data = 147MB greater for a total of 545MB // Setting the target to >= 550 MiB will make it likely we can respect the target. static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024; +/** Minimum size of a witness commitment structure. Defined in BIP 141. **/ +static constexpr size_t MINIMUM_WITNESS_COMMITMENT{38}; struct BlockHasher { |