multisig_tests.cpp
1 // Copyright (c) 2011-2022 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 <test/util/transaction_utils.h> 14 #include <tinyformat.h> 15 #include <uint256.h> 16 17 18 #include <boost/test/unit_test.hpp> 19 20 BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup) 21 22 static CScript 23 sign_multisig(const CScript& scriptPubKey, const std::vector<CKey>& keys, const CTransaction& transaction, int whichIn) 24 { 25 uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL, 0, SigVersion::BASE); 26 27 CScript result; 28 result << OP_0; // CHECKMULTISIG bug workaround 29 for (const CKey &key : keys) 30 { 31 std::vector<unsigned char> vchSig; 32 BOOST_CHECK(key.Sign(hash, vchSig)); 33 vchSig.push_back((unsigned char)SIGHASH_ALL); 34 result << vchSig; 35 } 36 return result; 37 } 38 39 BOOST_AUTO_TEST_CASE(multisig_verify) 40 { 41 unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC; 42 43 ScriptError err; 44 CKey key[4]; 45 CAmount amount = 0; 46 for (int i = 0; i < 4; i++) 47 key[i].MakeNewKey(true); 48 49 CScript a_and_b; 50 a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; 51 52 CScript a_or_b; 53 a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; 54 55 CScript escrow; 56 escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG; 57 58 CMutableTransaction txFrom; // Funding transaction 59 txFrom.vout.resize(3); 60 txFrom.vout[0].scriptPubKey = a_and_b; 61 txFrom.vout[1].scriptPubKey = a_or_b; 62 txFrom.vout[2].scriptPubKey = escrow; 63 64 CMutableTransaction txTo[3]; // Spending transaction 65 for (int i = 0; i < 3; i++) 66 { 67 txTo[i].vin.resize(1); 68 txTo[i].vout.resize(1); 69 txTo[i].vin[0].prevout.n = i; 70 txTo[i].vin[0].prevout.hash = txFrom.GetHash(); 71 txTo[i].vout[0].nValue = 1; 72 } 73 74 std::vector<CKey> keys; 75 CScript s; 76 77 // Test a AND b: 78 keys.assign(1,key[0]); 79 keys.push_back(key[1]); 80 s = sign_multisig(a_and_b, keys, CTransaction(txTo[0]), 0); 81 BOOST_CHECK(VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount, MissingDataBehavior::ASSERT_FAIL), &err)); 82 BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); 83 84 for (int i = 0; i < 4; i++) 85 { 86 keys.assign(1,key[i]); 87 s = sign_multisig(a_and_b, keys, CTransaction(txTo[0]), 0); 88 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)); 89 BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err)); 90 91 keys.assign(1,key[1]); 92 keys.push_back(key[i]); 93 s = sign_multisig(a_and_b, keys, CTransaction(txTo[0]), 0); 94 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)); 95 BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); 96 } 97 98 // Test a OR b: 99 for (int i = 0; i < 4; i++) 100 { 101 keys.assign(1,key[i]); 102 s = sign_multisig(a_or_b, keys, CTransaction(txTo[1]), 0); 103 if (i == 0 || i == 1) 104 { 105 BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount, MissingDataBehavior::ASSERT_FAIL), &err), strprintf("a|b: %d", i)); 106 BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); 107 } 108 else 109 { 110 BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount, MissingDataBehavior::ASSERT_FAIL), &err), strprintf("a|b: %d", i)); 111 BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); 112 } 113 } 114 s.clear(); 115 s << OP_0 << OP_1; 116 BOOST_CHECK(!VerifyScript(s, a_or_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount, MissingDataBehavior::ASSERT_FAIL), &err)); 117 BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err)); 118 119 120 for (int i = 0; i < 4; i++) 121 for (int j = 0; j < 4; j++) 122 { 123 keys.assign(1,key[i]); 124 keys.push_back(key[j]); 125 s = sign_multisig(escrow, keys, CTransaction(txTo[2]), 0); 126 if (i < j && i < 3 && j < 3) 127 { 128 BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, nullptr, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount, MissingDataBehavior::ASSERT_FAIL), &err), strprintf("escrow 1: %d %d", i, j)); 129 BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); 130 } 131 else 132 { 133 BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, nullptr, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount, MissingDataBehavior::ASSERT_FAIL), &err), strprintf("escrow 2: %d %d", i, j)); 134 BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); 135 } 136 } 137 } 138 139 BOOST_AUTO_TEST_CASE(multisig_IsStandard) 140 { 141 CKey key[4]; 142 for (int i = 0; i < 4; i++) 143 key[i].MakeNewKey(true); 144 145 const auto is_standard{[](const CScript& spk) { 146 TxoutType type; 147 bool res{::IsStandard(spk, std::nullopt, type)}; 148 if (res) { 149 BOOST_CHECK_EQUAL(type, TxoutType::MULTISIG); 150 } 151 return res; 152 }}; 153 154 CScript a_and_b; 155 a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; 156 BOOST_CHECK(is_standard(a_and_b)); 157 158 CScript a_or_b; 159 a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; 160 BOOST_CHECK(is_standard(a_or_b)); 161 162 CScript escrow; 163 escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG; 164 BOOST_CHECK(is_standard(escrow)); 165 166 CScript one_of_four; 167 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; 168 BOOST_CHECK(!is_standard(one_of_four)); 169 170 CScript malformed[6]; 171 malformed[0] << OP_3 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; 172 malformed[1] << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_3 << OP_CHECKMULTISIG; 173 malformed[2] << OP_0 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; 174 malformed[3] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_0 << OP_CHECKMULTISIG; 175 malformed[4] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_CHECKMULTISIG; 176 malformed[5] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()); 177 178 for (int i = 0; i < 6; i++) { 179 BOOST_CHECK(!is_standard(malformed[i])); 180 } 181 } 182 183 BOOST_AUTO_TEST_CASE(multisig_Sign) 184 { 185 // Test SignSignature() (and therefore the version of Solver() that signs transactions) 186 FillableSigningProvider keystore; 187 CKey key[4]; 188 for (int i = 0; i < 4; i++) 189 { 190 key[i].MakeNewKey(true); 191 BOOST_CHECK(keystore.AddKey(key[i])); 192 } 193 194 CScript a_and_b; 195 a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; 196 197 CScript a_or_b; 198 a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; 199 200 CScript escrow; 201 escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG; 202 203 CMutableTransaction txFrom; // Funding transaction 204 txFrom.vout.resize(3); 205 txFrom.vout[0].scriptPubKey = a_and_b; 206 txFrom.vout[1].scriptPubKey = a_or_b; 207 txFrom.vout[2].scriptPubKey = escrow; 208 209 CMutableTransaction txTo[3]; // Spending transaction 210 for (int i = 0; i < 3; i++) 211 { 212 txTo[i].vin.resize(1); 213 txTo[i].vout.resize(1); 214 txTo[i].vin[0].prevout.n = i; 215 txTo[i].vin[0].prevout.hash = txFrom.GetHash(); 216 txTo[i].vout[0].nValue = 1; 217 } 218 219 for (int i = 0; i < 3; i++) 220 { 221 SignatureData empty; 222 BOOST_CHECK_MESSAGE(SignSignature(keystore, CTransaction(txFrom), txTo[i], 0, SIGHASH_ALL, empty), strprintf("SignSignature %d", i)); 223 } 224 } 225 226 227 BOOST_AUTO_TEST_SUITE_END()