/ src / test / multisig_tests.cpp
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()