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