LCOV - code coverage report
Current view: top level - src/test - multisig_tests.cpp (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 99.3 % 138 137
Test Date: 2024-11-04 05:10:19 Functions: 100.0 % 8 8
Branches: 52.2 % 738 385

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

Generated by: LCOV version 2.0-1