Skip to content

Commit 0aa9207

Browse files
committed
[qa] Witness version 0 signing unit tests
1 parent 978e200 commit 0aa9207

File tree

1 file changed

+276
-0
lines changed

1 file changed

+276
-0
lines changed

src/test/transaction_tests.cpp

Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
#include "main.h" // For CheckTransaction
1515
#include "policy/policy.h"
1616
#include "script/script.h"
17+
#include "script/sign.h"
1718
#include "script/script_error.h"
19+
#include "script/standard.h"
1820
#include "utilstrencodings.h"
1921

2022
#include <map>
@@ -25,11 +27,14 @@
2527
#include <boost/assign/list_of.hpp>
2628
#include <boost/test/unit_test.hpp>
2729
#include <boost/assign/list_of.hpp>
30+
#include <boost/foreach.hpp>
2831

2932
#include <univalue.h>
3033

3134
using namespace std;
3235

36+
typedef vector<unsigned char> valtype;
37+
3338
// In script_tests.cpp
3439
extern UniValue read_json(const std::string& jsondata);
3540

@@ -315,6 +320,277 @@ BOOST_AUTO_TEST_CASE(test_Get)
315320
BOOST_CHECK_EQUAL(coins.GetValueIn(t1), (50+21+22)*CENT);
316321
}
317322

323+
void CreateCreditAndSpend(const CKeyStore& keystore, const CScript& outscript, CTransaction& output, CMutableTransaction& input, bool success = true)
324+
{
325+
CMutableTransaction outputm;
326+
outputm.nVersion = 1;
327+
outputm.vin.resize(1);
328+
outputm.vin[0].prevout.SetNull();
329+
outputm.vin[0].scriptSig = CScript();
330+
outputm.wit.vtxinwit.resize(1);
331+
outputm.vout.resize(1);
332+
outputm.vout[0].nValue = 1;
333+
outputm.vout[0].scriptPubKey = outscript;
334+
CDataStream ssout(SER_NETWORK, PROTOCOL_VERSION);
335+
ssout << outputm;
336+
ssout >> output;
337+
assert(output.vin.size() == 1);
338+
assert(output.vin[0] == outputm.vin[0]);
339+
assert(output.vout.size() == 1);
340+
assert(output.vout[0] == outputm.vout[0]);
341+
assert(output.wit.vtxinwit.size() == 0);
342+
343+
CMutableTransaction inputm;
344+
inputm.nVersion = 1;
345+
inputm.vin.resize(1);
346+
inputm.vin[0].prevout.hash = output.GetHash();
347+
inputm.vin[0].prevout.n = 0;
348+
inputm.wit.vtxinwit.resize(1);
349+
inputm.vout.resize(1);
350+
inputm.vout[0].nValue = 1;
351+
inputm.vout[0].scriptPubKey = CScript();
352+
bool ret = SignSignature(keystore, output, inputm, 0, SIGHASH_ALL);
353+
assert(ret == success);
354+
CDataStream ssin(SER_NETWORK, PROTOCOL_VERSION);
355+
ssin << inputm;
356+
ssin >> input;
357+
assert(input.vin.size() == 1);
358+
assert(input.vin[0] == inputm.vin[0]);
359+
assert(input.vout.size() == 1);
360+
assert(input.vout[0] == inputm.vout[0]);
361+
if (inputm.wit.IsNull()) {
362+
assert(input.wit.IsNull());
363+
} else {
364+
assert(!input.wit.IsNull());
365+
assert(input.wit.vtxinwit.size() == 1);
366+
assert(input.wit.vtxinwit[0].scriptWitness.stack == inputm.wit.vtxinwit[0].scriptWitness.stack);
367+
}
368+
}
369+
370+
void CheckWithFlag(const CTransaction& output, const CMutableTransaction& input, int flags, bool success)
371+
{
372+
ScriptError error;
373+
CTransaction inputi(input);
374+
bool ret = VerifyScript(inputi.vin[0].scriptSig, output.vout[0].scriptPubKey, inputi.wit.vtxinwit.size() > 0 ? &inputi.wit.vtxinwit[0].scriptWitness : NULL, flags, TransactionSignatureChecker(&inputi, 0, output.vout[0].nValue), &error);
375+
assert(ret == success);
376+
}
377+
378+
static CScript PushAll(const vector<valtype>& values)
379+
{
380+
CScript result;
381+
BOOST_FOREACH(const valtype& v, values) {
382+
if (v.size() == 0) {
383+
result << OP_0;
384+
} else if (v.size() == 1 && v[0] >= 1 && v[0] <= 16) {
385+
result << CScript::EncodeOP_N(v[0]);
386+
} else {
387+
result << v;
388+
}
389+
}
390+
return result;
391+
}
392+
393+
void ReplaceRedeemScript(CScript& script, const CScript& redeemScript)
394+
{
395+
vector<valtype> stack;
396+
EvalScript(stack, script, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SIGVERSION_BASE);
397+
assert(stack.size() > 0);
398+
stack.back() = std::vector<unsigned char>(redeemScript.begin(), redeemScript.end());
399+
script = PushAll(stack);
400+
}
401+
402+
BOOST_AUTO_TEST_CASE(test_witness)
403+
{
404+
CBasicKeyStore keystore, keystore2;
405+
CKey key1, key2, key3, key1L, key2L;
406+
CPubKey pubkey1, pubkey2, pubkey3, pubkey1L, pubkey2L;
407+
key1.MakeNewKey(true);
408+
key2.MakeNewKey(true);
409+
key3.MakeNewKey(true);
410+
key1L.MakeNewKey(false);
411+
key2L.MakeNewKey(false);
412+
pubkey1 = key1.GetPubKey();
413+
pubkey2 = key2.GetPubKey();
414+
pubkey3 = key3.GetPubKey();
415+
pubkey1L = key1L.GetPubKey();
416+
pubkey2L = key2L.GetPubKey();
417+
keystore.AddKeyPubKey(key1, pubkey1);
418+
keystore.AddKeyPubKey(key2, pubkey2);
419+
keystore.AddKeyPubKey(key1L, pubkey1L);
420+
keystore.AddKeyPubKey(key2L, pubkey2L);
421+
CScript scriptPubkey1, scriptPubkey2, scriptPubkey1L, scriptPubkey2L, scriptMulti;
422+
scriptPubkey1 << ToByteVector(pubkey1) << OP_CHECKSIG;
423+
scriptPubkey2 << ToByteVector(pubkey2) << OP_CHECKSIG;
424+
scriptPubkey1L << ToByteVector(pubkey1L) << OP_CHECKSIG;
425+
scriptPubkey2L << ToByteVector(pubkey2L) << OP_CHECKSIG;
426+
std::vector<CPubKey> oneandthree;
427+
oneandthree.push_back(pubkey1);
428+
oneandthree.push_back(pubkey3);
429+
scriptMulti = GetScriptForMultisig(2, oneandthree);
430+
keystore.AddCScript(scriptPubkey1);
431+
keystore.AddCScript(scriptPubkey2);
432+
keystore.AddCScript(scriptPubkey1L);
433+
keystore.AddCScript(scriptPubkey2L);
434+
keystore.AddCScript(scriptMulti);
435+
keystore.AddCScript(GetScriptForWitness(scriptPubkey1));
436+
keystore.AddCScript(GetScriptForWitness(scriptPubkey2));
437+
keystore.AddCScript(GetScriptForWitness(scriptPubkey1L));
438+
keystore.AddCScript(GetScriptForWitness(scriptPubkey2L));
439+
keystore.AddCScript(GetScriptForWitness(scriptMulti));
440+
keystore2.AddCScript(scriptMulti);
441+
keystore2.AddCScript(GetScriptForWitness(scriptMulti));
442+
keystore2.AddKeyPubKey(key3, pubkey3);
443+
444+
CTransaction output1, output2;
445+
CMutableTransaction input1, input2;
446+
SignatureData sigdata;
447+
448+
// Normal pay-to-compressed-pubkey.
449+
CreateCreditAndSpend(keystore, scriptPubkey1, output1, input1);
450+
CreateCreditAndSpend(keystore, scriptPubkey2, output2, input2);
451+
CheckWithFlag(output1, input1, 0, true);
452+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
453+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
454+
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
455+
CheckWithFlag(output1, input2, 0, false);
456+
CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, false);
457+
CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
458+
CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
459+
460+
// P2SH pay-to-compressed-pubkey.
461+
CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey1)), output1, input1);
462+
CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey2)), output2, input2);
463+
ReplaceRedeemScript(input2.vin[0].scriptSig, scriptPubkey1);
464+
CheckWithFlag(output1, input1, 0, true);
465+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
466+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
467+
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
468+
CheckWithFlag(output1, input2, 0, true);
469+
CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, false);
470+
CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
471+
CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
472+
473+
// Witness pay-to-compressed-pubkey (v0).
474+
CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey1), output1, input1);
475+
CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey2), output2, input2);
476+
CheckWithFlag(output1, input1, 0, true);
477+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
478+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
479+
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
480+
CheckWithFlag(output1, input2, 0, true);
481+
CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, true);
482+
CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
483+
CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
484+
485+
// P2SH witness pay-to-compressed-pubkey (v0).
486+
CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey1))), output1, input1);
487+
CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey2))), output2, input2);
488+
ReplaceRedeemScript(input2.vin[0].scriptSig, GetScriptForWitness(scriptPubkey1));
489+
CheckWithFlag(output1, input1, 0, true);
490+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
491+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
492+
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
493+
CheckWithFlag(output1, input2, 0, true);
494+
CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, true);
495+
CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
496+
CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
497+
498+
// Normal pay-to-uncompressed-pubkey.
499+
CreateCreditAndSpend(keystore, scriptPubkey1L, output1, input1);
500+
CreateCreditAndSpend(keystore, scriptPubkey2L, output2, input2);
501+
CheckWithFlag(output1, input1, 0, true);
502+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
503+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
504+
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
505+
CheckWithFlag(output1, input2, 0, false);
506+
CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, false);
507+
CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
508+
CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
509+
510+
// P2SH pay-to-uncompressed-pubkey.
511+
CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey1L)), output1, input1);
512+
CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey2L)), output2, input2);
513+
ReplaceRedeemScript(input2.vin[0].scriptSig, scriptPubkey1L);
514+
CheckWithFlag(output1, input1, 0, true);
515+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
516+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
517+
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
518+
CheckWithFlag(output1, input2, 0, true);
519+
CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, false);
520+
CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
521+
CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
522+
523+
// Witness pay-to-uncompressed-pubkey (v1).
524+
CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey1L), output1, input1);
525+
CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey2L), output2, input2);
526+
CheckWithFlag(output1, input1, 0, true);
527+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
528+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
529+
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
530+
CheckWithFlag(output1, input2, 0, true);
531+
CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, true);
532+
CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
533+
CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
534+
535+
// P2SH witness pay-to-uncompressed-pubkey (v1).
536+
CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey1L))), output1, input1);
537+
CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey2L))), output2, input2);
538+
ReplaceRedeemScript(input2.vin[0].scriptSig, GetScriptForWitness(scriptPubkey1L));
539+
CheckWithFlag(output1, input1, 0, true);
540+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
541+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
542+
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
543+
CheckWithFlag(output1, input2, 0, true);
544+
CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, true);
545+
CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
546+
CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
547+
548+
// Normal 2-of-2 multisig
549+
CreateCreditAndSpend(keystore, scriptMulti, output1, input1, false);
550+
CheckWithFlag(output1, input1, 0, false);
551+
CreateCreditAndSpend(keystore2, scriptMulti, output2, input2, false);
552+
CheckWithFlag(output2, input2, 0, false);
553+
BOOST_CHECK(output1 == output2);
554+
UpdateTransaction(input1, 0, CombineSignatures(output1.vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1.vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0)));
555+
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
556+
557+
// P2SH 2-of-2 multisig
558+
CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptMulti)), output1, input1, false);
559+
CheckWithFlag(output1, input1, 0, true);
560+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, false);
561+
CreateCreditAndSpend(keystore2, GetScriptForDestination(CScriptID(scriptMulti)), output2, input2, false);
562+
CheckWithFlag(output2, input2, 0, true);
563+
CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH, false);
564+
BOOST_CHECK(output1 == output2);
565+
UpdateTransaction(input1, 0, CombineSignatures(output1.vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1.vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0)));
566+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
567+
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
568+
569+
// Witness 2-of-2 multisig
570+
CreateCreditAndSpend(keystore, GetScriptForWitness(scriptMulti), output1, input1, false);
571+
CheckWithFlag(output1, input1, 0, true);
572+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false);
573+
CreateCreditAndSpend(keystore2, GetScriptForWitness(scriptMulti), output2, input2, false);
574+
CheckWithFlag(output2, input2, 0, true);
575+
CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false);
576+
BOOST_CHECK(output1 == output2);
577+
UpdateTransaction(input1, 0, CombineSignatures(output1.vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1.vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0)));
578+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true);
579+
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
580+
581+
// P2SH witness 2-of-2 multisig
582+
CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptMulti))), output1, input1, false);
583+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
584+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false);
585+
CreateCreditAndSpend(keystore2, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptMulti))), output2, input2, false);
586+
CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH, true);
587+
CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false);
588+
BOOST_CHECK(output1 == output2);
589+
UpdateTransaction(input1, 0, CombineSignatures(output1.vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1.vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0)));
590+
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true);
591+
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
592+
}
593+
318594
BOOST_AUTO_TEST_CASE(test_IsStandard)
319595
{
320596
LOCK(cs_main);

0 commit comments

Comments
 (0)