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