LCOV - code coverage report
Current view: top level - src/test - multisig_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 160 160 100.0 %
Date: 2015-10-12 22:39:14 Functions: 11 19 57.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2011-2013 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 "keystore.h"
       7             : #include "policy/policy.h"
       8             : #include "script/script.h"
       9             : #include "script/script_error.h"
      10             : #include "script/interpreter.h"
      11             : #include "script/sign.h"
      12             : #include "uint256.h"
      13             : #include "test/test_bitcoin.h"
      14             : 
      15             : #ifdef ENABLE_WALLET
      16             : #include "wallet/wallet_ismine.h"
      17             : #endif
      18             : 
      19             : #include <boost/foreach.hpp>
      20             : #include <boost/test/unit_test.hpp>
      21             : 
      22             : using namespace std;
      23             : 
      24             : typedef vector<unsigned char> valtype;
      25             : 
      26           1 : BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup)
      27             : 
      28             : CScript
      29          29 : sign_multisig(CScript scriptPubKey, vector<CKey> keys, CTransaction transaction, int whichIn)
      30             : {
      31          29 :     uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL);
      32             : 
      33             :     CScript result;
      34          29 :     result << OP_0; // CHECKMULTISIG bug workaround
      35         424 :     BOOST_FOREACH(const CKey &key, keys)
      36             :     {
      37             :         vector<unsigned char> vchSig;
      38         400 :         BOOST_CHECK(key.Sign(hash, vchSig));
      39          50 :         vchSig.push_back((unsigned char)SIGHASH_ALL);
      40          50 :         result << vchSig;
      41             :     }
      42          29 :     return result;
      43             : }
      44             : 
      45           6 : BOOST_AUTO_TEST_CASE(multisig_verify)
      46             : {
      47           1 :     unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
      48             : 
      49             :     ScriptError err;
      50           5 :     CKey key[4];
      51           4 :     for (int i = 0; i < 4; i++)
      52           4 :         key[i].MakeNewKey(true);
      53             : 
      54             :     CScript a_and_b;
      55           3 :     a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
      56             : 
      57             :     CScript a_or_b;
      58           3 :     a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
      59             : 
      60             :     CScript escrow;
      61           4 :     escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
      62             : 
      63           1 :     CMutableTransaction txFrom;  // Funding transaction
      64           2 :     txFrom.vout.resize(3);
      65           1 :     txFrom.vout[0].scriptPubKey = a_and_b;
      66           1 :     txFrom.vout[1].scriptPubKey = a_or_b;
      67           1 :     txFrom.vout[2].scriptPubKey = escrow;
      68             : 
      69           7 :     CMutableTransaction txTo[3]; // Spending transaction
      70           3 :     for (int i = 0; i < 3; i++)
      71             :     {
      72           6 :         txTo[i].vin.resize(1);
      73           6 :         txTo[i].vout.resize(1);
      74           3 :         txTo[i].vin[0].prevout.n = i;
      75           3 :         txTo[i].vin[0].prevout.hash = txFrom.GetHash();
      76           3 :         txTo[i].vout[0].nValue = 1;
      77             :     }
      78             : 
      79           1 :     vector<CKey> keys;
      80             :     CScript s;
      81             : 
      82             :     // Test a AND b:
      83             :     keys.assign(1,key[0]);
      84           1 :     keys.push_back(key[1]);
      85           5 :     s = sign_multisig(a_and_b, keys, txTo[0], 0);
      86           8 :     BOOST_CHECK(VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err));
      87           7 :     BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
      88             : 
      89           5 :     for (int i = 0; i < 4; i++)
      90             :     {
      91           4 :         keys.assign(1,key[i]);
      92          20 :         s = sign_multisig(a_and_b, keys, txTo[0], 0);
      93          32 :         BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err), strprintf("a&b 1: %d", i));
      94          28 :         BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
      95             : 
      96             :         keys.assign(1,key[1]);
      97           4 :         keys.push_back(key[i]);
      98          20 :         s = sign_multisig(a_and_b, keys, txTo[0], 0);
      99          32 :         BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err), strprintf("a&b 2: %d", i));
     100          28 :         BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
     101             :     }
     102             : 
     103             :     // Test a OR b:
     104           5 :     for (int i = 0; i < 4; i++)
     105             :     {
     106           4 :         keys.assign(1,key[i]);
     107          20 :         s = sign_multisig(a_or_b, keys, txTo[1], 0);
     108           4 :         if (i == 0 || i == 1)
     109             :         {
     110          16 :             BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err), strprintf("a|b: %d", i));
     111          14 :             BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
     112             :         }
     113             :         else
     114             :         {
     115          16 :             BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err), strprintf("a|b: %d", i));
     116          14 :             BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
     117             :         }
     118             :     }
     119             :     s.clear();
     120           1 :     s << OP_0 << OP_1;
     121           8 :     BOOST_CHECK(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err));
     122           7 :     BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));
     123             : 
     124             : 
     125           5 :     for (int i = 0; i < 4; i++)
     126          20 :         for (int j = 0; j < 4; j++)
     127             :         {
     128          16 :             keys.assign(1,key[i]);
     129          16 :             keys.push_back(key[j]);
     130          80 :             s = sign_multisig(escrow, keys, txTo[2], 0);
     131          16 :             if (i < j && i < 3 && j < 3)
     132             :             {
     133          24 :                 BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], 0), &err), strprintf("escrow 1: %d %d", i, j));
     134          21 :                 BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
     135             :             }
     136             :             else
     137             :             {
     138         104 :                 BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], 0), &err), strprintf("escrow 2: %d %d", i, j));
     139          91 :                 BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
     140             :             }
     141           5 :         }
     142           1 : }
     143             : 
     144           6 : BOOST_AUTO_TEST_CASE(multisig_IsStandard)
     145             : {
     146           5 :     CKey key[4];
     147           4 :     for (int i = 0; i < 4; i++)
     148           4 :         key[i].MakeNewKey(true);
     149             : 
     150             :     txnouttype whichType;
     151             : 
     152             :     CScript a_and_b;
     153           3 :     a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
     154           8 :     BOOST_CHECK(::IsStandard(a_and_b, whichType));
     155             : 
     156             :     CScript a_or_b;
     157           3 :     a_or_b  << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
     158           8 :     BOOST_CHECK(::IsStandard(a_or_b, whichType));
     159             : 
     160             :     CScript escrow;
     161           4 :     escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
     162           7 :     BOOST_CHECK(::IsStandard(escrow, whichType));
     163             : 
     164             :     CScript one_of_four;
     165           5 :     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;
     166           8 :     BOOST_CHECK(!::IsStandard(one_of_four, whichType));
     167             : 
     168          13 :     CScript malformed[6];
     169           3 :     malformed[0] << OP_3 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
     170           3 :     malformed[1] << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
     171           3 :     malformed[2] << OP_0 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
     172           3 :     malformed[3] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_0 << OP_CHECKMULTISIG;
     173           3 :     malformed[4] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_CHECKMULTISIG;
     174           3 :     malformed[5] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey());
     175             : 
     176           7 :     for (int i = 0; i < 6; i++)
     177          53 :         BOOST_CHECK(!::IsStandard(malformed[i], whichType));
     178           1 : }
     179             : 
     180           6 : BOOST_AUTO_TEST_CASE(multisig_Solver1)
     181             : {
     182             :     // Tests Solver() that returns lists of keys that are
     183             :     // required to satisfy a ScriptPubKey
     184             :     //
     185             :     // Also tests IsMine() and ExtractDestination()
     186             :     //
     187             :     // Note: ExtractDestination for the multisignature transactions
     188             :     // always returns false for this release, even if you have
     189             :     // one key that would satisfy an (a|b) or 2-of-3 keys needed
     190             :     // to spend an escrow transaction.
     191             :     //
     192           2 :     CBasicKeyStore keystore, emptykeystore, partialkeystore;
     193           7 :     CKey key[3];
     194           7 :     CTxDestination keyaddr[3];
     195           3 :     for (int i = 0; i < 3; i++)
     196             :     {
     197           3 :         key[i].MakeNewKey(true);
     198           3 :         keystore.AddKey(key[i]);
     199           6 :         keyaddr[i] = key[i].GetPubKey().GetID();
     200             :     }
     201           1 :     partialkeystore.AddKey(key[0]);
     202             : 
     203             :     {
     204             :         vector<valtype> solutions;
     205             :         txnouttype whichType;
     206             :         CScript s;
     207           2 :         s << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
     208           8 :         BOOST_CHECK(Solver(s, whichType, solutions));
     209           9 :         BOOST_CHECK(solutions.size() == 1);
     210             :         CTxDestination addr;
     211           8 :         BOOST_CHECK(ExtractDestination(s, addr));
     212           8 :         BOOST_CHECK(addr == keyaddr[0]);
     213             : #ifdef ENABLE_WALLET
     214           8 :         BOOST_CHECK(IsMine(keystore, s));
     215           9 :         BOOST_CHECK(!IsMine(emptykeystore, s));
     216             : #endif
     217             :     }
     218             :     {
     219             :         vector<valtype> solutions;
     220             :         txnouttype whichType;
     221             :         CScript s;
     222           3 :         s << OP_DUP << OP_HASH160 << ToByteVector(key[0].GetPubKey().GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
     223           8 :         BOOST_CHECK(Solver(s, whichType, solutions));
     224           9 :         BOOST_CHECK(solutions.size() == 1);
     225             :         CTxDestination addr;
     226           8 :         BOOST_CHECK(ExtractDestination(s, addr));
     227           8 :         BOOST_CHECK(addr == keyaddr[0]);
     228             : #ifdef ENABLE_WALLET
     229           8 :         BOOST_CHECK(IsMine(keystore, s));
     230           9 :         BOOST_CHECK(!IsMine(emptykeystore, s));
     231             : #endif
     232             :     }
     233             :     {
     234             :         vector<valtype> solutions;
     235             :         txnouttype whichType;
     236             :         CScript s;
     237           3 :         s << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
     238           8 :         BOOST_CHECK(Solver(s, whichType, solutions));
     239           6 :         BOOST_CHECK_EQUAL(solutions.size(), 4U);
     240             :         CTxDestination addr;
     241           8 :         BOOST_CHECK(!ExtractDestination(s, addr));
     242             : #ifdef ENABLE_WALLET
     243           8 :         BOOST_CHECK(IsMine(keystore, s));
     244           8 :         BOOST_CHECK(!IsMine(emptykeystore, s));
     245           9 :         BOOST_CHECK(!IsMine(partialkeystore, s));
     246             : #endif
     247             :     }
     248             :     {
     249             :         vector<valtype> solutions;
     250             :         txnouttype whichType;
     251             :         CScript s;
     252           3 :         s << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
     253           8 :         BOOST_CHECK(Solver(s, whichType, solutions));
     254           6 :         BOOST_CHECK_EQUAL(solutions.size(), 4U);
     255           1 :         vector<CTxDestination> addrs;
     256             :         int nRequired;
     257           8 :         BOOST_CHECK(ExtractDestinations(s, whichType, addrs, nRequired));
     258           8 :         BOOST_CHECK(addrs[0] == keyaddr[0]);
     259           9 :         BOOST_CHECK(addrs[1] == keyaddr[1]);
     260           8 :         BOOST_CHECK(nRequired == 1);
     261             : #ifdef ENABLE_WALLET
     262           8 :         BOOST_CHECK(IsMine(keystore, s));
     263           8 :         BOOST_CHECK(!IsMine(emptykeystore, s));
     264           9 :         BOOST_CHECK(!IsMine(partialkeystore, s));
     265             : #endif
     266             :     }
     267             :     {
     268             :         vector<valtype> solutions;
     269             :         txnouttype whichType;
     270             :         CScript s;
     271           4 :         s << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
     272           8 :         BOOST_CHECK(Solver(s, whichType, solutions));
     273          10 :         BOOST_CHECK(solutions.size() == 5);
     274           1 :     }
     275           1 : }
     276             : 
     277           6 : BOOST_AUTO_TEST_CASE(multisig_Sign)
     278             : {
     279             :     // Test SignSignature() (and therefore the version of Solver() that signs transactions)
     280           1 :     CBasicKeyStore keystore;
     281           9 :     CKey key[4];
     282           4 :     for (int i = 0; i < 4; i++)
     283             :     {
     284           4 :         key[i].MakeNewKey(true);
     285           4 :         keystore.AddKey(key[i]);
     286             :     }
     287             : 
     288             :     CScript a_and_b;
     289           3 :     a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
     290             : 
     291             :     CScript a_or_b;
     292           3 :     a_or_b  << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
     293             : 
     294             :     CScript escrow;
     295           4 :     escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
     296             : 
     297           1 :     CMutableTransaction txFrom;  // Funding transaction
     298           2 :     txFrom.vout.resize(3);
     299           1 :     txFrom.vout[0].scriptPubKey = a_and_b;
     300           1 :     txFrom.vout[1].scriptPubKey = a_or_b;
     301           1 :     txFrom.vout[2].scriptPubKey = escrow;
     302             : 
     303           7 :     CMutableTransaction txTo[3]; // Spending transaction
     304           3 :     for (int i = 0; i < 3; i++)
     305             :     {
     306           6 :         txTo[i].vin.resize(1);
     307           6 :         txTo[i].vout.resize(1);
     308           3 :         txTo[i].vin[0].prevout.n = i;
     309           3 :         txTo[i].vin[0].prevout.hash = txFrom.GetHash();
     310           3 :         txTo[i].vout[0].nValue = 1;
     311             :     }
     312             : 
     313           4 :     for (int i = 0; i < 3; i++)
     314             :     {
     315          27 :         BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
     316           1 :     }
     317           1 : }
     318             : 
     319             : 
     320           3 : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.11