Gavin Andresen
13 years ago
27 changed files with 1615 additions and 460 deletions
@ -0,0 +1,294 @@
@@ -0,0 +1,294 @@
|
||||
#include <boost/assert.hpp> |
||||
#include <boost/assign/list_of.hpp> |
||||
#include <boost/assign/list_inserter.hpp> |
||||
#include <boost/assign/std/vector.hpp> |
||||
#include <boost/test/unit_test.hpp> |
||||
#include <boost/foreach.hpp> |
||||
#include <boost/tuple/tuple.hpp> |
||||
|
||||
#include <openssl/ec.h> |
||||
#include <openssl/err.h> |
||||
|
||||
#include "keystore.h" |
||||
#include "main.h" |
||||
#include "script.h" |
||||
#include "wallet.h" |
||||
|
||||
using namespace std; |
||||
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& nSigOpCount, |
||||
int nHashType, bool fStrictOpEval); |
||||
|
||||
BOOST_AUTO_TEST_SUITE(multisig_tests) |
||||
|
||||
CScript |
||||
sign_multisig(CScript scriptPubKey, vector<CKey> keys, CTransaction transaction, int whichIn) |
||||
{ |
||||
uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL); |
||||
|
||||
CScript result; |
||||
result << OP_0; // CHECKMULTISIG bug workaround
|
||||
BOOST_FOREACH(CKey key, keys) |
||||
{ |
||||
vector<unsigned char> vchSig; |
||||
BOOST_CHECK(key.Sign(hash, vchSig)); |
||||
vchSig.push_back((unsigned char)SIGHASH_ALL); |
||||
result << vchSig; |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
BOOST_AUTO_TEST_CASE(multisig_verify) |
||||
{ |
||||
CKey key[4]; |
||||
for (int i = 0; i < 4; i++) |
||||
key[i].MakeNewKey(); |
||||
|
||||
CScript a_and_b; |
||||
a_and_b << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG; |
||||
|
||||
CScript a_or_b; |
||||
a_or_b << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG; |
||||
|
||||
CScript escrow; |
||||
escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG; |
||||
|
||||
CTransaction txFrom; // Funding transaction
|
||||
txFrom.vout.resize(3); |
||||
txFrom.vout[0].scriptPubKey = a_and_b; |
||||
txFrom.vout[1].scriptPubKey = a_or_b; |
||||
txFrom.vout[2].scriptPubKey = escrow; |
||||
|
||||
CTransaction txTo[3]; // Spending transaction
|
||||
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; |
||||
} |
||||
|
||||
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, nUnused, 0, true)); |
||||
|
||||
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, nUnused, 0, true), 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, nUnused, 0, true), strprintf("a&b 2: %d", i)); |
||||
} |
||||
|
||||
// Test a OR b:
|
||||
for (int i = 0; i < 4; i++) |
||||
{ |
||||
keys.clear(); |
||||
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, nUnused, 0, true), strprintf("a|b: %d", i)); |
||||
else |
||||
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, txTo[1], 0, nUnused, 0, true), strprintf("a|b: %d", i)); |
||||
} |
||||
s.clear(); |
||||
s << OP_0 << OP_0; |
||||
BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, nUnused, 0, true)); |
||||
s.clear(); |
||||
s << OP_0 << OP_1; |
||||
BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, nUnused, 0, true)); |
||||
|
||||
|
||||
for (int i = 0; i < 4; i++) |
||||
for (int j = 0; j < 4; j++) |
||||
{ |
||||
keys.clear(); |
||||
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, nUnused, 0, true), strprintf("escrow 1: %d %d", i, j)); |
||||
else |
||||
BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, txTo[2], 0, nUnused, 0, true), strprintf("escrow 2: %d %d", i, j)); |
||||
} |
||||
} |
||||
|
||||
BOOST_AUTO_TEST_CASE(multisig_IsStandard) |
||||
{ |
||||
CKey key[4]; |
||||
for (int i = 0; i < 4; i++) |
||||
key[i].MakeNewKey(); |
||||
|
||||
CScript a_and_b; |
||||
a_and_b << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG; |
||||
BOOST_CHECK(::IsStandard(a_and_b)); |
||||
|
||||
CScript a_or_b; |
||||
a_or_b << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG; |
||||
BOOST_CHECK(::IsStandard(a_or_b)); |
||||
|
||||
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) |
||||
{ |
||||
// Tests Solver() that returns lists of keys that are
|
||||
// required to satisfy a ScriptPubKey
|
||||
//
|
||||
// Also tests IsMine() and ExtractAddress()
|
||||
//
|
||||
// Note: ExtractAddress for the multisignature transactions
|
||||
// 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.
|
||||
//
|
||||
CBasicKeyStore keystore, emptykeystore; |
||||
CKey key[3]; |
||||
CBitcoinAddress keyaddr[3]; |
||||
for (int i = 0; i < 3; i++) |
||||
{ |
||||
key[i].MakeNewKey(); |
||||
keystore.AddKey(key[i]); |
||||
keyaddr[i].SetPubKey(key[i].GetPubKey()); |
||||
} |
||||
|
||||
{ |
||||
vector<valtype> solutions; |
||||
txnouttype whichType; |
||||
CScript s; |
||||
s << key[0].GetPubKey() << OP_CHECKSIG; |
||||
BOOST_CHECK(Solver(s, whichType, solutions)); |
||||
BOOST_CHECK(solutions.size() == 1); |
||||
CBitcoinAddress addr; |
||||
BOOST_CHECK(ExtractAddress(s, &keystore, addr)); |
||||
BOOST_CHECK(addr == keyaddr[0]); |
||||
BOOST_CHECK(IsMine(keystore, s)); |
||||
BOOST_CHECK(!IsMine(emptykeystore, s)); |
||||
} |
||||
{ |
||||
vector<valtype> solutions; |
||||
txnouttype whichType; |
||||
CScript s; |
||||
s << OP_DUP << OP_HASH160 << Hash160(key[0].GetPubKey()) << OP_EQUALVERIFY << OP_CHECKSIG; |
||||
BOOST_CHECK(Solver(s, whichType, solutions)); |
||||
BOOST_CHECK(solutions.size() == 1); |
||||
CBitcoinAddress addr; |
||||
BOOST_CHECK(ExtractAddress(s, &keystore, addr)); |
||||
BOOST_CHECK(addr == keyaddr[0]); |
||||
BOOST_CHECK(IsMine(keystore, s)); |
||||
BOOST_CHECK(!IsMine(emptykeystore, s)); |
||||
} |
||||
{ |
||||
vector<valtype> solutions; |
||||
txnouttype whichType; |
||||
CScript s; |
||||
s << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG; |
||||
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<valtype> solutions; |
||||
txnouttype whichType; |
||||
CScript s; |
||||
s << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG; |
||||
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<valtype> solutions; |
||||
txnouttype whichType; |
||||
CScript s; |
||||
s << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG; |
||||
BOOST_CHECK(Solver(s, whichType, solutions)); |
||||
BOOST_CHECK(solutions.size() == 5); |
||||
} |
||||
} |
||||
|
||||
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++) |
||||
{ |
||||
key[i].MakeNewKey(); |
||||
keystore.AddKey(key[i]); |
||||
} |
||||
|
||||
CScript a_and_b; |
||||
a_and_b << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG; |
||||
|
||||
CScript a_or_b; |
||||
a_or_b << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG; |
||||
|
||||
CScript escrow; |
||||
escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG; |
||||
|
||||
CTransaction txFrom; // Funding transaction
|
||||
txFrom.vout.resize(3); |
||||
txFrom.vout[0].scriptPubKey = a_and_b; |
||||
txFrom.vout[1].scriptPubKey = a_or_b; |
||||
txFrom.vout[2].scriptPubKey = escrow; |
||||
|
||||
CTransaction txTo[3]; // Spending transaction
|
||||
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++) |
||||
{ |
||||
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i)); |
||||
} |
||||
} |
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() |
@ -0,0 +1,234 @@
@@ -0,0 +1,234 @@
|
||||
#include <boost/assert.hpp> |
||||
#include <boost/assign/list_of.hpp> |
||||
#include <boost/assign/list_inserter.hpp> |
||||
#include <boost/assign/std/vector.hpp> |
||||
#include <boost/test/unit_test.hpp> |
||||
#include <boost/foreach.hpp> |
||||
|
||||
#include "../main.h" |
||||
#include "../script.h" |
||||
#include "../wallet.h" |
||||
|
||||
using namespace std; |
||||
|
||||
// Test routines internal to script.cpp:
|
||||
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& nSigOps, |
||||
int nHashType, bool fStrictOpEval); |
||||
|
||||
BOOST_AUTO_TEST_SUITE(script_op_eval_tests) |
||||
|
||||
BOOST_AUTO_TEST_CASE(script_op_eval1) |
||||
{ |
||||
// OP_EVAL looks like this:
|
||||
// scriptSig: <sig> <sig...> <serialized_script>
|
||||
// scriptPubKey: DUP HASH160 <hash> EQUALVERIFY EVAL
|
||||
|
||||
// Test SignSignature() (and therefore the version of Solver() that signs transactions)
|
||||
CBasicKeyStore keystore; |
||||
CKey key[4]; |
||||
for (int i = 0; i < 4; i++) |
||||
{ |
||||
key[i].MakeNewKey(); |
||||
keystore.AddKey(key[i]); |
||||
} |
||||
|
||||
// 8 Scripts: checking all combinations of
|
||||
// different keys, straight/EVAL, pubkey/pubkeyhash
|
||||
CScript standardScripts[4]; |
||||
standardScripts[0] << key[0].GetPubKey() << OP_CHECKSIG; |
||||
standardScripts[1].SetBitcoinAddress(key[1].GetPubKey()); |
||||
standardScripts[2] << key[1].GetPubKey() << OP_CHECKSIG; |
||||
standardScripts[3].SetBitcoinAddress(key[2].GetPubKey()); |
||||
CScript evalScripts[4]; |
||||
uint160 sigScriptHashes[4]; |
||||
for (int i = 0; i < 4; i++) |
||||
{ |
||||
sigScriptHashes[i] = Hash160(standardScripts[i]); |
||||
keystore.AddCScript(sigScriptHashes[i], standardScripts[i]); |
||||
evalScripts[i] << OP_DUP << OP_HASH160 << sigScriptHashes[i] << OP_EQUALVERIFY << OP_EVAL; |
||||
} |
||||
|
||||
CTransaction txFrom; // Funding transaction:
|
||||
txFrom.vout.resize(8); |
||||
for (int i = 0; i < 4; i++) |
||||
{ |
||||
txFrom.vout[i].scriptPubKey = evalScripts[i]; |
||||
txFrom.vout[i+4].scriptPubKey = standardScripts[i]; |
||||
} |
||||
BOOST_CHECK(txFrom.IsStandard()); |
||||
|
||||
CTransaction txTo[8]; // Spending transactions
|
||||
for (int i = 0; i < 8; 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; |
||||
BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i)); |
||||
} |
||||
for (int i = 0; i < 8; i++) |
||||
{ |
||||
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i)); |
||||
} |
||||
// All of the above should be OK, and the txTos have valid signatures
|
||||
// Check to make sure signature verification fails if we use the wrong ScriptSig:
|
||||
for (int i = 0; i < 8; i++) |
||||
for (int j = 0; j < 8; j++) |
||||
{ |
||||
CScript sigSave = txTo[i].vin[0].scriptSig; |
||||
txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig; |
||||
int nUnused = 0; |
||||
bool sigOK = VerifySignature(txFrom, txTo[i], 0, nUnused); |
||||
if (i == j) |
||||
BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j)); |
||||
else |
||||
BOOST_CHECK_MESSAGE(!sigOK, strprintf("VerifySignature %d %d", i, j)); |
||||
txTo[i].vin[0].scriptSig = sigSave; |
||||
} |
||||
} |
||||
|
||||
BOOST_AUTO_TEST_CASE(script_op_eval2) |
||||
{ |
||||
// Test OP_EVAL edge cases
|
||||
|
||||
CScript recurse; |
||||
recurse << OP_DUP << OP_EVAL; |
||||
|
||||
uint160 recurseHash = Hash160(recurse); |
||||
|
||||
CScript fund; |
||||
fund << OP_DUP << OP_HASH160 << recurseHash << OP_EQUALVERIFY << OP_EVAL; |
||||
|
||||
CTransaction txFrom; // Funding transaction:
|
||||
txFrom.vout.resize(1); |
||||
txFrom.vout[0].scriptPubKey = fund; |
||||
|
||||
BOOST_CHECK(txFrom.IsStandard()); // Looks like a standard transaction until you try to spend it
|
||||
|
||||
CTransaction txTo; |
||||
txTo.vin.resize(1); |
||||
txTo.vout.resize(1); |
||||
txTo.vin[0].prevout.n = 0; |
||||
txTo.vin[0].prevout.hash = txFrom.GetHash(); |
||||
txTo.vin[0].scriptSig = CScript() << static_cast<std::vector<unsigned char> >(recurse); |
||||
txTo.vout[0].nValue = 1; |
||||
|
||||
int nUnused = 0; |
||||
BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, true)); |
||||
BOOST_CHECK(!VerifySignature(txFrom, txTo, 0, nUnused, true)); |
||||
} |
||||
|
||||
BOOST_AUTO_TEST_CASE(script_op_eval3) |
||||
{ |
||||
// Test the CScript::Set* methods
|
||||
CBasicKeyStore keystore; |
||||
CKey key[4]; |
||||
std::vector<CKey> keys; |
||||
for (int i = 0; i < 4; i++) |
||||
{ |
||||
key[i].MakeNewKey(); |
||||
keystore.AddKey(key[i]); |
||||
keys.push_back(key[i]); |
||||
} |
||||
|
||||
CScript inner[4]; |
||||
inner[0].SetBitcoinAddress(key[0].GetPubKey()); |
||||
inner[1].SetMultisig(2, std::vector<CKey>(keys.begin(), keys.begin()+2)); |
||||
inner[2].SetMultisig(1, std::vector<CKey>(keys.begin(), keys.begin()+2)); |
||||
inner[3].SetMultisig(2, std::vector<CKey>(keys.begin(), keys.begin()+3)); |
||||
|
||||
CScript outer[4]; |
||||
for (int i = 0; i < 4; i++) |
||||
{ |
||||
outer[i].SetEval(inner[i]); |
||||
keystore.AddCScript(Hash160(inner[i]), inner[i]); |
||||
} |
||||
|
||||
CTransaction txFrom; // Funding transaction:
|
||||
txFrom.vout.resize(4); |
||||
for (int i = 0; i < 4; i++) |
||||
{ |
||||
txFrom.vout[i].scriptPubKey = outer[i]; |
||||
} |
||||
BOOST_CHECK(txFrom.IsStandard()); |
||||
|
||||
CTransaction txTo[4]; // Spending transactions
|
||||
for (int i = 0; i < 4; 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; |
||||
txTo[i].vout[0].scriptPubKey = inner[i]; |
||||
BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i)); |
||||
} |
||||
for (int i = 0; i < 4; i++) |
||||
{ |
||||
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i)); |
||||
BOOST_CHECK_MESSAGE(txTo[i].IsStandard(), strprintf("txTo[%d].IsStandard", i)); |
||||
} |
||||
} |
||||
|
||||
BOOST_AUTO_TEST_CASE(script_op_eval_backcompat1) |
||||
{ |
||||
// Check backwards-incompatibility-testing code
|
||||
CScript returnsEleven; |
||||
returnsEleven << OP_11; |
||||
|
||||
// This should validate on new clients, but will
|
||||
// be invalid on old clients (that interpret OP_EVAL as a no-op)
|
||||
// ... except there's a special rule that makes new clients reject
|
||||
// it.
|
||||
CScript fund; |
||||
fund << OP_EVAL << OP_11 << OP_EQUAL; |
||||
|
||||
CTransaction txFrom; // Funding transaction:
|
||||
txFrom.vout.resize(1); |
||||
txFrom.vout[0].scriptPubKey = fund; |
||||
|
||||
CTransaction txTo; |
||||
txTo.vin.resize(1); |
||||
txTo.vout.resize(1); |
||||
txTo.vin[0].prevout.n = 0; |
||||
txTo.vin[0].prevout.hash = txFrom.GetHash(); |
||||
txTo.vin[0].scriptSig = CScript() << static_cast<std::vector<unsigned char> >(returnsEleven); |
||||
txTo.vout[0].nValue = 1; |
||||
|
||||
int nUnused = 0; |
||||
BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, true)); |
||||
BOOST_CHECK(!VerifySignature(txFrom, txTo, 0, nUnused, true)); |
||||
} |
||||
|
||||
BOOST_AUTO_TEST_CASE(script_op_eval_switchover) |
||||
{ |
||||
// Test OP_EVAL switchover code
|
||||
CScript notValid; |
||||
notValid << OP_11 << OP_12 << OP_EQUALVERIFY; |
||||
|
||||
// This will be valid under old rules, invalid under new:
|
||||
CScript fund; |
||||
fund << OP_EVAL; |
||||
|
||||
CTransaction txFrom; // Funding transaction:
|
||||
txFrom.vout.resize(1); |
||||
txFrom.vout[0].scriptPubKey = fund; |
||||
|
||||
CTransaction txTo; |
||||
txTo.vin.resize(1); |
||||
txTo.vout.resize(1); |
||||
txTo.vin[0].prevout.n = 0; |
||||
txTo.vin[0].prevout.hash = txFrom.GetHash(); |
||||
txTo.vin[0].scriptSig = CScript() << static_cast<std::vector<unsigned char> >(notValid); |
||||
txTo.vout[0].nValue = 1; |
||||
|
||||
int nUnused = 0; |
||||
BOOST_CHECK(VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, false)); |
||||
|
||||
// Under strict op_eval switchover, it should be considered invalid:
|
||||
BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, true)); |
||||
} |
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() |
Loading…
Reference in new issue