multisig_tests.cpp raw

   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()
 229