Skip to content

Commit fc4743f

Browse files
Matt CoralloTheBlueMatt
Matt Corallo
authored andcommittedAug 20, 2012
Add data-driven transaction tests.
1 parent 336a0ab commit fc4743f

File tree

3 files changed

+216
-0
lines changed

3 files changed

+216
-0
lines changed
 

‎src/test/data/tx_invalid.json

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[
2+
["The following are deserialized transactions which are invalid."],
3+
["They are in the form"],
4+
["[[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"],
5+
["serializedTransaction, enforceP2SH]"],
6+
["Objects that are only a single string (like this one) are ignored"],
7+
8+
["0e1b5688cf179cd9f7cbda1fac0090f6e684bbf8cd946660120197c3f3681809 but with extra junk appended to the end of the scriptPubKey"],
9+
[[["6ca7ec7b1847f6bdbd737176050e6a08d66ccd55bb94ad24f4018024107a5827", 0, "0x41 0x043b640e983c9690a14c039a2037ecc3467b27a0dcd58f19d76c7bc118d09fec45adc5370a1c5bf8067ca9f5557a4cf885fdb0fe0dcc9c3a7137226106fbc779a5 CHECKSIG VERIFY 1"]],
10+
"010000000127587a10248001f424ad94bb55cd6cd6086a0e05767173bdbdf647187beca76c000000004948304502201b822ad10d6adc1a341ae8835be3f70a25201bbff31f59cbb9c5353a5f0eca18022100ea7b2f7074e9aa9cf70aa8d0ffee13e6b45dddabf1ab961bda378bcdb778fa4701ffffffff0100f2052a010000001976a914fc50c5907d86fed474ba5ce8b12a66e0a4c139d888ac00000000", true],
11+
12+
["This is the nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG from tx_valid.json"],
13+
["but with the signature duplicated in the scriptPubKey with a non-standard pushdata prefix"],
14+
["See FindAndDelete, which will only remove if it uses the same pushdata prefix as is standard"],
15+
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x4c 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]],
16+
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true],
17+
18+
["Same as above, but with the sig in the scriptSig also pushed with the same non-standard OP_PUSHDATA"],
19+
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x4c 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]],
20+
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006b4c473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true],
21+
22+
["An invalid P2SH Transaction"],
23+
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]],
24+
"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", true]
25+
26+
]

‎src/test/data/tx_valid.json

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
[
2+
["The following are deserialized transactions which are valid."],
3+
["They are in the form"],
4+
["[[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"],
5+
["serializedTransaction, enforceP2SH]"],
6+
["Objects that are only a single string (like this one) are ignored"],
7+
8+
["The following is 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"],
9+
["It is of particular interest because it contains an invalidly-encoded signature which OpenSSL accepts"],
10+
["See http://r6.ca/blog/20111119T211504Z.html"],
11+
["It is also the first OP_CHECKMULTISIG transaction in standard form"],
12+
[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
13+
"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", true],
14+
15+
["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"],
16+
["It has an arbitrary extra byte stuffed into the signature at pos length - 2"],
17+
[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
18+
"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004A0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", true],
19+
20+
["The following is c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73"],
21+
["It is of interest because it contains a 0-sequence as well as a signature of SIGHASH type 0 (which is not a real type)"],
22+
[[["406b2b06bcd34d3c8733e6b79f7a394c8a431fbf4ff5ac705c93f4076bb77602", 0, "DUP HASH160 0x14 0xdc44b1164188067c3a32d4780f5996fa14a4f2d9 EQUALVERIFY CHECKSIG"]],
23+
"01000000010276b76b07f4935c70acf54fbf1f438a4c397a9fb7e633873c4dd3bc062b6b40000000008c493046022100d23459d03ed7e9511a47d13292d3430a04627de6235b6e51a40f9cd386f2abe3022100e7d25b080f0bb8d8d5f878bba7d54ad2fda650ea8d158a33ee3cbd11768191fd004104b0e2c879e4daf7b9ab68350228c159766676a14f5815084ba166432aab46198d4cca98fa3e9981d0a90b2effc514b76279476550ba3663fdcaff94c38420e9d5000000000100093d00000000001976a9149a7b0f3b80c6baaeedce0a0842553800f832ba1f88ac00000000", true],
24+
25+
["A nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG"],
26+
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1"]],
27+
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true],
28+
29+
["Same as above, but with the signature duplicated in the scriptPubKey with the proper pushdata prefix"],
30+
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]],
31+
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true],
32+
33+
["The following is f7fdd091fa6d8f5e7a8c2458f5c38faffff2d3f1406b6e4fe2c99dcc0d2d1cbb"],
34+
["It caught a bug in the workaround for 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63 in an overly simple implementation"],
35+
[[["b464e85df2a238416f8bdae11d120add610380ea07f4ef19c5f9dfd472f96c3d", 0, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"],
36+
["b7978cc96e59a8b13e0865d3f95657561a7f725be952438637475920bac9eb21", 1, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"]],
37+
"01000000023d6cf972d4dff9c519eff407ea800361dd0a121de1da8b6f4138a2f25de864b4000000008a4730440220ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e022049cffa1cdc102a0b56e0e04913606c70af702a1149dc3b305ab9439288fee090014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff21ebc9ba20594737864352e95b727f1a565756f9d365083eb1a8596ec98c97b7010000008a4730440220503ff10e9f1e0de731407a4a245531c9ff17676eda461f8ceeb8c06049fa2c810220c008ac34694510298fa60b3f000df01caa244f165b727d4896eb84f81e46bcc4014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff01f0da5200000000001976a914857ccd42dded6df32949d4646dfa10a92458cfaa88ac00000000", true],
38+
39+
["The following tests for the presence of a bug in the handling of SIGHASH_SINGLE"],
40+
["It results in signing the constant 1, instead of something generated based on the transaction,"],
41+
["when the input doing the signing has an index greater than the maximum output index"],
42+
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0xe52b482f2faa8ecbf0db344f93c84ac908557f33 EQUALVERIFY CHECKSIG"], ["0000000000000000000000000000000000000000000000000000000000000200", 0, "1"]],
43+
"01000000020002000000000000000000000000000000000000000000000000000000000000000000000151ffffffff0001000000000000000000000000000000000000000000000000000000000000000000006b483045022100c9cdd08798a28af9d1baf44a6c77bcc7e279f47dc487c8c899911bc48feaffcc0220503c5c50ae3998a733263c5c0f7061b483e2b56c4c41b456e7d2f5a78a74c077032102d5c25adb51b61339d2b05315791e21bbe80ea470a49db0135720983c905aace0ffffffff010000000000000000015100000000", true],
44+
45+
["An invalid P2SH Transaction"],
46+
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]],
47+
"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", false],
48+
49+
["A valid P2SH Transaction using the standard transaction type put forth in BIP 16"],
50+
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x8febbed40483661de6958d957412f82deed8e2f7 EQUAL"]],
51+
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100c66c9cdf4c43609586d15424c54707156e316d88b0a1534c9e6b0d4f311406310221009c0fe51dbc9c4ab7cc25d3fdbeccf6679fe6827f08edf2b4a9f16ee3eb0e438a0123210338e8034509af564c62644c07691942e0c056752008a173c89f60ab2a88ac2ebfacffffffff010000000000000000015100000000", true]
52+
]

‎src/test/transaction_tests.cpp

+138
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,150 @@
1+
#include <map>
2+
#include <string>
13
#include <boost/test/unit_test.hpp>
4+
#include "json/json_spirit_writer_template.h"
25

36
#include "main.h"
47
#include "wallet.h"
58

69
using namespace std;
10+
using namespace json_spirit;
11+
12+
// In script_tests.cpp
13+
extern Array read_json(const std::string& filename);
14+
extern CScript ParseScript(string s);
715

816
BOOST_AUTO_TEST_SUITE(transaction_tests)
917

18+
BOOST_AUTO_TEST_CASE(tx_valid)
19+
{
20+
// Read tests from test/data/tx_valid.json
21+
// Format is an array of arrays
22+
// Inner arrays are either [ "comment" ]
23+
// or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], serializedTransaction, enforceP2SH
24+
// ... where all scripts are stringified scripts.
25+
Array tests = read_json("tx_valid.json");
26+
27+
BOOST_FOREACH(Value& tv, tests)
28+
{
29+
Array test = tv.get_array();
30+
string strTest = write_string(tv, false);
31+
if (test[0].type() == array_type)
32+
{
33+
if (test.size() != 3 || test[1].type() != str_type || test[2].type() != bool_type)
34+
{
35+
BOOST_ERROR("Bad test: " << strTest);
36+
continue;
37+
}
38+
39+
map<COutPoint, CScript> mapprevOutScriptPubKeys;
40+
Array inputs = test[0].get_array();
41+
bool fValid = true;
42+
BOOST_FOREACH(Value& input, inputs)
43+
{
44+
if (input.type() != array_type)
45+
{
46+
fValid = false;
47+
break;
48+
}
49+
Array vinput = input.get_array();
50+
if (vinput.size() != 3)
51+
{
52+
fValid = false;
53+
break;
54+
}
55+
56+
mapprevOutScriptPubKeys[COutPoint(uint256(vinput[0].get_str()), vinput[1].get_int())] = ParseScript(vinput[2].get_str());
57+
}
58+
if (!fValid)
59+
{
60+
BOOST_ERROR("Bad test: " << strTest);
61+
continue;
62+
}
63+
64+
string transaction = test[1].get_str();
65+
CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION);
66+
CTransaction tx;
67+
stream >> tx;
68+
69+
for (unsigned int i = 0; i < tx.vin.size(); i++)
70+
{
71+
if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout))
72+
{
73+
BOOST_ERROR("Bad test: " << strTest);
74+
break;
75+
}
76+
77+
BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], tx, i, test[2].get_bool(), 0), strTest);
78+
}
79+
}
80+
}
81+
}
82+
83+
BOOST_AUTO_TEST_CASE(tx_invalid)
84+
{
85+
// Read tests from test/data/tx_invalid.json
86+
// Format is an array of arrays
87+
// Inner arrays are either [ "comment" ]
88+
// or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], serializedTransaction, enforceP2SH
89+
// ... where all scripts are stringified scripts.
90+
Array tests = read_json("tx_invalid.json");
91+
92+
BOOST_FOREACH(Value& tv, tests)
93+
{
94+
Array test = tv.get_array();
95+
string strTest = write_string(tv, false);
96+
if (test[0].type() == array_type)
97+
{
98+
if (test.size() != 3 || test[1].type() != str_type || test[2].type() != bool_type)
99+
{
100+
BOOST_ERROR("Bad test: " << strTest);
101+
continue;
102+
}
103+
104+
map<COutPoint, CScript> mapprevOutScriptPubKeys;
105+
Array inputs = test[0].get_array();
106+
bool fValid = true;
107+
BOOST_FOREACH(Value& input, inputs)
108+
{
109+
if (input.type() != array_type)
110+
{
111+
fValid = false;
112+
break;
113+
}
114+
Array vinput = input.get_array();
115+
if (vinput.size() != 3)
116+
{
117+
fValid = false;
118+
break;
119+
}
120+
121+
mapprevOutScriptPubKeys[COutPoint(uint256(vinput[0].get_str()), vinput[1].get_int())] = ParseScript(vinput[2].get_str());
122+
}
123+
if (!fValid)
124+
{
125+
BOOST_ERROR("Bad test: " << strTest);
126+
continue;
127+
}
128+
129+
string transaction = test[1].get_str();
130+
CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION);
131+
CTransaction tx;
132+
stream >> tx;
133+
134+
for (unsigned int i = 0; i < tx.vin.size(); i++)
135+
{
136+
if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout))
137+
{
138+
BOOST_ERROR("Bad test: " << strTest);
139+
break;
140+
}
141+
142+
BOOST_CHECK_MESSAGE(!VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], tx, i, test[2].get_bool(), 0), strTest);
143+
}
144+
}
145+
}
146+
}
147+
10148
BOOST_AUTO_TEST_CASE(basic_transaction_tests)
11149
{
12150
// Random real transaction (e2769b09e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436)

0 commit comments

Comments
 (0)