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