mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-12-12 05:34:57 +01:00
OP_EVAL implementation
OP_EVAL is a new opcode that evaluates an item on the stack as a script. It enables a new type of bitcoin address that needs an arbitrarily complex script to redeem.
This commit is contained in:
@@ -20,9 +20,7 @@ using namespace boost::assign;
|
||||
typedef vector<unsigned char> valtype;
|
||||
|
||||
extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
|
||||
extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, int nHashType);
|
||||
extern bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType);
|
||||
extern bool Solver(const CScript& scriptPubKey, vector<vector<pair<opcodetype, valtype> > >& vSolutionsRet);
|
||||
extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, int& nSigOpCount, int nHashType);
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(multisig_tests)
|
||||
|
||||
@@ -76,24 +74,25 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
|
||||
|
||||
vector<CKey> keys;
|
||||
CScript s;
|
||||
int nUnused = 0;
|
||||
|
||||
// Test a AND b:
|
||||
keys.clear();
|
||||
keys += key[0],key[1]; // magic operator+= from boost.assign
|
||||
s = sign_multisig(a_and_b, keys, txTo[0], 0);
|
||||
BOOST_CHECK(VerifyScript(s, a_and_b, txTo[0], 0, 0));
|
||||
BOOST_CHECK(VerifyScript(s, a_and_b, txTo[0], 0, nUnused, 0));
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
keys.clear();
|
||||
keys += key[i];
|
||||
s = sign_multisig(a_and_b, keys, txTo[0], 0);
|
||||
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, txTo[0], 0, 0), strprintf("a&b 1: %d", i));
|
||||
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, txTo[0], 0, nUnused, 0), strprintf("a&b 1: %d", i));
|
||||
|
||||
keys.clear();
|
||||
keys += key[1],key[i];
|
||||
s = sign_multisig(a_and_b, keys, txTo[0], 0);
|
||||
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, txTo[0], 0, 0), strprintf("a&b 2: %d", i));
|
||||
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, txTo[0], 0, nUnused, 0), strprintf("a&b 2: %d", i));
|
||||
}
|
||||
|
||||
// Test a OR b:
|
||||
@@ -103,16 +102,16 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
|
||||
keys += key[i];
|
||||
s = sign_multisig(a_or_b, keys, txTo[1], 0);
|
||||
if (i == 0 || i == 1)
|
||||
BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, txTo[1], 0, 0), strprintf("a|b: %d", i));
|
||||
BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, txTo[1], 0, nUnused, 0), strprintf("a|b: %d", i));
|
||||
else
|
||||
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, txTo[1], 0, 0), strprintf("a|b: %d", i));
|
||||
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, txTo[1], 0, nUnused, 0), strprintf("a|b: %d", i));
|
||||
}
|
||||
s.clear();
|
||||
s << OP_0 << OP_0;
|
||||
BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, 0));
|
||||
BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, nUnused, 0));
|
||||
s.clear();
|
||||
s << OP_0 << OP_1;
|
||||
BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, 0));
|
||||
BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, nUnused, 0));
|
||||
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
@@ -122,16 +121,16 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
|
||||
keys += key[i],key[j];
|
||||
s = sign_multisig(escrow, keys, txTo[2], 0);
|
||||
if (i < j && i < 3 && j < 3)
|
||||
BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, txTo[2], 0, 0), strprintf("escrow 1: %d %d", i, j));
|
||||
BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, txTo[2], 0, nUnused, 0), strprintf("escrow 1: %d %d", i, j));
|
||||
else
|
||||
BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, txTo[2], 0, 0), strprintf("escrow 2: %d %d", i, j));
|
||||
BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, txTo[2], 0, nUnused, 0), strprintf("escrow 2: %d %d", i, j));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(multisig_IsStandard)
|
||||
{
|
||||
CKey key[3];
|
||||
for (int i = 0; i < 3; i++)
|
||||
CKey key[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
key[i].MakeNewKey();
|
||||
|
||||
CScript a_and_b;
|
||||
@@ -145,6 +144,21 @@ BOOST_AUTO_TEST_CASE(multisig_IsStandard)
|
||||
CScript escrow;
|
||||
escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
|
||||
BOOST_CHECK(::IsStandard(escrow));
|
||||
|
||||
CScript one_of_four;
|
||||
one_of_four << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << key[3].GetPubKey() << OP_4 << OP_CHECKMULTISIG;
|
||||
BOOST_CHECK(!::IsStandard(one_of_four));
|
||||
|
||||
CScript malformed[6];
|
||||
malformed[0] << OP_3 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
|
||||
malformed[1] << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
|
||||
malformed[2] << OP_0 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
|
||||
malformed[3] << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_0 << OP_CHECKMULTISIG;
|
||||
malformed[4] << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_CHECKMULTISIG;
|
||||
malformed[5] << OP_1 << key[0].GetPubKey() << key[1].GetPubKey();
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
BOOST_CHECK(!::IsStandard(malformed[i]));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(multisig_Solver1)
|
||||
@@ -170,13 +184,12 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
|
||||
}
|
||||
|
||||
{
|
||||
vector<vector<pair<opcodetype, valtype> > > solutions;
|
||||
vector<valtype> solutions;
|
||||
txntype whichType;
|
||||
CScript s;
|
||||
s << key[0].GetPubKey() << OP_CHECKSIG;
|
||||
BOOST_CHECK(Solver(s, solutions));
|
||||
BOOST_CHECK(Solver(s, whichType, solutions));
|
||||
BOOST_CHECK(solutions.size() == 1);
|
||||
if (solutions.size() == 1)
|
||||
BOOST_CHECK(solutions[0].size() == 1);
|
||||
CBitcoinAddress addr;
|
||||
BOOST_CHECK(ExtractAddress(s, &keystore, addr));
|
||||
BOOST_CHECK(addr == keyaddr[0]);
|
||||
@@ -184,13 +197,12 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
|
||||
BOOST_CHECK(!IsMine(emptykeystore, s));
|
||||
}
|
||||
{
|
||||
vector<vector<pair<opcodetype, valtype> > > solutions;
|
||||
vector<valtype> solutions;
|
||||
txntype whichType;
|
||||
CScript s;
|
||||
s << OP_DUP << OP_HASH160 << Hash160(key[0].GetPubKey()) << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||
BOOST_CHECK(Solver(s, solutions));
|
||||
BOOST_CHECK(Solver(s, whichType, solutions));
|
||||
BOOST_CHECK(solutions.size() == 1);
|
||||
if (solutions.size() == 1)
|
||||
BOOST_CHECK(solutions[0].size() == 1);
|
||||
CBitcoinAddress addr;
|
||||
BOOST_CHECK(ExtractAddress(s, &keystore, addr));
|
||||
BOOST_CHECK(addr == keyaddr[0]);
|
||||
@@ -198,47 +210,40 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
|
||||
BOOST_CHECK(!IsMine(emptykeystore, s));
|
||||
}
|
||||
{
|
||||
vector<vector<pair<opcodetype, valtype> > > solutions;
|
||||
vector<valtype> solutions;
|
||||
txntype whichType;
|
||||
CScript s;
|
||||
s << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
|
||||
BOOST_CHECK(Solver(s, solutions));
|
||||
BOOST_CHECK(solutions.size() == 1);
|
||||
if (solutions.size() == 1)
|
||||
BOOST_CHECK(solutions[0].size() == 2);
|
||||
BOOST_CHECK(Solver(s, whichType, solutions));
|
||||
BOOST_CHECK_EQUAL(solutions.size(), 4);
|
||||
CBitcoinAddress addr;
|
||||
BOOST_CHECK(!ExtractAddress(s, &keystore, addr));
|
||||
BOOST_CHECK(IsMine(keystore, s));
|
||||
BOOST_CHECK(!IsMine(emptykeystore, s));
|
||||
}
|
||||
{
|
||||
vector<vector<pair<opcodetype, valtype> > > solutions;
|
||||
vector<valtype> solutions;
|
||||
txntype whichType;
|
||||
CScript s;
|
||||
s << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
|
||||
BOOST_CHECK(Solver(s, solutions));
|
||||
BOOST_CHECK(solutions.size() == 2);
|
||||
if (solutions.size() == 2)
|
||||
{
|
||||
BOOST_CHECK(solutions[0].size() == 1);
|
||||
BOOST_CHECK(solutions[1].size() == 1);
|
||||
}
|
||||
CBitcoinAddress addr;
|
||||
BOOST_CHECK(ExtractAddress(s, &keystore, addr));
|
||||
BOOST_CHECK(addr == keyaddr[0]);
|
||||
BOOST_CHECK(Solver(s, whichType, solutions));
|
||||
BOOST_CHECK_EQUAL(solutions.size(), 4);
|
||||
vector<CBitcoinAddress> addrs;
|
||||
int nRequired;
|
||||
BOOST_CHECK(ExtractAddresses(s, &keystore, whichType, addrs, nRequired));
|
||||
BOOST_CHECK(addrs[0] == keyaddr[0]);
|
||||
BOOST_CHECK(addrs[1] == keyaddr[1]);
|
||||
BOOST_CHECK(nRequired = 1);
|
||||
BOOST_CHECK(IsMine(keystore, s));
|
||||
BOOST_CHECK(!IsMine(emptykeystore, s));
|
||||
}
|
||||
{
|
||||
vector<vector<pair<opcodetype, valtype> > > solutions;
|
||||
vector<valtype> solutions;
|
||||
txntype whichType;
|
||||
CScript s;
|
||||
s << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
|
||||
BOOST_CHECK(Solver(s, solutions));
|
||||
BOOST_CHECK(solutions.size() == 3);
|
||||
if (solutions.size() == 3)
|
||||
{
|
||||
BOOST_CHECK(solutions[0].size() == 2);
|
||||
BOOST_CHECK(solutions[1].size() == 2);
|
||||
BOOST_CHECK(solutions[2].size() == 2);
|
||||
}
|
||||
BOOST_CHECK(Solver(s, whichType, solutions));
|
||||
BOOST_CHECK(solutions.size() == 5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user