@@ -133,58 +133,96 @@ This BIP depends on [[bip-0141.mediawiki|BIP141]] and will be deployed by versio
133
133
The idea of MAST originates from Russell O’Connor, Pieter Wuille, and [https://bitcointalk.org/index.php?topic=255145.msg2757327#msg2757327 Peter Todd ].
134
134
135
135
== Reference Implementation ==
136
- https://github.com/jl2012/bitcoin/commit/f335cab76eb95d4f7754a718df201216a4975d8c
136
+ https://github.com/jl2012/bitcoin/tree/segwit_mast
137
137
138
138
<source lang ="cpp" >
139
+ //New rules apply if version byte is 1 and witness program size is 32 bytes
139
140
if (witversion == 1) {
140
141
if (program.size() == 32) {
142
+
143
+ //Witness stack must have at least 3 items
141
144
if (witness.stack.size() < 3)
142
145
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
143
146
144
- //Script: the last witness stack item
147
+ //Script is the last witness stack item
145
148
scriptPubKey = CScript(witness.stack.back().begin(), witness.stack.back().end());
146
149
uint256 hashScriptPubKey;
147
150
CHash256().Write(&scriptPubKey[0], scriptPubKey.size()).Finalize(hashScriptPubKey.begin());
148
151
149
- //Path: the second last witness stack item; size = 32N, 0 <= N < 33
152
+ //Path is the second last witness stack item
150
153
std::vector<unsigned char> pathdata = witness.stack.at(witness.stack.size() - 2);
154
+
155
+ // Size of Path must be a multiple of 32 bytes (0 byte is allowed)
151
156
if (pathdata.size() & 0x1F)
152
157
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
158
+
159
+ // Depth of the tree is size of Path divided by 32
153
160
unsigned int depth = pathdata.size() >> 5;
161
+
162
+ // Maximum allowed depth is 32
154
163
if (depth > 32)
155
164
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
156
165
std::vector<uint256> path;
157
166
path.resize(depth);
158
167
for (unsigned int i = 0; i < depth; i++)
159
168
memcpy(path[i].begin(), &pathdata[32 * i], 32);
160
169
161
- //Position: the third last witness stack item; unsigned int with smallest possible value and no leading zero
170
+ //Position is the third last witness stack item
162
171
std::vector<unsigned char> positiondata = witness.stack.at(witness.stack.size() - 3);
172
+
173
+ //Position may have 4 bytes at most
163
174
if (positiondata.size() > 4)
164
175
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
176
+
165
177
uint32_t position = 0;
178
+
179
+ //Position is an unsigned little-endian integer with no leading zero byte
166
180
if (positiondata.size() > 0) {
167
181
if (positiondata.back() == 0x00)
168
182
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
169
183
for (size_t i = 0; i != positiondata.size(); ++i)
170
184
position |= static_cast<uint32_t>(positiondata[i]) << 8 * i;
171
185
}
186
+
187
+ //Position must not be larger than the maximum number of items allowed by the depth of tree
172
188
if (depth < 32) {
173
189
if (position >= (1U << depth))
174
190
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
175
191
}
176
192
193
+ //Calculate the Merkle Root and compare with the witness program
177
194
uint256 root = ComputeMerkleRootFromBranch(hashScriptPubKey, path, position);
178
195
if (memcmp(root.begin(), &program[0], 32))
179
196
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
180
197
198
+ //Remaining stack items used for evaluation
181
199
stack = std::vector<std::vector<unsigned char> >(witness.stack.begin(), witness.stack.end() - 3);
182
- } else {
200
+ }
201
+
202
+ else {
203
+ //Invalid if version byte is 1 but witness program size is not 32 bytes
183
204
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH);
184
205
}
185
206
}
186
207
</source >
187
208
209
+ Copying from <code>src/consensus/merkle.cpp </code>:
210
+ <source lang="cpp">
211
+ uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vector<uint256>& vMerkleBranch, uint32_t nIndex) {
212
+ uint256 hash = leaf;
213
+ for (std::vector<uint256>::const_iterator it = vMerkleBranch.begin(); it != vMerkleBranch.end(); ++it) {
214
+ if (nIndex & 1) {
215
+ hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash));
216
+ } else {
217
+ hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it));
218
+ }
219
+ nIndex >>= 1;
220
+ }
221
+ return hash;
222
+ }
223
+ </source>
224
+
225
+
188
226
== References ==
189
227
*[[bip-0141.mediawiki |BIP141 Segregated Witness (Consensus layer) ]]
190
228
0 commit comments