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 <tinyformat.h> 14 #include <uint256.h> 15 16 17 #include <boost/test/unit_test.hpp> 18 19 BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup) 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 { 40 unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC; 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 const auto is_standard{[](const CScript& spk) { 145 TxoutType type; 146 bool res{::IsStandard(spk, std::nullopt, type)}; 147 if (res) { 148 BOOST_CHECK_EQUAL(type, TxoutType::MULTISIG); 149 } 150 return res; 151 }}; 152 153 CScript a_and_b; 154 a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; 155 BOOST_CHECK(is_standard(a_and_b)); 156 157 CScript a_or_b; 158 a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; 159 BOOST_CHECK(is_standard(a_or_b)); 160 161 CScript escrow; 162 escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG; 163 BOOST_CHECK(is_standard(escrow)); 164 165 CScript one_of_four; 166 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; 167 BOOST_CHECK(!is_standard(one_of_four)); 168 169 CScript malformed[6]; 170 malformed[0] << OP_3 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; 171 malformed[1] << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_3 << OP_CHECKMULTISIG; 172 malformed[2] << OP_0 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; 173 malformed[3] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_0 << OP_CHECKMULTISIG; 174 malformed[4] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_CHECKMULTISIG; 175 malformed[5] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()); 176 177 for (int i = 0; i < 6; i++) { 178 BOOST_CHECK(!is_standard(malformed[i])); 179 } 180 } 181 182 BOOST_AUTO_TEST_CASE(multisig_Sign) 183 { 184 // Test SignSignature() (and therefore the version of Solver() that signs transactions) 185 FillableSigningProvider keystore; 186 CKey key[4]; 187 for (int i = 0; i < 4; i++) 188 { 189 key[i].MakeNewKey(true); 190 BOOST_CHECK(keystore.AddKey(key[i])); 191 } 192 193 CScript a_and_b; 194 a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; 195 196 CScript a_or_b; 197 a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; 198 199 CScript escrow; 200 escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG; 201 202 CMutableTransaction txFrom; // Funding transaction 203 txFrom.vout.resize(3); 204 txFrom.vout[0].scriptPubKey = a_and_b; 205 txFrom.vout[1].scriptPubKey = a_or_b; 206 txFrom.vout[2].scriptPubKey = escrow; 207 208 CMutableTransaction txTo[3]; // Spending transaction 209 for (int i = 0; i < 3; i++) 210 { 211 txTo[i].vin.resize(1); 212 txTo[i].vout.resize(1); 213 txTo[i].vin[0].prevout.n = i; 214 txTo[i].vin[0].prevout.hash = txFrom.GetHash(); 215 txTo[i].vout[0].nValue = 1; 216 } 217 218 for (int i = 0; i < 3; i++) 219 { 220 SignatureData empty; 221 BOOST_CHECK_MESSAGE(SignSignature(keystore, CTransaction(txFrom), txTo[i], 0, SIGHASH_ALL, empty), strprintf("SignSignature %d", i)); 222 } 223 } 224 225 226 BOOST_AUTO_TEST_SUITE_END()