1 #include <boost/assert.hpp>
2 #include <boost/assign/list_of.hpp>
3 #include <boost/assign/list_inserter.hpp>
4 #include <boost/assign/std/vector.hpp>
5 #include <boost/test/unit_test.hpp>
6 #include <boost/foreach.hpp>
10 #include "../wallet.h"
14 // Test routines internal to script.cpp:
15 extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
16 extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, int& nSigOps, int nHashType);
18 BOOST_AUTO_TEST_SUITE(script_op_eval_tests)
20 BOOST_AUTO_TEST_CASE(script_op_eval1)
22 // OP_EVAL looks like this:
23 // scriptSig: <sig> <sig...> <serialized_script>
24 // scriptPubKey: DUP HASH160 <hash> EQUALVERIFY EVAL
26 // Test SignSignature() (and therefore the version of Solver() that signs transactions)
27 CBasicKeyStore keystore;
29 for (int i = 0; i < 4; i++)
32 keystore.AddKey(key[i]);
35 // 8 Scripts: checking all combinations of
36 // different keys, straight/EVAL, pubkey/pubkeyhash
37 CScript standardScripts[4];
38 standardScripts[0] << key[0].GetPubKey() << OP_CHECKSIG;
39 standardScripts[1].SetBitcoinAddress(key[1].GetPubKey());
40 standardScripts[2] << key[1].GetPubKey() << OP_CHECKSIG;
41 standardScripts[3].SetBitcoinAddress(key[2].GetPubKey());
42 CScript evalScripts[4];
43 uint160 sigScriptHashes[4];
44 for (int i = 0; i < 4; i++)
46 sigScriptHashes[i] = Hash160(standardScripts[i]);
47 keystore.AddCScript(sigScriptHashes[i], standardScripts[i]);
48 evalScripts[i] << OP_DUP << OP_HASH160 << sigScriptHashes[i] << OP_EQUALVERIFY << OP_EVAL;
51 CTransaction txFrom; // Funding transaction:
52 txFrom.vout.resize(8);
53 for (int i = 0; i < 4; i++)
55 txFrom.vout[i].scriptPubKey = evalScripts[i];
56 txFrom.vout[i+4].scriptPubKey = standardScripts[i];
58 BOOST_CHECK(txFrom.IsStandard());
60 CTransaction txTo[8]; // Spending transactions
61 for (int i = 0; i < 8; i++)
63 txTo[i].vin.resize(1);
64 txTo[i].vout.resize(1);
65 txTo[i].vin[0].prevout.n = i;
66 txTo[i].vin[0].prevout.hash = txFrom.GetHash();
67 txTo[i].vout[0].nValue = 1;
68 BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
70 for (int i = 0; i < 8; i++)
72 BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
74 // All of the above should be OK, and the txTos have valid signatures
75 // Check to make sure signature verification fails if we use the wrong ScriptSig:
76 for (int i = 0; i < 8; i++)
77 for (int j = 0; j < 8; j++)
79 CScript sigSave = txTo[i].vin[0].scriptSig;
80 txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig;
82 bool sigOK = VerifySignature(txFrom, txTo[i], 0, nUnused);
84 BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j));
86 BOOST_CHECK_MESSAGE(!sigOK, strprintf("VerifySignature %d %d", i, j));
87 txTo[i].vin[0].scriptSig = sigSave;
91 BOOST_AUTO_TEST_CASE(script_op_eval2)
93 // Test OP_EVAL edge cases
96 recurse << OP_DUP << OP_EVAL;
98 uint160 recurseHash = Hash160(recurse);
101 fund << OP_DUP << OP_HASH160 << recurseHash << OP_EQUALVERIFY << OP_EVAL;
103 CTransaction txFrom; // Funding transaction:
104 txFrom.vout.resize(1);
105 txFrom.vout[0].scriptPubKey = fund;
107 BOOST_CHECK(txFrom.IsStandard()); // Looks like a standard transaction until you try to spend it
112 txTo.vin[0].prevout.n = 0;
113 txTo.vin[0].prevout.hash = txFrom.GetHash();
114 txTo.vin[0].scriptSig = CScript() << static_cast<std::vector<unsigned char> >(recurse);
115 txTo.vout[0].nValue = 1;
118 BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0));
119 BOOST_CHECK(!VerifySignature(txFrom, txTo, 0, nUnused));
122 BOOST_AUTO_TEST_CASE(script_op_eval3)
124 // Test the CScript::Set* methods
125 CBasicKeyStore keystore;
127 std::vector<CKey> keys;
128 for (int i = 0; i < 4; i++)
131 keystore.AddKey(key[i]);
132 keys.push_back(key[i]);
136 inner[0].SetBitcoinAddress(key[0].GetPubKey());
137 inner[1].SetMultisig(2, std::vector<CKey>(keys.begin(), keys.begin()+2));
138 inner[2].SetMultisig(1, std::vector<CKey>(keys.begin(), keys.begin()+2));
139 inner[3].SetMultisig(2, std::vector<CKey>(keys.begin(), keys.begin()+3));
142 for (int i = 0; i < 4; i++)
144 outer[i].SetEval(inner[i]);
145 keystore.AddCScript(Hash160(inner[i]), inner[i]);
148 CTransaction txFrom; // Funding transaction:
149 txFrom.vout.resize(4);
150 for (int i = 0; i < 4; i++)
152 txFrom.vout[i].scriptPubKey = outer[i];
154 BOOST_CHECK(txFrom.IsStandard());
156 CTransaction txTo[4]; // Spending transactions
157 for (int i = 0; i < 4; i++)
159 txTo[i].vin.resize(1);
160 txTo[i].vout.resize(1);
161 txTo[i].vin[0].prevout.n = i;
162 txTo[i].vin[0].prevout.hash = txFrom.GetHash();
163 txTo[i].vout[0].nValue = 1;
164 txTo[i].vout[0].scriptPubKey = inner[i];
165 BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
167 for (int i = 0; i < 4; i++)
169 BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
170 BOOST_CHECK_MESSAGE(txTo[i].IsStandard(), strprintf("txTo[%d].IsStandard", i));
174 BOOST_AUTO_TEST_CASE(script_op_eval_backcompat)
176 // Check backwards-incompatibility-testing code
177 CScript returnsEleven;
178 returnsEleven << OP_11;
180 // This will validate on new clients, but will
181 // be invalid on old clients (that interpret OP_EVAL as a no-op)
183 fund << OP_EVAL << OP_11 << OP_EQUAL;
185 CTransaction txFrom; // Funding transaction:
186 txFrom.vout.resize(1);
187 txFrom.vout[0].scriptPubKey = fund;
192 txTo.vin[0].prevout.n = 0;
193 txTo.vin[0].prevout.hash = txFrom.GetHash();
194 txTo.vin[0].scriptSig = CScript() << static_cast<std::vector<unsigned char> >(returnsEleven);
195 txTo.vout[0].nValue = 1;
198 BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0));
199 BOOST_CHECK(!VerifySignature(txFrom, txTo, 0, nUnused));
203 BOOST_AUTO_TEST_SUITE_END()