2016-12-31 18:01:21 +00:00
|
|
|
// Copyright (c) 2011-2016 The Bitcoin Core developers
|
2014-12-13 04:09:33 +00:00
|
|
|
// Distributed under the MIT software license, see the accompanying
|
2014-03-18 09:11:00 +00:00
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
2011-09-28 16:30:06 +00:00
|
|
|
|
2013-04-13 05:13:08 +00:00
|
|
|
#include "key.h"
|
2011-09-28 16:30:06 +00:00
|
|
|
#include "keystore.h"
|
2014-10-11 22:41:05 +00:00
|
|
|
#include "policy/policy.h"
|
2014-08-20 15:37:40 +00:00
|
|
|
#include "script/script.h"
|
2014-11-13 19:27:38 +00:00
|
|
|
#include "script/script_error.h"
|
2014-08-27 18:11:41 +00:00
|
|
|
#include "script/interpreter.h"
|
2014-08-27 15:22:33 +00:00
|
|
|
#include "script/sign.h"
|
2016-04-18 13:12:46 +00:00
|
|
|
#include "script/ismine.h"
|
2013-04-13 05:13:08 +00:00
|
|
|
#include "uint256.h"
|
2015-03-12 08:34:42 +00:00
|
|
|
#include "test/test_bitcoin.h"
|
2013-04-13 05:13:08 +00:00
|
|
|
|
2014-08-29 20:07:39 +00:00
|
|
|
|
2013-04-13 05:13:08 +00:00
|
|
|
#include <boost/test/unit_test.hpp>
|
2011-09-28 16:30:06 +00:00
|
|
|
|
2016-12-05 07:03:53 +00:00
|
|
|
typedef std::vector<unsigned char> valtype;
|
2011-09-28 16:30:06 +00:00
|
|
|
|
2015-03-12 08:34:42 +00:00
|
|
|
BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup)
|
2011-09-28 16:30:06 +00:00
|
|
|
|
|
|
|
CScript
|
2016-12-05 07:03:53 +00:00
|
|
|
sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transaction, int whichIn)
|
2011-09-28 16:30:06 +00:00
|
|
|
{
|
2015-12-27 18:49:08 +00:00
|
|
|
uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL, 0, SIGVERSION_BASE);
|
2011-09-28 16:30:06 +00:00
|
|
|
|
|
|
|
CScript result;
|
|
|
|
result << OP_0; // CHECKMULTISIG bug workaround
|
2017-06-02 01:18:57 +00:00
|
|
|
for (const CKey &key : keys)
|
2011-09-28 16:30:06 +00:00
|
|
|
{
|
2016-12-05 07:03:53 +00:00
|
|
|
std::vector<unsigned char> vchSig;
|
2011-09-28 16:30:06 +00:00
|
|
|
BOOST_CHECK(key.Sign(hash, vchSig));
|
|
|
|
vchSig.push_back((unsigned char)SIGHASH_ALL);
|
|
|
|
result << vchSig;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(multisig_verify)
|
|
|
|
{
|
2012-11-13 22:03:25 +00:00
|
|
|
unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
|
|
|
|
|
2014-11-13 19:27:38 +00:00
|
|
|
ScriptError err;
|
2011-09-28 16:30:06 +00:00
|
|
|
CKey key[4];
|
2016-03-31 12:51:29 +00:00
|
|
|
CAmount amount = 0;
|
2011-09-28 16:30:06 +00:00
|
|
|
for (int i = 0; i < 4; i++)
|
2012-02-20 17:32:33 +00:00
|
|
|
key[i].MakeNewKey(true);
|
2011-09-28 16:30:06 +00:00
|
|
|
|
|
|
|
CScript a_and_b;
|
2014-09-25 02:54:08 +00:00
|
|
|
a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
|
2011-09-28 16:30:06 +00:00
|
|
|
|
|
|
|
CScript a_or_b;
|
2014-09-25 02:54:08 +00:00
|
|
|
a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
|
2011-09-28 16:30:06 +00:00
|
|
|
|
|
|
|
CScript escrow;
|
2014-09-25 02:54:08 +00:00
|
|
|
escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
|
2011-09-28 16:30:06 +00:00
|
|
|
|
2014-06-07 11:53:27 +00:00
|
|
|
CMutableTransaction txFrom; // Funding transaction
|
2011-09-28 16:30:06 +00:00
|
|
|
txFrom.vout.resize(3);
|
|
|
|
txFrom.vout[0].scriptPubKey = a_and_b;
|
|
|
|
txFrom.vout[1].scriptPubKey = a_or_b;
|
|
|
|
txFrom.vout[2].scriptPubKey = escrow;
|
|
|
|
|
2014-06-07 11:53:27 +00:00
|
|
|
CMutableTransaction txTo[3]; // Spending transaction
|
2011-09-28 16:30:06 +00:00
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
txTo[i].vin.resize(1);
|
|
|
|
txTo[i].vout.resize(1);
|
|
|
|
txTo[i].vin[0].prevout.n = i;
|
|
|
|
txTo[i].vin[0].prevout.hash = txFrom.GetHash();
|
|
|
|
txTo[i].vout[0].nValue = 1;
|
|
|
|
}
|
|
|
|
|
2016-12-05 07:03:53 +00:00
|
|
|
std::vector<CKey> keys;
|
2011-09-28 16:30:06 +00:00
|
|
|
CScript s;
|
|
|
|
|
|
|
|
// Test a AND b:
|
2014-12-19 21:49:00 +00:00
|
|
|
keys.assign(1,key[0]);
|
|
|
|
keys.push_back(key[1]);
|
2011-09-28 16:30:06 +00:00
|
|
|
s = sign_multisig(a_and_b, keys, txTo[0], 0);
|
2016-03-31 12:51:29 +00:00
|
|
|
BOOST_CHECK(VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err));
|
2014-11-13 19:27:38 +00:00
|
|
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
2011-09-28 16:30:06 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
{
|
2014-12-19 21:49:00 +00:00
|
|
|
keys.assign(1,key[i]);
|
2011-09-28 16:30:06 +00:00
|
|
|
s = sign_multisig(a_and_b, keys, txTo[0], 0);
|
2016-03-31 12:51:29 +00:00
|
|
|
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 1: %d", i));
|
2014-11-13 19:27:38 +00:00
|
|
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
|
2011-09-28 16:30:06 +00:00
|
|
|
|
2014-12-19 21:49:00 +00:00
|
|
|
keys.assign(1,key[1]);
|
|
|
|
keys.push_back(key[i]);
|
2011-09-28 16:30:06 +00:00
|
|
|
s = sign_multisig(a_and_b, keys, txTo[0], 0);
|
2016-03-31 12:51:29 +00:00
|
|
|
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 2: %d", i));
|
2014-11-13 19:27:38 +00:00
|
|
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
2011-09-28 16:30:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Test a OR b:
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
{
|
2014-12-19 21:49:00 +00:00
|
|
|
keys.assign(1,key[i]);
|
2011-09-28 16:30:06 +00:00
|
|
|
s = sign_multisig(a_or_b, keys, txTo[1], 0);
|
|
|
|
if (i == 0 || i == 1)
|
2014-11-13 19:27:38 +00:00
|
|
|
{
|
2016-03-31 12:51:29 +00:00
|
|
|
BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i));
|
2014-11-13 19:27:38 +00:00
|
|
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
|
|
|
}
|
2011-09-28 16:30:06 +00:00
|
|
|
else
|
2014-11-13 19:27:38 +00:00
|
|
|
{
|
2016-03-31 12:51:29 +00:00
|
|
|
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i));
|
2014-11-13 19:27:38 +00:00
|
|
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
|
|
|
}
|
2011-09-28 16:30:06 +00:00
|
|
|
}
|
|
|
|
s.clear();
|
|
|
|
s << OP_0 << OP_1;
|
2016-03-31 12:51:29 +00:00
|
|
|
BOOST_CHECK(!VerifyScript(s, a_or_b, NULL, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err));
|
2014-11-13 19:27:38 +00:00
|
|
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));
|
2011-09-28 16:30:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
for (int j = 0; j < 4; j++)
|
|
|
|
{
|
2014-12-19 21:49:00 +00:00
|
|
|
keys.assign(1,key[i]);
|
|
|
|
keys.push_back(key[j]);
|
2011-09-28 16:30:06 +00:00
|
|
|
s = sign_multisig(escrow, keys, txTo[2], 0);
|
|
|
|
if (i < j && i < 3 && j < 3)
|
2014-11-13 19:27:38 +00:00
|
|
|
{
|
2016-03-31 12:51:29 +00:00
|
|
|
BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, NULL, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 1: %d %d", i, j));
|
2014-11-13 19:27:38 +00:00
|
|
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
|
|
|
}
|
2011-09-28 16:30:06 +00:00
|
|
|
else
|
2014-11-13 19:27:38 +00:00
|
|
|
{
|
2016-03-31 12:51:29 +00:00
|
|
|
BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, NULL, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 2: %d %d", i, j));
|
2014-11-13 19:27:38 +00:00
|
|
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
|
|
|
}
|
2011-09-28 16:30:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(multisig_IsStandard)
|
|
|
|
{
|
2011-10-03 17:05:43 +00:00
|
|
|
CKey key[4];
|
|
|
|
for (int i = 0; i < 4; i++)
|
2012-02-20 17:32:33 +00:00
|
|
|
key[i].MakeNewKey(true);
|
2011-09-28 16:30:06 +00:00
|
|
|
|
2013-06-24 19:09:50 +00:00
|
|
|
txnouttype whichType;
|
|
|
|
|
2011-09-28 16:30:06 +00:00
|
|
|
CScript a_and_b;
|
2014-09-25 02:54:08 +00:00
|
|
|
a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
|
2013-06-24 19:09:50 +00:00
|
|
|
BOOST_CHECK(::IsStandard(a_and_b, whichType));
|
2011-09-28 16:30:06 +00:00
|
|
|
|
|
|
|
CScript a_or_b;
|
2014-09-25 02:54:08 +00:00
|
|
|
a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
|
2013-06-24 19:09:50 +00:00
|
|
|
BOOST_CHECK(::IsStandard(a_or_b, whichType));
|
2011-09-28 16:30:06 +00:00
|
|
|
|
|
|
|
CScript escrow;
|
2014-09-25 02:54:08 +00:00
|
|
|
escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
|
2013-06-24 19:09:50 +00:00
|
|
|
BOOST_CHECK(::IsStandard(escrow, whichType));
|
2011-10-03 17:05:43 +00:00
|
|
|
|
|
|
|
CScript one_of_four;
|
2014-09-25 02:54:08 +00:00
|
|
|
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;
|
2013-06-24 19:09:50 +00:00
|
|
|
BOOST_CHECK(!::IsStandard(one_of_four, whichType));
|
2011-10-03 17:05:43 +00:00
|
|
|
|
|
|
|
CScript malformed[6];
|
2014-09-25 02:54:08 +00:00
|
|
|
malformed[0] << OP_3 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
|
|
|
|
malformed[1] << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
|
|
|
|
malformed[2] << OP_0 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
|
|
|
|
malformed[3] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_0 << OP_CHECKMULTISIG;
|
|
|
|
malformed[4] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_CHECKMULTISIG;
|
|
|
|
malformed[5] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey());
|
2011-10-03 17:05:43 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < 6; i++)
|
2013-06-24 19:09:50 +00:00
|
|
|
BOOST_CHECK(!::IsStandard(malformed[i], whichType));
|
2011-09-28 16:30:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(multisig_Solver1)
|
|
|
|
{
|
|
|
|
// Tests Solver() that returns lists of keys that are
|
|
|
|
// required to satisfy a ScriptPubKey
|
|
|
|
//
|
2014-08-27 15:47:17 +00:00
|
|
|
// Also tests IsMine() and ExtractDestination()
|
2011-09-28 16:30:06 +00:00
|
|
|
//
|
2014-08-27 15:47:17 +00:00
|
|
|
// Note: ExtractDestination for the multisignature transactions
|
2011-09-28 16:30:06 +00:00
|
|
|
// always returns false for this release, even if you have
|
|
|
|
// one key that would satisfy an (a|b) or 2-of-3 keys needed
|
|
|
|
// to spend an escrow transaction.
|
|
|
|
//
|
2012-01-02 07:27:41 +00:00
|
|
|
CBasicKeyStore keystore, emptykeystore, partialkeystore;
|
2011-09-28 16:30:06 +00:00
|
|
|
CKey key[3];
|
2012-05-14 21:44:52 +00:00
|
|
|
CTxDestination keyaddr[3];
|
2011-09-28 16:30:06 +00:00
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
{
|
2012-02-20 17:32:33 +00:00
|
|
|
key[i].MakeNewKey(true);
|
2011-09-28 16:30:06 +00:00
|
|
|
keystore.AddKey(key[i]);
|
2012-05-14 21:44:52 +00:00
|
|
|
keyaddr[i] = key[i].GetPubKey().GetID();
|
2011-09-28 16:30:06 +00:00
|
|
|
}
|
2012-01-02 07:27:41 +00:00
|
|
|
partialkeystore.AddKey(key[0]);
|
2011-09-28 16:30:06 +00:00
|
|
|
|
|
|
|
{
|
2016-12-05 07:03:53 +00:00
|
|
|
std::vector<valtype> solutions;
|
2011-11-08 18:20:29 +00:00
|
|
|
txnouttype whichType;
|
2011-09-28 16:30:06 +00:00
|
|
|
CScript s;
|
2014-09-25 02:54:08 +00:00
|
|
|
s << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
|
2011-10-03 17:05:43 +00:00
|
|
|
BOOST_CHECK(Solver(s, whichType, solutions));
|
2011-09-28 16:30:06 +00:00
|
|
|
BOOST_CHECK(solutions.size() == 1);
|
2012-05-14 21:44:52 +00:00
|
|
|
CTxDestination addr;
|
|
|
|
BOOST_CHECK(ExtractDestination(s, addr));
|
2011-09-28 16:30:06 +00:00
|
|
|
BOOST_CHECK(addr == keyaddr[0]);
|
|
|
|
BOOST_CHECK(IsMine(keystore, s));
|
|
|
|
BOOST_CHECK(!IsMine(emptykeystore, s));
|
|
|
|
}
|
|
|
|
{
|
2016-12-05 07:03:53 +00:00
|
|
|
std::vector<valtype> solutions;
|
2011-11-08 18:20:29 +00:00
|
|
|
txnouttype whichType;
|
2011-09-28 16:30:06 +00:00
|
|
|
CScript s;
|
2014-09-25 02:54:08 +00:00
|
|
|
s << OP_DUP << OP_HASH160 << ToByteVector(key[0].GetPubKey().GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
|
2011-10-03 17:05:43 +00:00
|
|
|
BOOST_CHECK(Solver(s, whichType, solutions));
|
2011-09-28 16:30:06 +00:00
|
|
|
BOOST_CHECK(solutions.size() == 1);
|
2012-05-14 21:44:52 +00:00
|
|
|
CTxDestination addr;
|
|
|
|
BOOST_CHECK(ExtractDestination(s, addr));
|
2011-09-28 16:30:06 +00:00
|
|
|
BOOST_CHECK(addr == keyaddr[0]);
|
|
|
|
BOOST_CHECK(IsMine(keystore, s));
|
|
|
|
BOOST_CHECK(!IsMine(emptykeystore, s));
|
|
|
|
}
|
|
|
|
{
|
2016-12-05 07:03:53 +00:00
|
|
|
std::vector<valtype> solutions;
|
2011-11-08 18:20:29 +00:00
|
|
|
txnouttype whichType;
|
2011-09-28 16:30:06 +00:00
|
|
|
CScript s;
|
2014-09-25 02:54:08 +00:00
|
|
|
s << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
|
2011-10-03 17:05:43 +00:00
|
|
|
BOOST_CHECK(Solver(s, whichType, solutions));
|
2013-03-07 17:38:25 +00:00
|
|
|
BOOST_CHECK_EQUAL(solutions.size(), 4U);
|
2012-05-14 21:44:52 +00:00
|
|
|
CTxDestination addr;
|
|
|
|
BOOST_CHECK(!ExtractDestination(s, addr));
|
2011-09-28 16:30:06 +00:00
|
|
|
BOOST_CHECK(IsMine(keystore, s));
|
|
|
|
BOOST_CHECK(!IsMine(emptykeystore, s));
|
2012-01-02 07:27:41 +00:00
|
|
|
BOOST_CHECK(!IsMine(partialkeystore, s));
|
2011-09-28 16:30:06 +00:00
|
|
|
}
|
|
|
|
{
|
2016-12-05 07:03:53 +00:00
|
|
|
std::vector<valtype> solutions;
|
2011-11-08 18:20:29 +00:00
|
|
|
txnouttype whichType;
|
2011-09-28 16:30:06 +00:00
|
|
|
CScript s;
|
2014-09-25 02:54:08 +00:00
|
|
|
s << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
|
2011-10-03 17:05:43 +00:00
|
|
|
BOOST_CHECK(Solver(s, whichType, solutions));
|
2013-03-07 17:38:25 +00:00
|
|
|
BOOST_CHECK_EQUAL(solutions.size(), 4U);
|
2016-12-05 07:03:53 +00:00
|
|
|
std::vector<CTxDestination> addrs;
|
2011-10-03 17:05:43 +00:00
|
|
|
int nRequired;
|
2012-05-14 21:44:52 +00:00
|
|
|
BOOST_CHECK(ExtractDestinations(s, whichType, addrs, nRequired));
|
2011-10-03 17:05:43 +00:00
|
|
|
BOOST_CHECK(addrs[0] == keyaddr[0]);
|
|
|
|
BOOST_CHECK(addrs[1] == keyaddr[1]);
|
2012-06-21 18:37:49 +00:00
|
|
|
BOOST_CHECK(nRequired == 1);
|
2011-09-28 16:30:06 +00:00
|
|
|
BOOST_CHECK(IsMine(keystore, s));
|
|
|
|
BOOST_CHECK(!IsMine(emptykeystore, s));
|
2012-01-02 07:27:41 +00:00
|
|
|
BOOST_CHECK(!IsMine(partialkeystore, s));
|
2011-09-28 16:30:06 +00:00
|
|
|
}
|
|
|
|
{
|
2016-12-05 07:03:53 +00:00
|
|
|
std::vector<valtype> solutions;
|
2011-11-08 18:20:29 +00:00
|
|
|
txnouttype whichType;
|
2011-09-28 16:30:06 +00:00
|
|
|
CScript s;
|
2014-09-25 02:54:08 +00:00
|
|
|
s << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
|
2011-10-03 17:05:43 +00:00
|
|
|
BOOST_CHECK(Solver(s, whichType, solutions));
|
|
|
|
BOOST_CHECK(solutions.size() == 5);
|
2011-09-28 16:30:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(multisig_Sign)
|
|
|
|
{
|
|
|
|
// Test SignSignature() (and therefore the version of Solver() that signs transactions)
|
|
|
|
CBasicKeyStore keystore;
|
|
|
|
CKey key[4];
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
{
|
2012-02-20 17:32:33 +00:00
|
|
|
key[i].MakeNewKey(true);
|
2011-09-28 16:30:06 +00:00
|
|
|
keystore.AddKey(key[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
CScript a_and_b;
|
2014-09-25 02:54:08 +00:00
|
|
|
a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
|
2011-09-28 16:30:06 +00:00
|
|
|
|
|
|
|
CScript a_or_b;
|
2014-09-25 02:54:08 +00:00
|
|
|
a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
|
2011-09-28 16:30:06 +00:00
|
|
|
|
|
|
|
CScript escrow;
|
2014-09-25 02:54:08 +00:00
|
|
|
escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
|
2011-09-28 16:30:06 +00:00
|
|
|
|
2014-06-07 11:53:27 +00:00
|
|
|
CMutableTransaction txFrom; // Funding transaction
|
2011-09-28 16:30:06 +00:00
|
|
|
txFrom.vout.resize(3);
|
|
|
|
txFrom.vout[0].scriptPubKey = a_and_b;
|
|
|
|
txFrom.vout[1].scriptPubKey = a_or_b;
|
|
|
|
txFrom.vout[2].scriptPubKey = escrow;
|
|
|
|
|
2014-06-07 11:53:27 +00:00
|
|
|
CMutableTransaction txTo[3]; // Spending transaction
|
2011-09-28 16:30:06 +00:00
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
txTo[i].vin.resize(1);
|
|
|
|
txTo[i].vout.resize(1);
|
|
|
|
txTo[i].vin[0].prevout.n = i;
|
|
|
|
txTo[i].vin[0].prevout.hash = txFrom.GetHash();
|
|
|
|
txTo[i].vout[0].nValue = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
{
|
2016-03-31 12:54:58 +00:00
|
|
|
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
|
2011-09-28 16:30:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|