diff options
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/Makefile.am | 31 | ||||
-rw-r--r-- | src/test/alert_tests.cpp | 26 | ||||
-rw-r--r-- | src/test/base58_tests.cpp | 17 | ||||
-rw-r--r-- | src/test/canonical_tests.cpp | 8 | ||||
-rw-r--r-- | src/test/checkblock_tests.cpp | 2 | ||||
-rw-r--r-- | src/test/data/alertTests.raw (renamed from src/test/data/alertTests) | bin | 1283 -> 1283 bytes | |||
-rw-r--r-- | src/test/miner_tests.cpp | 16 | ||||
-rw-r--r-- | src/test/multisig_tests.cpp | 2 | ||||
-rw-r--r-- | src/test/script_tests.cpp | 35 | ||||
-rw-r--r-- | src/test/sighash_tests.cpp | 120 | ||||
-rw-r--r-- | src/test/transaction_tests.cpp | 8 | ||||
-rw-r--r-- | src/test/wallet_tests.cpp | 1 |
12 files changed, 186 insertions, 80 deletions
diff --git a/src/test/Makefile.am b/src/test/Makefile.am index 80571aa295..c3495095d9 100644 --- a/src/test/Makefile.am +++ b/src/test/Makefile.am @@ -2,7 +2,7 @@ include $(top_srcdir)/src/Makefile.include AM_CPPFLAGS = $(INCLUDES) -I$(top_builddir)/src/obj \ -I$(top_srcdir)/src/leveldb/include -I$(top_srcdir)/src/leveldb/helpers \ - -I$(top_srcdir)/src $(BOOST_INCLUDES) + -I$(top_srcdir)/src $(BOOST_INCLUDES) $(BDB_CPPFLAGS) AM_LDFLAGS = $(PTHREAD_CFLAGS) @@ -10,21 +10,22 @@ bin_PROGRAMS = test_bitcoin TESTS = test_bitcoin -TEST_DATA_DIR=$(top_srcdir)/src/test/data +JSON_TEST_FILES= data/script_valid.json \ + data/base58_keys_valid.json data/sig_canonical.json \ + data/sig_noncanonical.json \ + data/base58_encode_decode.json \ + data/base58_keys_invalid.json \ + data/script_invalid.json data/tx_invalid.json \ + data/tx_valid.json -TEST_DATA_FILES= $(TEST_DATA_DIR)/script_valid.json \ - $(TEST_DATA_DIR)/base58_keys_valid.json $(TEST_DATA_DIR)/sig_canonical.json \ - $(TEST_DATA_DIR)/sig_noncanonical.json \ - $(TEST_DATA_DIR)/base58_encode_decode.json $(TEST_DATA_DIR)/alertTests \ - $(TEST_DATA_DIR)/base58_keys_invalid.json \ - $(TEST_DATA_DIR)/script_invalid.json $(TEST_DATA_DIR)/tx_invalid.json \ - $(TEST_DATA_DIR)/tx_valid.json +RAW_TEST_FILES = data/alertTests.raw + +BUILT_SOURCES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h) # test_bitcoin binary # -test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(TESTDEFS) \ - -DTEST_DATA_DIR=$(TEST_DATA_DIR) +test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(TESTDEFS) test_bitcoin_LDADD = $(LIBBITCOIN) $(LIBLEVELDB) $(LIBMEMENV) \ - $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) + $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(BDB_LIBS) test_bitcoin_SOURCES = accounting_tests.cpp alert_tests.cpp \ allocator_tests.cpp base32_tests.cpp base58_tests.cpp base64_tests.cpp \ bignum_tests.cpp bloom_tests.cpp canonical_tests.cpp checkblock_tests.cpp \ @@ -33,6 +34,8 @@ test_bitcoin_SOURCES = accounting_tests.cpp alert_tests.cpp \ netbase_tests.cpp pmt_tests.cpp rpc_tests.cpp script_P2SH_tests.cpp \ script_tests.cpp serialize_tests.cpp sigopcount_tests.cpp test_bitcoin.cpp \ transaction_tests.cpp uint160_tests.cpp uint256_tests.cpp util_tests.cpp \ - wallet_tests.cpp $(TEST_DATA_FILES) + wallet_tests.cpp sighash_tests.cpp $(JSON_TEST_FILES) $(RAW_TEST_FILES) + +nodist_test_bitcoin_SOURCES = $(BUILT_SOURCES) -CLEANFILES = *.gcda *.gcno +CLEANFILES = *.gcda *.gcno $(BUILT_SOURCES) diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index f7a11376d3..cb941943f7 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -9,6 +9,7 @@ #include "alert.h" #include "serialize.h" #include "util.h" +#include "data/alertTests.raw.h" #if 0 // @@ -71,27 +72,13 @@ struct ReadAlerts { ReadAlerts() { - std::string filename("alertTests"); - namespace fs = boost::filesystem; - fs::path testFile = fs::current_path() / "test" / "data" / filename; -#ifdef TEST_DATA_DIR - if (!fs::exists(testFile)) - { - testFile = fs::path(BOOST_PP_STRINGIZE(TEST_DATA_DIR)) / filename; - } -#endif - FILE* fp = fopen(testFile.string().c_str(), "rb"); - if (!fp) return; - - - CAutoFile filein = CAutoFile(fp, SER_DISK, CLIENT_VERSION); - if (!filein) return; - + std::vector<unsigned char> vch(alert_tests::alertTests, alert_tests::alertTests + sizeof(alert_tests::alertTests)); + CDataStream stream(vch, SER_DISK, CLIENT_VERSION); try { - while (!feof(filein)) + while (stream.good()) { CAlert alert; - filein >> alert; + stream >> alert; alerts.push_back(alert); } } @@ -125,6 +112,9 @@ BOOST_AUTO_TEST_CASE(AlertApplies) { BOOST_CHECK(alert.CheckSignature()); } + + BOOST_CHECK(alerts.size() >= 3); + // Matches: BOOST_CHECK(alerts[0].AppliesTo(1, "")); BOOST_CHECK(alerts[0].AppliesTo(70001, "")); diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index af65416485..05675685bd 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -2,20 +2,21 @@ #include "json/json_spirit_reader_template.h" #include "json/json_spirit_writer_template.h" #include "json/json_spirit_utils.h" +#include "data/base58_encode_decode.json.h" +#include "data/base58_keys_invalid.json.h" +#include "data/base58_keys_valid.json.h" #include "base58.h" #include "util.h" - using namespace json_spirit; -extern Array read_json(const std::string& filename); +extern Array read_json(const std::string& jsondata); BOOST_AUTO_TEST_SUITE(base58_tests) // Goal: test low-level base58 encoding functionality BOOST_AUTO_TEST_CASE(base58_EncodeBase58) { - Array tests = read_json("base58_encode_decode.json"); - + Array tests = read_json(std::string(json_tests::base58_encode_decode, json_tests::base58_encode_decode + sizeof(json_tests::base58_encode_decode))); BOOST_FOREACH(Value& tv, tests) { Array test = tv.get_array(); @@ -36,7 +37,7 @@ BOOST_AUTO_TEST_CASE(base58_EncodeBase58) // Goal: test low-level base58 decoding functionality BOOST_AUTO_TEST_CASE(base58_DecodeBase58) { - Array tests = read_json("base58_encode_decode.json"); + Array tests = read_json(std::string(json_tests::base58_encode_decode, json_tests::base58_encode_decode + sizeof(json_tests::base58_encode_decode))); std::vector<unsigned char> result; BOOST_FOREACH(Value& tv, tests) @@ -104,7 +105,7 @@ public: // Goal: check that parsed keys match test payload BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) { - Array tests = read_json("base58_keys_valid.json"); + Array tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid))); std::vector<unsigned char> result; CBitcoinSecret secret; CBitcoinAddress addr; @@ -163,7 +164,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) // Goal: check that generated keys match test vectors BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) { - Array tests = read_json("base58_keys_valid.json"); + Array tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid))); std::vector<unsigned char> result; BOOST_FOREACH(Value& tv, tests) { @@ -231,7 +232,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) // Goal: check that base58 parsing code is robust against a variety of corrupted data BOOST_AUTO_TEST_CASE(base58_keys_invalid) { - Array tests = read_json("base58_keys_invalid.json"); // Negative testcases + Array tests = read_json(std::string(json_tests::base58_keys_invalid, json_tests::base58_keys_invalid + sizeof(json_tests::base58_keys_invalid))); // Negative testcases std::vector<unsigned char> result; CBitcoinSecret secret; CBitcoinAddress addr; diff --git a/src/test/canonical_tests.cpp b/src/test/canonical_tests.cpp index 09988da259..ec32ceb8a4 100644 --- a/src/test/canonical_tests.cpp +++ b/src/test/canonical_tests.cpp @@ -8,13 +8,15 @@ #include "key.h" #include "script.h" #include "util.h" +#include "data/sig_noncanonical.json.h" +#include "data/sig_canonical.json.h" using namespace std; using namespace json_spirit; // In script_tests.cpp -extern Array read_json(const std::string& filename); +extern Array read_json(const std::string& jsondata); BOOST_AUTO_TEST_SUITE(canonical_tests) @@ -58,7 +60,7 @@ bool static IsCanonicalSignature_OpenSSL(const std::vector<unsigned char> &vchSi BOOST_AUTO_TEST_CASE(script_canon) { - Array tests = read_json("sig_canonical.json"); + Array tests = read_json(std::string(json_tests::sig_canonical, json_tests::sig_canonical + sizeof(json_tests::sig_canonical))); BOOST_FOREACH(Value &tv, tests) { string test = tv.get_str(); @@ -72,7 +74,7 @@ BOOST_AUTO_TEST_CASE(script_canon) BOOST_AUTO_TEST_CASE(script_noncanon) { - Array tests = read_json("sig_noncanonical.json"); + Array tests = read_json(std::string(json_tests::sig_noncanonical, json_tests::sig_noncanonical + sizeof(json_tests::sig_noncanonical))); BOOST_FOREACH(Value &tv, tests) { string test = tv.get_str(); diff --git a/src/test/checkblock_tests.cpp b/src/test/checkblock_tests.cpp index 5675c40e76..e34680db99 100644 --- a/src/test/checkblock_tests.cpp +++ b/src/test/checkblock_tests.cpp @@ -19,7 +19,7 @@ bool read_block(const std::string& filename, CBlock& block) { namespace fs = boost::filesystem; - fs::path testFile = fs::current_path() / "test" / "data" / filename; + fs::path testFile = fs::current_path() / "data" / filename; #ifdef TEST_DATA_DIR if (!fs::exists(testFile)) { diff --git a/src/test/data/alertTests b/src/test/data/alertTests.raw Binary files differindex 7fc4528961..7fc4528961 100644 --- a/src/test/data/alertTests +++ b/src/test/data/alertTests.raw diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 8183504147..67165760b2 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -65,10 +65,10 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) { CBlock *pblock = &pblocktemplate->block; // pointer for convenience pblock->nVersion = 1; - pblock->nTime = pindexBest->GetMedianTimePast()+1; + pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1; pblock->vtx[0].vin[0].scriptSig = CScript(); pblock->vtx[0].vin[0].scriptSig.push_back(blockinfo[i].extranonce); - pblock->vtx[0].vin[0].scriptSig.push_back(pindexBest->nHeight); + pblock->vtx[0].vin[0].scriptSig.push_back(chainActive.Height()); pblock->vtx[0].vout[0].scriptPubKey = CScript(); if (txFirst.size() < 2) txFirst.push_back(new CTransaction(pblock->vtx[0])); @@ -83,6 +83,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) // Just to make sure we can still make simple blocks BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey)); + delete pblocktemplate; // block sigops > limit: 1000 CHECKMULTISIG + 1 tx.vin.resize(1); @@ -192,14 +193,17 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) mempool.clear(); // subsidy changing - int nHeight = pindexBest->nHeight; - pindexBest->nHeight = 209999; + int nHeight = chainActive.Height(); + chainActive.Tip()->nHeight = 209999; BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey)); delete pblocktemplate; - pindexBest->nHeight = 210000; + chainActive.Tip()->nHeight = 210000; BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey)); delete pblocktemplate; - pindexBest->nHeight = nHeight; + chainActive.Tip()->nHeight = nHeight; + + BOOST_FOREACH(CTransaction *tx, txFirst) + delete tx; } BOOST_AUTO_TEST_CASE(sha256transform_equality) diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index 9ef932b5b4..7f6f141c62 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -19,7 +19,7 @@ using namespace boost::assign; typedef vector<unsigned char> valtype; -extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); +extern uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); BOOST_AUTO_TEST_SUITE(multisig_tests) diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index c1f6f178db..32be914414 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -14,12 +14,14 @@ #include "main.h" #include "wallet.h" +#include "data/script_invalid.json.h" +#include "data/script_valid.json.h" using namespace std; using namespace json_spirit; using namespace boost::algorithm; -extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); +extern uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); static const unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC; @@ -90,34 +92,15 @@ ParseScript(string s) } Array -read_json(const std::string& filename) +read_json(const std::string& jsondata) { - namespace fs = boost::filesystem; - fs::path testFile = fs::current_path() / "test" / "data" / filename; - -#ifdef TEST_DATA_DIR - if (!fs::exists(testFile)) - { - testFile = fs::path(BOOST_PP_STRINGIZE(TEST_DATA_DIR)) / filename; - } -#endif - - ifstream ifs(testFile.string().c_str(), ifstream::in); Value v; - if (!read_stream(ifs, v)) - { - if (ifs.fail()) - BOOST_ERROR("Cound not find/open " << filename); - else - BOOST_ERROR("JSON syntax error in " << filename); - return Array(); - } - if (v.type() != array_type) + + if (!read_string(jsondata, v) || v.type() != array_type) { - BOOST_ERROR(filename << " does not contain a json array"); + BOOST_ERROR("Parse error."); return Array(); } - return v.get_array(); } @@ -130,7 +113,7 @@ BOOST_AUTO_TEST_CASE(script_valid) // Inner arrays are [ "scriptSig", "scriptPubKey" ] // ... where scriptSig and scriptPubKey are stringified // scripts. - Array tests = read_json("script_valid.json"); + Array tests = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid))); BOOST_FOREACH(Value& tv, tests) { @@ -154,7 +137,7 @@ BOOST_AUTO_TEST_CASE(script_valid) BOOST_AUTO_TEST_CASE(script_invalid) { // Scripts that should evaluate as invalid - Array tests = read_json("script_invalid.json"); + Array tests = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid))); BOOST_FOREACH(Value& tv, tests) { diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp new file mode 100644 index 0000000000..f098d46186 --- /dev/null +++ b/src/test/sighash_tests.cpp @@ -0,0 +1,120 @@ +#include <boost/test/unit_test.hpp> + +#include "main.h" +#include "util.h" + +extern uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); + +// Old script.cpp SignatureHash function +uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType) +{ + if (nIn >= txTo.vin.size()) + { + printf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn); + return 1; + } + CTransaction txTmp(txTo); + + // In case concatenating two scripts ends up with two codeseparators, + // or an extra one at the end, this prevents all those possible incompatibilities. + scriptCode.FindAndDelete(CScript(OP_CODESEPARATOR)); + + // Blank out other inputs' signatures + for (unsigned int i = 0; i < txTmp.vin.size(); i++) + txTmp.vin[i].scriptSig = CScript(); + txTmp.vin[nIn].scriptSig = scriptCode; + + // Blank out some of the outputs + if ((nHashType & 0x1f) == SIGHASH_NONE) + { + // Wildcard payee + txTmp.vout.clear(); + + // Let the others update at will + for (unsigned int i = 0; i < txTmp.vin.size(); i++) + if (i != nIn) + txTmp.vin[i].nSequence = 0; + } + else if ((nHashType & 0x1f) == SIGHASH_SINGLE) + { + // Only lock-in the txout payee at same index as txin + unsigned int nOut = nIn; + if (nOut >= txTmp.vout.size()) + { + printf("ERROR: SignatureHash() : nOut=%d out of range\n", nOut); + return 1; + } + txTmp.vout.resize(nOut+1); + for (unsigned int i = 0; i < nOut; i++) + txTmp.vout[i].SetNull(); + + // Let the others update at will + for (unsigned int i = 0; i < txTmp.vin.size(); i++) + if (i != nIn) + txTmp.vin[i].nSequence = 0; + } + + // Blank out other inputs completely, not recommended for open transactions + if (nHashType & SIGHASH_ANYONECANPAY) + { + txTmp.vin[0] = txTmp.vin[nIn]; + txTmp.vin.resize(1); + } + + // Serialize and hash + CHashWriter ss(SER_GETHASH, 0); + ss << txTmp << nHashType; + return ss.GetHash(); +} + +void static RandomScript(CScript &script) { + static const opcodetype oplist[] = {OP_FALSE, OP_1, OP_2, OP_3, OP_CHECKSIG, OP_IF, OP_VERIF, OP_RETURN, OP_CODESEPARATOR}; + script = CScript(); + int ops = (insecure_rand() % 10); + for (int i=0; i<ops; i++) + script << oplist[insecure_rand() % (sizeof(oplist)/sizeof(oplist[0]))]; +} + +void static RandomTransaction(CTransaction &tx, bool fSingle) { + tx.nVersion = insecure_rand(); + tx.vin.clear(); + tx.vout.clear(); + tx.nLockTime = (insecure_rand() % 2) ? insecure_rand() : 0; + int ins = (insecure_rand() % 4) + 1; + int outs = fSingle ? ins : (insecure_rand() % 4) + 1; + for (int in = 0; in < ins; in++) { + tx.vin.push_back(CTxIn()); + CTxIn &txin = tx.vin.back(); + txin.prevout.hash = GetRandHash(); + txin.prevout.n = insecure_rand() % 4; + RandomScript(txin.scriptSig); + txin.nSequence = (insecure_rand() % 2) ? insecure_rand() : (unsigned int)-1; + } + for (int out = 0; out < outs; out++) { + tx.vout.push_back(CTxOut()); + CTxOut &txout = tx.vout.back(); + txout.nValue = insecure_rand() % 100000000; + RandomScript(txout.scriptPubKey); + } +} + +BOOST_AUTO_TEST_SUITE(sighash_tests) + +BOOST_AUTO_TEST_CASE(sighash_test) +{ + seed_insecure_rand(false); + + for (int i=0; i<50000; i++) { + int nHashType = insecure_rand(); + CTransaction txTo; + RandomTransaction(txTo, (nHashType & 0x1f) == SIGHASH_SINGLE); + CScript scriptCode; + RandomScript(scriptCode); + int nIn = insecure_rand() % txTo.vin.size(); + BOOST_CHECK(SignatureHash(scriptCode, txTo, nIn, nHashType) == + SignatureHashOld(scriptCode, txTo, nIn, nHashType)); + } +} + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 0c7475b4f2..416b93ab33 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -5,12 +5,14 @@ #include "main.h" #include "wallet.h" +#include "data/tx_invalid.json.h" +#include "data/tx_valid.json.h" using namespace std; using namespace json_spirit; // In script_tests.cpp -extern Array read_json(const std::string& filename); +extern Array read_json(const std::string& jsondata); extern CScript ParseScript(string s); BOOST_AUTO_TEST_SUITE(transaction_tests) @@ -22,7 +24,7 @@ BOOST_AUTO_TEST_CASE(tx_valid) // 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"); + Array tests = read_json(std::string(json_tests::tx_valid, json_tests::tx_valid + sizeof(json_tests::tx_valid))); BOOST_FOREACH(Value& tv, tests) { @@ -91,7 +93,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid) // 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"); + Array tests = read_json(std::string(json_tests::tx_invalid, json_tests::tx_invalid + sizeof(json_tests::tx_invalid))); BOOST_FOREACH(Value& tv, tests) { diff --git a/src/test/wallet_tests.cpp b/src/test/wallet_tests.cpp index a14f6b2b70..51f3b27c8b 100644 --- a/src/test/wallet_tests.cpp +++ b/src/test/wallet_tests.cpp @@ -289,6 +289,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) BOOST_CHECK_NE(fails, RANDOM_REPEATS); } } + empty_wallet(); } BOOST_AUTO_TEST_SUITE_END() |