@@ -253,11 +253,22 @@ struct KeyData
253
253
}
254
254
};
255
255
256
+ enum WitnessMode {
257
+ WITNESS_NONE,
258
+ WITNESS_PKH,
259
+ WITNESS_SH
260
+ };
256
261
257
262
class TestBuilder
258
263
{
259
264
private:
260
- CScript scriptPubKey;
265
+ // ! Actually executed script
266
+ CScript script;
267
+ // ! The P2SH redeemscript
268
+ CScript redeemscript;
269
+ // ! The Witness embedded script
270
+ CScript witscript;
271
+ CScriptWitness scriptWitness;
261
272
CTransaction creditTx;
262
273
CMutableTransaction spendTx;
263
274
bool havePush;
@@ -282,13 +293,25 @@ class TestBuilder
282
293
}
283
294
284
295
public:
285
- TestBuilder (const CScript& redeemScript , const std::string& comment_, int flags_, bool P2SH = false ) : scriptPubKey(redeemScript ), havePush(false ), comment(comment_), flags(flags_), scriptError(SCRIPT_ERR_OK)
296
+ TestBuilder (const CScript& script_ , const std::string& comment_, int flags_, bool P2SH = false , WitnessMode wm = WITNESS_NONE ) : script(script_ ), havePush(false ), comment(comment_), flags(flags_), scriptError(SCRIPT_ERR_OK)
286
297
{
298
+ CScript scriptPubKey = script;
299
+ if (wm == WITNESS_PKH) {
300
+ uint160 hash;
301
+ CHash160 ().Write (&script[1 ], script.size () - 1 ).Finalize (hash.begin ());
302
+ script = CScript () << OP_DUP << OP_HASH160 << ToByteVector (hash) << OP_EQUALVERIFY << OP_CHECKSIG;
303
+ scriptPubKey = CScript () << OP_0 << ToByteVector (hash);
304
+ } else if (wm == WITNESS_SH) {
305
+ witscript = scriptPubKey;
306
+ uint256 hash;
307
+ CSHA256 ().Write (&witscript[0 ], witscript.size ()).Finalize (hash.begin ());
308
+ scriptPubKey = CScript () << OP_0 << ToByteVector (hash);
309
+ }
287
310
if (P2SH) {
288
- creditTx = BuildCreditingTransaction (CScript () << OP_HASH160 << ToByteVector (CScriptID (redeemScript)) << OP_EQUAL);
289
- } else {
290
- creditTx = BuildCreditingTransaction (redeemScript);
311
+ redeemscript = scriptPubKey;
312
+ scriptPubKey = CScript () << OP_HASH160 << ToByteVector (CScriptID (redeemscript)) << OP_EQUAL;
291
313
}
314
+ creditTx = BuildCreditingTransaction (scriptPubKey);
292
315
spendTx = BuildSpendingTransaction (CScript (), CScriptWitness (), creditTx);
293
316
}
294
317
@@ -318,9 +341,9 @@ class TestBuilder
318
341
return *this ;
319
342
}
320
343
321
- TestBuilder& PushSig (const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32 , unsigned int lenS = 32 )
344
+ TestBuilder& PushSig (const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32 , unsigned int lenS = 32 , int sigversion = 0 )
322
345
{
323
- uint256 hash = SignatureHash (scriptPubKey , spendTx, 0 , nHashType, 0 , 0 );
346
+ uint256 hash = SignatureHash (script , spendTx, 0 , nHashType, 0 , sigversion );
324
347
std::vector<unsigned char > vchSig, r, s;
325
348
uint32_t iter = 0 ;
326
349
do {
@@ -336,6 +359,11 @@ class TestBuilder
336
359
return *this ;
337
360
}
338
361
362
+ TestBuilder& PushWitSig (const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32 , unsigned int lenS = 32 , int sigversion = 1 )
363
+ {
364
+ return PushSig (key, nHashType, lenR, lenS, sigversion).AsWit ();
365
+ }
366
+
339
367
TestBuilder& Push (const CPubKey& pubkey)
340
368
{
341
369
DoPush (std::vector<unsigned char >(pubkey.begin (), pubkey.end ()));
@@ -344,10 +372,16 @@ class TestBuilder
344
372
345
373
TestBuilder& PushRedeem ()
346
374
{
347
- DoPush (std::vector<unsigned char >(scriptPubKey .begin (), scriptPubKey .end ()));
375
+ DoPush (std::vector<unsigned char >(redeemscript .begin (), redeemscript .end ()));
348
376
return *this ;
349
377
}
350
378
379
+ TestBuilder& PushWitRedeem ()
380
+ {
381
+ DoPush (std::vector<unsigned char >(witscript.begin (), witscript.end ()));
382
+ return AsWit ();
383
+ }
384
+
351
385
TestBuilder& EditPush (unsigned int pos, const std::string& hexin, const std::string& hexout)
352
386
{
353
387
assert (havePush);
@@ -372,15 +406,30 @@ class TestBuilder
372
406
{
373
407
TestBuilder copy = *this ; // Make a copy so we can rollback the push.
374
408
DoPush ();
375
- DoTest (creditTx.vout [0 ].scriptPubKey , spendTx.vin [0 ].scriptSig , CScriptWitness () , flags, comment, scriptError);
409
+ DoTest (creditTx.vout [0 ].scriptPubKey , spendTx.vin [0 ].scriptSig , scriptWitness , flags, comment, scriptError);
376
410
*this = copy;
377
411
return *this ;
378
412
}
379
413
414
+ TestBuilder& AsWit ()
415
+ {
416
+ assert (havePush);
417
+ scriptWitness.stack .push_back (push);
418
+ havePush = false ;
419
+ return *this ;
420
+ }
421
+
380
422
UniValue GetJSON ()
381
423
{
382
424
DoPush ();
383
425
UniValue array (UniValue::VARR);
426
+ if (!scriptWitness.stack .empty ()) {
427
+ UniValue wit (UniValue::VARR);
428
+ for (unsigned i = 0 ; i < scriptWitness.stack .size (); i++) {
429
+ wit.push_back (HexStr (scriptWitness.stack [i]));
430
+ }
431
+ array.push_back (wit);
432
+ }
384
433
array.push_back (FormatScript (spendTx.vin [0 ].scriptSig ));
385
434
array.push_back (FormatScript (creditTx.vout [0 ].scriptPubKey ));
386
435
array.push_back (FormatScriptFlags (flags));
@@ -676,6 +725,30 @@ BOOST_AUTO_TEST_CASE(script_build)
676
725
" P2SH with CLEANSTACK" , SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH, true
677
726
).PushSig (keys.key0 ).PushRedeem ());
678
727
728
+ tests.push_back (TestBuilder (CScript () << ToByteVector (keys.pubkey0 ) << OP_CHECKSIG,
729
+ " Basic P2WSH" , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false , WITNESS_SH
730
+ ).PushWitSig (keys.key0 ).PushWitRedeem ());
731
+ tests.push_back (TestBuilder (CScript () << ToByteVector (keys.pubkey0 ),
732
+ " Basic P2WPKH" , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false , WITNESS_PKH
733
+ ).PushWitSig (keys.key0 ).Push (keys.pubkey0 ).AsWit ());
734
+ tests.push_back (TestBuilder (CScript () << ToByteVector (keys.pubkey0 ) << OP_CHECKSIG,
735
+ " Basic P2SH(P2WSH)" , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true , WITNESS_SH
736
+ ).PushWitSig (keys.key0 ).PushWitRedeem ().PushRedeem ());
737
+ tests.push_back (TestBuilder (CScript () << ToByteVector (keys.pubkey0 ),
738
+ " Basic P2SH(P2WPKH)" , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true , WITNESS_PKH
739
+ ).PushWitSig (keys.key0 ).Push (keys.pubkey0 ).AsWit ().PushRedeem ());
740
+ tests.push_back (TestBuilder (CScript () << ToByteVector (keys.pubkey1 ) << OP_CHECKSIG,
741
+ " Basic P2WSH with the wrong key" , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false , WITNESS_SH
742
+ ).PushWitSig (keys.key0 ).PushWitRedeem ().ScriptError (SCRIPT_ERR_EVAL_FALSE));
743
+ tests.push_back (TestBuilder (CScript () << ToByteVector (keys.pubkey1 ),
744
+ " Basic P2WPKH with the wrong key" , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false , WITNESS_PKH
745
+ ).PushWitSig (keys.key0 ).Push (keys.pubkey1 ).AsWit ().ScriptError (SCRIPT_ERR_EVAL_FALSE));
746
+ tests.push_back (TestBuilder (CScript () << ToByteVector (keys.pubkey1 ) << OP_CHECKSIG,
747
+ " Basic P2SH(P2WSH) with the wrong key" , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true , WITNESS_SH
748
+ ).PushWitSig (keys.key0 ).PushWitRedeem ().PushRedeem ().ScriptError (SCRIPT_ERR_EVAL_FALSE));
749
+ tests.push_back (TestBuilder (CScript () << ToByteVector (keys.pubkey1 ),
750
+ " Basic P2SH(P2WPKH) with the wrong key" , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true , WITNESS_PKH
751
+ ).PushWitSig (keys.key0 ).Push (keys.pubkey1 ).AsWit ().PushRedeem ().ScriptError (SCRIPT_ERR_EVAL_FALSE));
679
752
680
753
std::set<std::string> tests_set;
681
754
0 commit comments