mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-07-01 11:11:15 +02:00
Add data-driven transaction tests.
This commit is contained in:
committed by
Matt Corallo
parent
336a0abbbb
commit
fc4743faa8
@ -1,12 +1,150 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include "json/json_spirit_writer_template.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "wallet.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace json_spirit;
|
||||
|
||||
// In script_tests.cpp
|
||||
extern Array read_json(const std::string& filename);
|
||||
extern CScript ParseScript(string s);
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(transaction_tests)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(tx_valid)
|
||||
{
|
||||
// Read tests from test/data/tx_valid.json
|
||||
// Format is an array of arrays
|
||||
// Inner arrays are either [ "comment" ]
|
||||
// or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], serializedTransaction, enforceP2SH
|
||||
// ... where all scripts are stringified scripts.
|
||||
Array tests = read_json("tx_valid.json");
|
||||
|
||||
BOOST_FOREACH(Value& tv, tests)
|
||||
{
|
||||
Array test = tv.get_array();
|
||||
string strTest = write_string(tv, false);
|
||||
if (test[0].type() == array_type)
|
||||
{
|
||||
if (test.size() != 3 || test[1].type() != str_type || test[2].type() != bool_type)
|
||||
{
|
||||
BOOST_ERROR("Bad test: " << strTest);
|
||||
continue;
|
||||
}
|
||||
|
||||
map<COutPoint, CScript> mapprevOutScriptPubKeys;
|
||||
Array inputs = test[0].get_array();
|
||||
bool fValid = true;
|
||||
BOOST_FOREACH(Value& input, inputs)
|
||||
{
|
||||
if (input.type() != array_type)
|
||||
{
|
||||
fValid = false;
|
||||
break;
|
||||
}
|
||||
Array vinput = input.get_array();
|
||||
if (vinput.size() != 3)
|
||||
{
|
||||
fValid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
mapprevOutScriptPubKeys[COutPoint(uint256(vinput[0].get_str()), vinput[1].get_int())] = ParseScript(vinput[2].get_str());
|
||||
}
|
||||
if (!fValid)
|
||||
{
|
||||
BOOST_ERROR("Bad test: " << strTest);
|
||||
continue;
|
||||
}
|
||||
|
||||
string transaction = test[1].get_str();
|
||||
CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION);
|
||||
CTransaction tx;
|
||||
stream >> tx;
|
||||
|
||||
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
||||
{
|
||||
if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout))
|
||||
{
|
||||
BOOST_ERROR("Bad test: " << strTest);
|
||||
break;
|
||||
}
|
||||
|
||||
BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], tx, i, test[2].get_bool(), 0), strTest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(tx_invalid)
|
||||
{
|
||||
// Read tests from test/data/tx_invalid.json
|
||||
// Format is an array of arrays
|
||||
// Inner arrays are either [ "comment" ]
|
||||
// or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], serializedTransaction, enforceP2SH
|
||||
// ... where all scripts are stringified scripts.
|
||||
Array tests = read_json("tx_invalid.json");
|
||||
|
||||
BOOST_FOREACH(Value& tv, tests)
|
||||
{
|
||||
Array test = tv.get_array();
|
||||
string strTest = write_string(tv, false);
|
||||
if (test[0].type() == array_type)
|
||||
{
|
||||
if (test.size() != 3 || test[1].type() != str_type || test[2].type() != bool_type)
|
||||
{
|
||||
BOOST_ERROR("Bad test: " << strTest);
|
||||
continue;
|
||||
}
|
||||
|
||||
map<COutPoint, CScript> mapprevOutScriptPubKeys;
|
||||
Array inputs = test[0].get_array();
|
||||
bool fValid = true;
|
||||
BOOST_FOREACH(Value& input, inputs)
|
||||
{
|
||||
if (input.type() != array_type)
|
||||
{
|
||||
fValid = false;
|
||||
break;
|
||||
}
|
||||
Array vinput = input.get_array();
|
||||
if (vinput.size() != 3)
|
||||
{
|
||||
fValid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
mapprevOutScriptPubKeys[COutPoint(uint256(vinput[0].get_str()), vinput[1].get_int())] = ParseScript(vinput[2].get_str());
|
||||
}
|
||||
if (!fValid)
|
||||
{
|
||||
BOOST_ERROR("Bad test: " << strTest);
|
||||
continue;
|
||||
}
|
||||
|
||||
string transaction = test[1].get_str();
|
||||
CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION);
|
||||
CTransaction tx;
|
||||
stream >> tx;
|
||||
|
||||
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
||||
{
|
||||
if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout))
|
||||
{
|
||||
BOOST_ERROR("Bad test: " << strTest);
|
||||
break;
|
||||
}
|
||||
|
||||
BOOST_CHECK_MESSAGE(!VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], tx, i, test[2].get_bool(), 0), strTest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(basic_transaction_tests)
|
||||
{
|
||||
// Random real transaction (e2769b09e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436)
|
||||
|
Reference in New Issue
Block a user