Bitcoin Core  22.99.0
P2P Digital Currency
multisig_tests.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2020 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <key.h>
6 #include <policy/policy.h>
7 #include <script/interpreter.h>
8 #include <script/script.h>
9 #include <script/script_error.h>
10 #include <script/sign.h>
11 #include <script/signingprovider.h>
12 #include <test/util/setup_common.h>
13 #include <tinyformat.h>
14 #include <uint256.h>
15 
16 
17 #include <boost/test/unit_test.hpp>
18 
20 
21 static CScript
22 sign_multisig(const CScript& scriptPubKey, const std::vector<CKey>& keys, const CTransaction& transaction, int whichIn)
23 {
24  uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL, 0, SigVersion::BASE);
25 
26  CScript result;
27  result << OP_0; // CHECKMULTISIG bug workaround
28  for (const CKey &key : keys)
29  {
30  std::vector<unsigned char> vchSig;
31  BOOST_CHECK(key.Sign(hash, vchSig));
32  vchSig.push_back((unsigned char)SIGHASH_ALL);
33  result << vchSig;
34  }
35  return result;
36 }
37 
38 BOOST_AUTO_TEST_CASE(multisig_verify)
39 {
41 
42  ScriptError err;
43  CKey key[4];
44  CAmount amount = 0;
45  for (int i = 0; i < 4; i++)
46  key[i].MakeNewKey(true);
47 
48  CScript a_and_b;
49  a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
50 
51  CScript a_or_b;
52  a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
53 
54  CScript escrow;
55  escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
56 
57  CMutableTransaction txFrom; // Funding transaction
58  txFrom.vout.resize(3);
59  txFrom.vout[0].scriptPubKey = a_and_b;
60  txFrom.vout[1].scriptPubKey = a_or_b;
61  txFrom.vout[2].scriptPubKey = escrow;
62 
63  CMutableTransaction txTo[3]; // Spending transaction
64  for (int i = 0; i < 3; i++)
65  {
66  txTo[i].vin.resize(1);
67  txTo[i].vout.resize(1);
68  txTo[i].vin[0].prevout.n = i;
69  txTo[i].vin[0].prevout.hash = txFrom.GetHash();
70  txTo[i].vout[0].nValue = 1;
71  }
72 
73  std::vector<CKey> keys;
74  CScript s;
75 
76  // Test a AND b:
77  keys.assign(1,key[0]);
78  keys.push_back(key[1]);
79  s = sign_multisig(a_and_b, keys, CTransaction(txTo[0]), 0);
80  BOOST_CHECK(VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount, MissingDataBehavior::ASSERT_FAIL), &err));
81  BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
82 
83  for (int i = 0; i < 4; i++)
84  {
85  keys.assign(1,key[i]);
86  s = sign_multisig(a_and_b, keys, CTransaction(txTo[0]), 0);
87  BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount, MissingDataBehavior::ASSERT_FAIL), &err), strprintf("a&b 1: %d", i));
88  BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
89 
90  keys.assign(1,key[1]);
91  keys.push_back(key[i]);
92  s = sign_multisig(a_and_b, keys, CTransaction(txTo[0]), 0);
93  BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount, MissingDataBehavior::ASSERT_FAIL), &err), strprintf("a&b 2: %d", i));
94  BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
95  }
96 
97  // Test a OR b:
98  for (int i = 0; i < 4; i++)
99  {
100  keys.assign(1,key[i]);
101  s = sign_multisig(a_or_b, keys, CTransaction(txTo[1]), 0);
102  if (i == 0 || i == 1)
103  {
104  BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount, MissingDataBehavior::ASSERT_FAIL), &err), strprintf("a|b: %d", i));
105  BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
106  }
107  else
108  {
109  BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount, MissingDataBehavior::ASSERT_FAIL), &err), strprintf("a|b: %d", i));
110  BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
111  }
112  }
113  s.clear();
114  s << OP_0 << OP_1;
115  BOOST_CHECK(!VerifyScript(s, a_or_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount, MissingDataBehavior::ASSERT_FAIL), &err));
116  BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));
117 
118 
119  for (int i = 0; i < 4; i++)
120  for (int j = 0; j < 4; j++)
121  {
122  keys.assign(1,key[i]);
123  keys.push_back(key[j]);
124  s = sign_multisig(escrow, keys, CTransaction(txTo[2]), 0);
125  if (i < j && i < 3 && j < 3)
126  {
127  BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, nullptr, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount, MissingDataBehavior::ASSERT_FAIL), &err), strprintf("escrow 1: %d %d", i, j));
128  BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
129  }
130  else
131  {
132  BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, nullptr, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount, MissingDataBehavior::ASSERT_FAIL), &err), strprintf("escrow 2: %d %d", i, j));
133  BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
134  }
135  }
136 }
137 
138 BOOST_AUTO_TEST_CASE(multisig_IsStandard)
139 {
140  CKey key[4];
141  for (int i = 0; i < 4; i++)
142  key[i].MakeNewKey(true);
143 
144  TxoutType whichType;
145 
146  CScript a_and_b;
147  a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
148  BOOST_CHECK(::IsStandard(a_and_b, whichType));
149 
150  CScript a_or_b;
151  a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
152  BOOST_CHECK(::IsStandard(a_or_b, whichType));
153 
154  CScript escrow;
155  escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
156  BOOST_CHECK(::IsStandard(escrow, whichType));
157 
158  CScript one_of_four;
159  one_of_four << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << ToByteVector(key[3].GetPubKey()) << OP_4 << OP_CHECKMULTISIG;
160  BOOST_CHECK(!::IsStandard(one_of_four, whichType));
161 
162  CScript malformed[6];
163  malformed[0] << OP_3 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
164  malformed[1] << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
165  malformed[2] << OP_0 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
166  malformed[3] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_0 << OP_CHECKMULTISIG;
167  malformed[4] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_CHECKMULTISIG;
168  malformed[5] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey());
169 
170  for (int i = 0; i < 6; i++)
171  BOOST_CHECK(!::IsStandard(malformed[i], whichType));
172 }
173 
174 BOOST_AUTO_TEST_CASE(multisig_Sign)
175 {
176  // Test SignSignature() (and therefore the version of Solver() that signs transactions)
177  FillableSigningProvider keystore;
178  CKey key[4];
179  for (int i = 0; i < 4; i++)
180  {
181  key[i].MakeNewKey(true);
182  BOOST_CHECK(keystore.AddKey(key[i]));
183  }
184 
185  CScript a_and_b;
186  a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
187 
188  CScript a_or_b;
189  a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
190 
191  CScript escrow;
192  escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
193 
194  CMutableTransaction txFrom; // Funding transaction
195  txFrom.vout.resize(3);
196  txFrom.vout[0].scriptPubKey = a_and_b;
197  txFrom.vout[1].scriptPubKey = a_or_b;
198  txFrom.vout[2].scriptPubKey = escrow;
199 
200  CMutableTransaction txTo[3]; // Spending transaction
201  for (int i = 0; i < 3; i++)
202  {
203  txTo[i].vin.resize(1);
204  txTo[i].vout.resize(1);
205  txTo[i].vin[0].prevout.n = i;
206  txTo[i].vin[0].prevout.hash = txFrom.GetHash();
207  txTo[i].vout[0].nValue = 1;
208  }
209 
210  for (int i = 0; i < 3; i++)
211  {
212  BOOST_CHECK_MESSAGE(SignSignature(keystore, CTransaction(txFrom), txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
213  }
214 }
215 
216 
ScriptErrorString
std::string ScriptErrorString(const ScriptError serror)
Definition: script_error.cpp:10
policy.h
CMutableTransaction::vin
std::vector< CTxIn > vin
Definition: transaction.h:346
CKey::MakeNewKey
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
Definition: key.cpp:160
SigVersion::BASE
@ BASE
Bare scripts and BIP16 P2SH-wrapped redeemscripts.
IsStandard
bool IsStandard(const CScript &scriptPubKey, TxoutType &whichType)
Definition: policy.cpp:53
TxoutType
TxoutType
Definition: standard.h:59
flags
int flags
Definition: bitcoin-tx.cpp:513
SCRIPT_ERR_OK
@ SCRIPT_ERR_OK
Definition: script_error.h:13
setup_common.h
FillableSigningProvider
Fillable signing provider that keeps keys in an address->secret map.
Definition: signingprovider.h:91
uint256.h
OP_CHECKMULTISIG
@ OP_CHECKMULTISIG
Definition: script.h:185
SCRIPT_ERR_SIG_DER
@ SCRIPT_ERR_SIG_DER
Definition: script_error.h:46
interpreter.h
OP_3
@ OP_3
Definition: script.h:79
SCRIPT_ERR_EVAL_FALSE
@ SCRIPT_ERR_EVAL_FALSE
Definition: script_error.h:15
BOOST_FIXTURE_TEST_SUITE
#define BOOST_FIXTURE_TEST_SUITE(a, b)
Definition: object.cpp:14
CScript::clear
void clear()
Definition: script.h:549
BOOST_AUTO_TEST_SUITE_END
BOOST_AUTO_TEST_SUITE_END()
VerifyScript
bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, const CScriptWitness *witness, unsigned int flags, const BaseSignatureChecker &checker, ScriptError *serror)
Definition: interpreter.cpp:1969
FillableSigningProvider::AddKey
virtual bool AddKey(const CKey &key)
Definition: signingprovider.h:152
CTransaction
The basic transaction that is broadcasted on the network and contained in blocks.
Definition: transaction.h:259
ScriptError
enum ScriptError_t ScriptError
tinyformat.h
signingprovider.h
OP_1
@ OP_1
Definition: script.h:76
OP_0
@ OP_0
Definition: script.h:69
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(multisig_verify)
Definition: multisig_tests.cpp:38
ToByteVector
std::vector< unsigned char > ToByteVector(const T &in)
Definition: script.h:60
SignSignature
bool SignSignature(const SigningProvider &provider, const CScript &fromPubKey, CMutableTransaction &txTo, unsigned int nIn, const CAmount &amount, int nHashType)
Produce a script signature for a transaction.
Definition: sign.cpp:513
sign.h
CAmount
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
OP_4
@ OP_4
Definition: script.h:80
BasicTestingSetup
Basic testing setup.
Definition: setup_common.h:76
OP_2
@ OP_2
Definition: script.h:78
SCRIPT_ERR_INVALID_STACK_OPERATION
@ SCRIPT_ERR_INVALID_STACK_OPERATION
Definition: script_error.h:36
uint256
256-bit opaque blob.
Definition: uint256.h:124
MissingDataBehavior::ASSERT_FAIL
@ ASSERT_FAIL
Abort execution through assertion failure (for consensus code)
CScript
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:405
script.h
CMutableTransaction::vout
std::vector< CTxOut > vout
Definition: transaction.h:347
prevector::assign
void assign(size_type n, const T &val)
Definition: prevector.h:218
strprintf
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1164
key.h
SIGHASH_ALL
@ SIGHASH_ALL
Definition: interpreter.h:27
CKey
An encapsulated private key.
Definition: key.h:26
SignatureHash
uint256 SignatureHash(const CScript &scriptCode, const T &txTo, unsigned int nIn, int nHashType, const CAmount &amount, SigVersion sigversion, const PrecomputedTransactionData *cache)
Definition: interpreter.cpp:1590
script_error.h
SCRIPT_VERIFY_P2SH
@ SCRIPT_VERIFY_P2SH
Definition: interpreter.h:46
MutableTransactionSignatureChecker
GenericTransactionSignatureChecker< CMutableTransaction > MutableTransactionSignatureChecker
Definition: interpreter.h:300
CMutableTransaction::GetHash
uint256 GetHash() const
Compute the hash of this CMutableTransaction.
Definition: transaction.cpp:62
CMutableTransaction
A mutable version of CTransaction.
Definition: transaction.h:344
sign_multisig
static CScript sign_multisig(const CScript &scriptPubKey, const std::vector< CKey > &keys, const CTransaction &transaction, int whichIn)
Definition: multisig_tests.cpp:22
GetPubKey
static bool GetPubKey(const SigningProvider &provider, const SignatureData &sigdata, const CKeyID &address, CPubKey &pubkey)
Definition: sign.cpp:104
BOOST_CHECK
#define BOOST_CHECK(expr)
Definition: object.cpp:17
SCRIPT_VERIFY_STRICTENC
@ SCRIPT_VERIFY_STRICTENC
Definition: interpreter.h:51