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

Generated by: LCOV version 2.0-1