summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjl2012 <jl2012@xbt.hk>2016-04-14 00:43:16 +0800
committerjl2012 <jl2012@xbt.hk>2016-04-14 00:43:16 +0800
commit3ef07340b42f3abee4b01d30d7a53315d0b30fa1 (patch)
treefdc3feeb72497a8f66e8027afd1d185a654922ba
parent6c71b46623246950fd9ea335047f07076957177f (diff)
downloadbips-3ef07340b42f3abee4b01d30d7a53315d0b30fa1.tar.xz
BIP114: Clarifying reference implementation
-rw-r--r--bip-0114.mediawiki48
1 files changed, 43 insertions, 5 deletions
diff --git a/bip-0114.mediawiki b/bip-0114.mediawiki
index 4ad593f..3688351 100644
--- a/bip-0114.mediawiki
+++ b/bip-0114.mediawiki
@@ -133,24 +133,33 @@ This BIP depends on [[bip-0141.mediawiki|BIP141]] and will be deployed by versio
The idea of MAST originates from Russell O’Connor, Pieter Wuille, and [https://bitcointalk.org/index.php?topic=255145.msg2757327#msg2757327 Peter Todd].
== Reference Implementation ==
-https://github.com/jl2012/bitcoin/commit/f335cab76eb95d4f7754a718df201216a4975d8c
+https://github.com/jl2012/bitcoin/tree/segwit_mast
<source lang="cpp">
+//New rules apply if version byte is 1 and witness program size is 32 bytes
if (witversion == 1) {
if (program.size() == 32) {
+
+ //Witness stack must have at least 3 items
if (witness.stack.size() < 3)
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
- //Script: the last witness stack item
+ //Script is the last witness stack item
scriptPubKey = CScript(witness.stack.back().begin(), witness.stack.back().end());
uint256 hashScriptPubKey;
CHash256().Write(&scriptPubKey[0], scriptPubKey.size()).Finalize(hashScriptPubKey.begin());
- //Path: the second last witness stack item; size = 32N, 0 <= N < 33
+ //Path is the second last witness stack item
std::vector<unsigned char> pathdata = witness.stack.at(witness.stack.size() - 2);
+
+ // Size of Path must be a multiple of 32 bytes (0 byte is allowed)
if (pathdata.size() & 0x1F)
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
+
+ // Depth of the tree is size of Path divided by 32
unsigned int depth = pathdata.size() >> 5;
+
+ // Maximum allowed depth is 32
if (depth > 32)
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
std::vector<uint256> path;
@@ -158,33 +167,62 @@ if (witversion == 1) {
for (unsigned int i = 0; i < depth; i++)
memcpy(path[i].begin(), &pathdata[32 * i], 32);
- //Position: the third last witness stack item; unsigned int with smallest possible value and no leading zero
+ //Position is the third last witness stack item
std::vector<unsigned char> positiondata = witness.stack.at(witness.stack.size() - 3);
+
+ //Position may have 4 bytes at most
if (positiondata.size() > 4)
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
+
uint32_t position = 0;
+
+ //Position is an unsigned little-endian integer with no leading zero byte
if (positiondata.size() > 0) {
if (positiondata.back() == 0x00)
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
for (size_t i = 0; i != positiondata.size(); ++i)
position |= static_cast<uint32_t>(positiondata[i]) << 8 * i;
}
+
+ //Position must not be larger than the maximum number of items allowed by the depth of tree
if (depth < 32) {
if (position >= (1U << depth))
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
}
+ //Calculate the Merkle Root and compare with the witness program
uint256 root = ComputeMerkleRootFromBranch(hashScriptPubKey, path, position);
if (memcmp(root.begin(), &program[0], 32))
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
+ //Remaining stack items used for evaluation
stack = std::vector<std::vector<unsigned char> >(witness.stack.begin(), witness.stack.end() - 3);
- } else {
+ }
+
+ else {
+ //Invalid if version byte is 1 but witness program size is not 32 bytes
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH);
}
}
</source>
+Copying from <code>src/consensus/merkle.cpp</code>:
+<source lang="cpp">
+uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vector<uint256>& vMerkleBranch, uint32_t nIndex) {
+ uint256 hash = leaf;
+ for (std::vector<uint256>::const_iterator it = vMerkleBranch.begin(); it != vMerkleBranch.end(); ++it) {
+ if (nIndex & 1) {
+ hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash));
+ } else {
+ hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it));
+ }
+ nIndex >>= 1;
+ }
+ return hash;
+}
+</source>
+
+
== References ==
*[[bip-0141.mediawiki|BIP141 Segregated Witness (Consensus layer)]]