aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/DoS_tests.cpp16
-rw-r--r--src/test/base58_tests.cpp300
-rw-r--r--src/test/bignum_tests.cpp53
-rw-r--r--src/test/bloom_tests.cpp447
-rw-r--r--src/test/canonical_tests.cpp87
-rw-r--r--src/test/compress_tests.cpp62
-rw-r--r--src/test/data/base58_encode_decode.json14
-rw-r--r--src/test/data/base58_keys_invalid.json152
-rw-r--r--src/test/data/base58_keys_valid.json452
-rw-r--r--src/test/data/sig_canonical.json7
-rw-r--r--src/test/data/sig_noncanonical.json22
-rw-r--r--src/test/miner_tests.cpp49
-rw-r--r--src/test/multisig_tests.cpp22
-rw-r--r--src/test/pmt_tests.cpp98
-rw-r--r--src/test/rpc_tests.cpp99
-rw-r--r--src/test/script_P2SH_tests.cpp30
-rw-r--r--src/test/script_tests.cpp46
-rw-r--r--src/test/serialize_tests.cpp45
-rw-r--r--src/test/test_bitcoin.cpp22
-rw-r--r--src/test/transaction_tests.cpp45
-rw-r--r--src/test/util_tests.cpp8
21 files changed, 1899 insertions, 177 deletions
diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp
index 7f08dd554..b1e98f65e 100644
--- a/src/test/DoS_tests.cpp
+++ b/src/test/DoS_tests.cpp
@@ -46,7 +46,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
BOOST_CHECK(CNode::IsBanned(addr1)); // ... but 1 still should be
dummyNode2.Misbehaving(50);
BOOST_CHECK(CNode::IsBanned(addr2));
-}
+}
BOOST_AUTO_TEST_CASE(DoS_banscore)
{
@@ -99,7 +99,7 @@ BOOST_AUTO_TEST_CASE(DoS_checknbits)
{
using namespace boost::assign; // for 'map_list_of()'
- // Timestamps,nBits from the bitcoin blockchain.
+ // Timestamps,nBits from the bitcoin block chain.
// These are the block-chain checkpoint blocks
typedef std::map<int64, unsigned int> BlockData;
BlockData chainData =
@@ -129,7 +129,6 @@ BOOST_AUTO_TEST_CASE(DoS_checknbits)
// ... but OK if enough time passed for difficulty to adjust downward:
BOOST_CHECK(CheckNBits(firstcheck.second, lastcheck.first+60*60*24*365*4, lastcheck.second, lastcheck.first));
-
}
CTransaction RandomOrphan()
@@ -231,6 +230,7 @@ BOOST_AUTO_TEST_CASE(DoS_checkSig)
key.MakeNewKey(true);
CBasicKeyStore keystore;
keystore.AddKey(key);
+ unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
// 100 orphan transactions:
static const int NPREV=100;
@@ -278,7 +278,7 @@ BOOST_AUTO_TEST_CASE(DoS_checkSig)
mst1 = boost::posix_time::microsec_clock::local_time();
for (unsigned int i = 0; i < 5; i++)
for (unsigned int j = 0; j < tx.vin.size(); j++)
- BOOST_CHECK(VerifySignature(orphans[j], tx, j, true, SIGHASH_ALL));
+ BOOST_CHECK(VerifySignature(CCoins(orphans[j], MEMPOOL_HEIGHT), tx, j, flags, SIGHASH_ALL));
mst2 = boost::posix_time::microsec_clock::local_time();
msdiff = mst2 - mst1;
long nManyValidate = msdiff.total_milliseconds();
@@ -289,13 +289,13 @@ BOOST_AUTO_TEST_CASE(DoS_checkSig)
// Empty a signature, validation should fail:
CScript save = tx.vin[0].scriptSig;
tx.vin[0].scriptSig = CScript();
- BOOST_CHECK(!VerifySignature(orphans[0], tx, 0, true, SIGHASH_ALL));
+ BOOST_CHECK(!VerifySignature(CCoins(orphans[0], MEMPOOL_HEIGHT), tx, 0, flags, SIGHASH_ALL));
tx.vin[0].scriptSig = save;
// Swap signatures, validation should fail:
std::swap(tx.vin[0].scriptSig, tx.vin[1].scriptSig);
- BOOST_CHECK(!VerifySignature(orphans[0], tx, 0, true, SIGHASH_ALL));
- BOOST_CHECK(!VerifySignature(orphans[1], tx, 1, true, SIGHASH_ALL));
+ BOOST_CHECK(!VerifySignature(CCoins(orphans[0], MEMPOOL_HEIGHT), tx, 0, flags, SIGHASH_ALL));
+ BOOST_CHECK(!VerifySignature(CCoins(orphans[1], MEMPOOL_HEIGHT), tx, 1, flags, SIGHASH_ALL));
std::swap(tx.vin[0].scriptSig, tx.vin[1].scriptSig);
// Exercise -maxsigcachesize code:
@@ -305,7 +305,7 @@ BOOST_AUTO_TEST_CASE(DoS_checkSig)
BOOST_CHECK(SignSignature(keystore, orphans[0], tx, 0));
BOOST_CHECK(tx.vin[0].scriptSig != oldSig);
for (unsigned int j = 0; j < tx.vin.size(); j++)
- BOOST_CHECK(VerifySignature(orphans[j], tx, j, true, SIGHASH_ALL));
+ BOOST_CHECK(VerifySignature(CCoins(orphans[j], MEMPOOL_HEIGHT), tx, j, flags, SIGHASH_ALL));
mapArgs.erase("-maxsigcachesize");
LimitOrphanTxSize(0);
diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp
index 3f265f1fe..7602fa93a 100644
--- a/src/test/base58_tests.cpp
+++ b/src/test/base58_tests.cpp
@@ -1,87 +1,259 @@
#include <boost/test/unit_test.hpp>
+#include "json/json_spirit_reader_template.h"
+#include "json/json_spirit_writer_template.h"
+#include "json/json_spirit_utils.h"
#include "base58.h"
+#include "util.h"
+
+using namespace json_spirit;
+extern Array read_json(const std::string& filename);
BOOST_AUTO_TEST_SUITE(base58_tests)
-// TODO:
-// EncodeBase58Check
-// DecodeBase58Check
-// CBase58Data
-// bool SetString(const char* psz)
- // bool SetString(const std::string& str)
- // std::string ToString() const
- // int CompareTo(const CBase58Data& b58) const
- // bool operator==(const CBase58Data& b58) const
- // bool operator<=(const CBase58Data& b58) const
- // bool operator>=(const CBase58Data& b58) const
- // bool operator< (const CBase58Data& b58) const
- // bool operator> (const CBase58Data& b58) const
-
-// CBitcoinAddress
- // bool SetHash160(const uint160& hash160)
- // bool SetPubKey(const std::vector<unsigned char>& vchPubKey)
- // bool IsValid() const
- // CBitcoinAddress()
- // CBitcoinAddress(uint160 hash160In)
- // CBitcoinAddress(const std::vector<unsigned char>& vchPubKey)
- // CBitcoinAddress(const std::string& strAddress)
- // CBitcoinAddress(const char* pszAddress)
- // uint160 GetHash160() const
-
-#define U(x) (reinterpret_cast<const unsigned char*>(x))
-static struct {
- const unsigned char *data;
- int size;
-} vstrIn[] = {
-{U(""), 0},
-{U("\x61"), 1},
-{U("\x62\x62\x62"), 3},
-{U("\x63\x63\x63"), 3},
-{U("\x73\x69\x6d\x70\x6c\x79\x20\x61\x20\x6c\x6f\x6e\x67\x20\x73\x74\x72\x69\x6e\x67"), 20},
-{U("\x00\xeb\x15\x23\x1d\xfc\xeb\x60\x92\x58\x86\xb6\x7d\x06\x52\x99\x92\x59\x15\xae\xb1\x72\xc0\x66\x47"), 25},
-{U("\x51\x6b\x6f\xcd\x0f"), 5},
-{U("\xbf\x4f\x89\x00\x1e\x67\x02\x74\xdd"), 9},
-{U("\x57\x2e\x47\x94"), 4},
-{U("\xec\xac\x89\xca\xd9\x39\x23\xc0\x23\x21"), 10},
-{U("\x10\xc8\x51\x1e"), 4},
-{U("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), 10},
+// Goal: test low-level base58 encoding functionality
+BOOST_AUTO_TEST_CASE(base58_EncodeBase58)
+{
+ Array tests = read_json("base58_encode_decode.json");
+
+ BOOST_FOREACH(Value& tv, tests)
+ {
+ Array test = tv.get_array();
+ std::string strTest = write_string(tv, false);
+ if (test.size() < 2) // Allow for extra stuff (useful for comments)
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+ std::vector<unsigned char> sourcedata = ParseHex(test[0].get_str());
+ std::string base58string = test[1].get_str();
+ BOOST_CHECK_MESSAGE(
+ EncodeBase58(&sourcedata[0], &sourcedata[sourcedata.size()]) == base58string,
+ strTest);
+ }
+}
+
+// Goal: test low-level base58 decoding functionality
+BOOST_AUTO_TEST_CASE(base58_DecodeBase58)
+{
+ Array tests = read_json("base58_encode_decode.json");
+ std::vector<unsigned char> result;
+
+ BOOST_FOREACH(Value& tv, tests)
+ {
+ Array test = tv.get_array();
+ std::string strTest = write_string(tv, false);
+ if (test.size() < 2) // Allow for extra stuff (useful for comments)
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+ std::vector<unsigned char> expected = ParseHex(test[0].get_str());
+ std::string base58string = test[1].get_str();
+ BOOST_CHECK_MESSAGE(DecodeBase58(base58string, result), strTest);
+ BOOST_CHECK_MESSAGE(result.size() == expected.size() && std::equal(result.begin(), result.end(), expected.begin()), strTest);
+ }
+
+ BOOST_CHECK(!DecodeBase58("invalid", result));
+}
+
+// Visitor to check address type
+class TestAddrTypeVisitor : public boost::static_visitor<bool>
+{
+private:
+ std::string exp_addrType;
+public:
+ TestAddrTypeVisitor(const std::string &exp_addrType) : exp_addrType(exp_addrType) { }
+ bool operator()(const CKeyID &id) const
+ {
+ return (exp_addrType == "pubkey");
+ }
+ bool operator()(const CScriptID &id) const
+ {
+ return (exp_addrType == "script");
+ }
+ bool operator()(const CNoDestination &no) const
+ {
+ return (exp_addrType == "none");
+ }
};
-const char *vstrOut[] = {
-"",
-"2g",
-"a3gV",
-"aPEr",
-"2cFupjhnEsSn59qHXstmK2ffpLv2",
-"1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L",
-"ABnLTmg",
-"3SEo3LWLoPntC",
-"3EFU7m",
-"EJDM8drfXA6uyA",
-"Rt5zm",
-"1111111111"
+// Visitor to check address payload
+class TestPayloadVisitor : public boost::static_visitor<bool>
+{
+private:
+ std::vector<unsigned char> exp_payload;
+public:
+ TestPayloadVisitor(std::vector<unsigned char> &exp_payload) : exp_payload(exp_payload) { }
+ bool operator()(const CKeyID &id) const
+ {
+ uint160 exp_key(exp_payload);
+ return exp_key == id;
+ }
+ bool operator()(const CScriptID &id) const
+ {
+ uint160 exp_key(exp_payload);
+ return exp_key == id;
+ }
+ bool operator()(const CNoDestination &no) const
+ {
+ return exp_payload.size() == 0;
+ }
};
-BOOST_AUTO_TEST_CASE(base58_EncodeBase58)
+// Goal: check that parsed keys match test payload
+BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
{
- for (unsigned int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++)
+ Array tests = read_json("base58_keys_valid.json");
+ std::vector<unsigned char> result;
+ CBitcoinSecret secret;
+ CBitcoinAddress addr;
+ // Save global state
+ bool fTestNet_stored = fTestNet;
+
+ BOOST_FOREACH(Value& tv, tests)
{
- BOOST_CHECK_EQUAL(EncodeBase58(vstrIn[i].data, vstrIn[i].data + vstrIn[i].size), vstrOut[i]);
+ Array test = tv.get_array();
+ std::string strTest = write_string(tv, false);
+ if (test.size() < 3) // Allow for extra stuff (useful for comments)
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+ std::string exp_base58string = test[0].get_str();
+ std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str());
+ const Object &metadata = test[2].get_obj();
+ bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
+ bool isTestnet = find_value(metadata, "isTestnet").get_bool();
+ fTestNet = isTestnet; // Override testnet flag
+ if(isPrivkey)
+ {
+ bool isCompressed = find_value(metadata, "isCompressed").get_bool();
+ // Must be valid private key
+ // Note: CBitcoinSecret::SetString tests isValid, whereas CBitcoinAddress does not!
+ BOOST_CHECK_MESSAGE(secret.SetString(exp_base58string), "!SetString:"+ strTest);
+ BOOST_CHECK_MESSAGE(secret.IsValid(), "!IsValid:" + strTest);
+ bool fCompressedOut = false;
+ CSecret privkey = secret.GetSecret(fCompressedOut);
+ BOOST_CHECK_MESSAGE(fCompressedOut == isCompressed, "compressed mismatch:" + strTest);
+ BOOST_CHECK_MESSAGE(privkey.size() == exp_payload.size() && std::equal(privkey.begin(), privkey.end(), exp_payload.begin()), "key mismatch:" + strTest);
+
+ // Private key must be invalid public key
+ addr.SetString(exp_base58string);
+ BOOST_CHECK_MESSAGE(!addr.IsValid(), "IsValid privkey as pubkey:" + strTest);
+ }
+ else
+ {
+ std::string exp_addrType = find_value(metadata, "addrType").get_str(); // "script" or "pubkey"
+ // Must be valid public key
+ BOOST_CHECK_MESSAGE(addr.SetString(exp_base58string), "SetString:" + strTest);
+ BOOST_CHECK_MESSAGE(addr.IsValid(), "!IsValid:" + strTest);
+ BOOST_CHECK_MESSAGE(addr.IsScript() == (exp_addrType == "script"), "isScript mismatch" + strTest);
+ CTxDestination dest = addr.Get();
+ BOOST_CHECK_MESSAGE(boost::apply_visitor(TestAddrTypeVisitor(exp_addrType), dest), "addrType mismatch" + strTest);
+
+ // Public key must be invalid private key
+ secret.SetString(exp_base58string);
+ BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid pubkey as privkey:" + strTest);
+ }
}
+ // Restore global state
+ fTestNet = fTestNet_stored;
}
-BOOST_AUTO_TEST_CASE(base58_DecodeBase58)
+// Goal: check that generated keys match test vectors
+BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
{
+ Array tests = read_json("base58_keys_valid.json");
std::vector<unsigned char> result;
- for (unsigned int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++)
+ // Save global state
+ bool fTestNet_stored = fTestNet;
+
+ BOOST_FOREACH(Value& tv, tests)
{
- std::vector<unsigned char> expected(vstrIn[i].data, vstrIn[i].data + vstrIn[i].size);
- BOOST_CHECK(DecodeBase58(vstrOut[i], result));
- BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
+ Array test = tv.get_array();
+ std::string strTest = write_string(tv, false);
+ if (test.size() < 3) // Allow for extra stuff (useful for comments)
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+ std::string exp_base58string = test[0].get_str();
+ std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str());
+ const Object &metadata = test[2].get_obj();
+ bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
+ bool isTestnet = find_value(metadata, "isTestnet").get_bool();
+ fTestNet = isTestnet; // Override testnet flag
+ if(isPrivkey)
+ {
+ bool isCompressed = find_value(metadata, "isCompressed").get_bool();
+ CBitcoinSecret secret;
+ secret.SetSecret(CSecret(exp_payload.begin(), exp_payload.end()), isCompressed);
+ BOOST_CHECK_MESSAGE(secret.ToString() == exp_base58string, "result mismatch: " + strTest);
+ }
+ else
+ {
+ std::string exp_addrType = find_value(metadata, "addrType").get_str();
+ CTxDestination dest;
+ if(exp_addrType == "pubkey")
+ {
+ dest = CKeyID(uint160(exp_payload));
+ }
+ else if(exp_addrType == "script")
+ {
+ dest = CScriptID(uint160(exp_payload));
+ }
+ else if(exp_addrType == "none")
+ {
+ dest = CNoDestination();
+ }
+ else
+ {
+ BOOST_ERROR("Bad addrtype: " << strTest);
+ continue;
+ }
+ CBitcoinAddress addrOut;
+ BOOST_CHECK_MESSAGE(boost::apply_visitor(CBitcoinAddressVisitor(&addrOut), dest), "encode dest: " + strTest);
+ BOOST_CHECK_MESSAGE(addrOut.ToString() == exp_base58string, "mismatch: " + strTest);
+ }
+ }
+
+ // Visiting a CNoDestination must fail
+ CBitcoinAddress dummyAddr;
+ CTxDestination nodest = CNoDestination();
+ BOOST_CHECK(!boost::apply_visitor(CBitcoinAddressVisitor(&dummyAddr), nodest));
+
+ // Restore global state
+ fTestNet = fTestNet_stored;
+}
+
+// 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
+ std::vector<unsigned char> result;
+ CBitcoinSecret secret;
+ CBitcoinAddress addr;
+
+ BOOST_FOREACH(Value& tv, tests)
+ {
+ Array test = tv.get_array();
+ std::string strTest = write_string(tv, false);
+ if (test.size() < 1) // Allow for extra stuff (useful for comments)
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+ std::string exp_base58string = test[0].get_str();
+
+ // must be invalid as public and as private key
+ addr.SetString(exp_base58string);
+ BOOST_CHECK_MESSAGE(!addr.IsValid(), "IsValid pubkey:" + strTest);
+ secret.SetString(exp_base58string);
+ BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid privkey:" + strTest);
}
- BOOST_CHECK(!DecodeBase58("invalid", result));
}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/bignum_tests.cpp b/src/test/bignum_tests.cpp
index 744681871..5b898d149 100644
--- a/src/test/bignum_tests.cpp
+++ b/src/test/bignum_tests.cpp
@@ -122,4 +122,57 @@ BOOST_AUTO_TEST_CASE(bignum_setint64)
}
}
+
+BOOST_AUTO_TEST_CASE(bignum_SetCompact)
+{
+ CBigNum num;
+ num.SetCompact(0);
+ BOOST_CHECK_EQUAL(num.GetHex(), "0");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0);
+
+ num.SetCompact(0x00123456);
+ BOOST_CHECK_EQUAL(num.GetHex(), "0");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0);
+
+ num.SetCompact(0x01123456);
+ BOOST_CHECK_EQUAL(num.GetHex(), "12");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x01120000);
+
+ // Make sure that we don't generate compacts with the 0x00800000 bit set
+ num = 0x80;
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x02008000);
+
+ num.SetCompact(0x01fedcba);
+ BOOST_CHECK_EQUAL(num.GetHex(), "-7e");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x01fe0000);
+
+ num.SetCompact(0x02123456);
+ BOOST_CHECK_EQUAL(num.GetHex(), "1234");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x02123400);
+
+ num.SetCompact(0x03123456);
+ BOOST_CHECK_EQUAL(num.GetHex(), "123456");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x03123456);
+
+ num.SetCompact(0x04123456);
+ BOOST_CHECK_EQUAL(num.GetHex(), "12345600");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x04123456);
+
+ num.SetCompact(0x04923456);
+ BOOST_CHECK_EQUAL(num.GetHex(), "-12345600");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x04923456);
+
+ num.SetCompact(0x05009234);
+ BOOST_CHECK_EQUAL(num.GetHex(), "92340000");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x05009234);
+
+ num.SetCompact(0x20123456);
+ BOOST_CHECK_EQUAL(num.GetHex(), "1234560000000000000000000000000000000000000000000000000000000000");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x20123456);
+
+ num.SetCompact(0xff123456);
+ BOOST_CHECK_EQUAL(num.GetHex(), "123456000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0xff123456);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp
new file mode 100644
index 000000000..4a2851cf4
--- /dev/null
+++ b/src/test/bloom_tests.cpp
@@ -0,0 +1,447 @@
+#include <boost/test/unit_test.hpp>
+#include <vector>
+
+#include "bloom.h"
+#include "util.h"
+#include "key.h"
+#include "base58.h"
+#include "main.h"
+
+using namespace std;
+using namespace boost::tuples;
+
+BOOST_AUTO_TEST_SUITE(bloom_tests)
+
+BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize)
+{
+ CBloomFilter filter(3, 0.01, 0, BLOOM_UPDATE_ALL);
+
+ filter.insert(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8"));
+ BOOST_CHECK_MESSAGE( filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "BloomFilter doesn't contain just-inserted object!");
+ // One bit different in first byte
+ BOOST_CHECK_MESSAGE(!filter.contains(ParseHex("19108ad8ed9bb6274d3980bab5a85c048f0950c8")), "BloomFilter contains something it shouldn't!");
+
+ filter.insert(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee"));
+ BOOST_CHECK_MESSAGE(filter.contains(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee")), "BloomFilter doesn't contain just-inserted object (2)!");
+
+ filter.insert(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5"));
+ BOOST_CHECK_MESSAGE(filter.contains(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5")), "BloomFilter doesn't contain just-inserted object (3)!");
+
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ filter.Serialize(stream, SER_NETWORK, PROTOCOL_VERSION);
+
+ vector<unsigned char> vch = ParseHex("03614e9b050000000000000001");
+ vector<char> expected(vch.size());
+
+ for (unsigned int i = 0; i < vch.size(); i++)
+ expected[i] = (char)vch[i];
+
+ BOOST_CHECK_EQUAL_COLLECTIONS(stream.begin(), stream.end(), expected.begin(), expected.end());
+}
+
+BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize_with_tweak)
+{
+ // Same test as bloom_create_insert_serialize, but we add a nTweak of 100
+ CBloomFilter filter(3, 0.01, 2147483649, BLOOM_UPDATE_ALL);
+
+ filter.insert(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8"));
+ BOOST_CHECK_MESSAGE( filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "BloomFilter doesn't contain just-inserted object!");
+ // One bit different in first byte
+ BOOST_CHECK_MESSAGE(!filter.contains(ParseHex("19108ad8ed9bb6274d3980bab5a85c048f0950c8")), "BloomFilter contains something it shouldn't!");
+
+ filter.insert(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee"));
+ BOOST_CHECK_MESSAGE(filter.contains(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee")), "BloomFilter doesn't contain just-inserted object (2)!");
+
+ filter.insert(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5"));
+ BOOST_CHECK_MESSAGE(filter.contains(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5")), "BloomFilter doesn't contain just-inserted object (3)!");
+
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ filter.Serialize(stream, SER_NETWORK, PROTOCOL_VERSION);
+
+ vector<unsigned char> vch = ParseHex("03ce4299050000000100008001");
+ vector<char> expected(vch.size());
+
+ for (unsigned int i = 0; i < vch.size(); i++)
+ expected[i] = (char)vch[i];
+
+ BOOST_CHECK_EQUAL_COLLECTIONS(stream.begin(), stream.end(), expected.begin(), expected.end());
+}
+
+BOOST_AUTO_TEST_CASE(bloom_create_insert_key)
+{
+ string strSecret = string("5Kg1gnAjaLfKiwhhPpGS3QfRg2m6awQvaj98JCZBZQ5SuS2F15C");
+ CBitcoinSecret vchSecret;
+ BOOST_CHECK(vchSecret.SetString(strSecret));
+
+ CKey key;
+ bool fCompressed;
+ CSecret secret = vchSecret.GetSecret(fCompressed);
+ key.SetSecret(secret, fCompressed);
+
+ CBloomFilter filter(2, 0.001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(key.GetPubKey().Raw());
+ uint160 hash = key.GetPubKey().GetID();
+ filter.insert(vector<unsigned char>(hash.begin(), hash.end()));
+
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ filter.Serialize(stream, SER_NETWORK, PROTOCOL_VERSION);
+
+ vector<unsigned char> vch = ParseHex("038fc16b080000000000000001");
+ vector<char> expected(vch.size());
+
+ for (unsigned int i = 0; i < vch.size(); i++)
+ expected[i] = (char)vch[i];
+
+ BOOST_CHECK_EQUAL_COLLECTIONS(stream.begin(), stream.end(), expected.begin(), expected.end());
+}
+
+BOOST_AUTO_TEST_CASE(bloom_match)
+{
+ // Random real transaction (b4749f017444b051c44dfd2720e88f314ff94f3dd6d56d40ef65854fcd7fff6b)
+ CTransaction tx;
+ CDataStream stream(ParseHex("01000000010b26e9b7735eb6aabdf358bab62f9816a21ba9ebdb719d5299e88607d722c190000000008b4830450220070aca44506c5cef3a16ed519d7c3c39f8aab192c4e1c90d065f37b8a4af6141022100a8e160b856c2d43d27d8fba71e5aef6405b8643ac4cb7cb3c462aced7f14711a0141046d11fee51b0e60666d5049a9101a72741df480b96ee26488a4d3466b95c9a40ac5eeef87e10a5cd336c19a84565f80fa6c547957b7700ff4dfbdefe76036c339ffffffff021bff3d11000000001976a91404943fdd508053c75000106d3bc6e2754dbcff1988ac2f15de00000000001976a914a266436d2965547608b9e15d9032a7b9d64fa43188ac00000000"), SER_DISK, CLIENT_VERSION);
+ stream >> tx;
+
+ // and one which spends it (e2769b09e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436)
+ unsigned char ch[] = {0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0xff, 0x7f, 0xcd, 0x4f, 0x85, 0x65, 0xef, 0x40, 0x6d, 0xd5, 0xd6, 0x3d, 0x4f, 0xf9, 0x4f, 0x31, 0x8f, 0xe8, 0x20, 0x27, 0xfd, 0x4d, 0xc4, 0x51, 0xb0, 0x44, 0x74, 0x01, 0x9f, 0x74, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x49, 0x30, 0x46, 0x02, 0x21, 0x00, 0xda, 0x0d, 0xc6, 0xae, 0xce, 0xfe, 0x1e, 0x06, 0xef, 0xdf, 0x05, 0x77, 0x37, 0x57, 0xde, 0xb1, 0x68, 0x82, 0x09, 0x30, 0xe3, 0xb0, 0xd0, 0x3f, 0x46, 0xf5, 0xfc, 0xf1, 0x50, 0xbf, 0x99, 0x0c, 0x02, 0x21, 0x00, 0xd2, 0x5b, 0x5c, 0x87, 0x04, 0x00, 0x76, 0xe4, 0xf2, 0x53, 0xf8, 0x26, 0x2e, 0x76, 0x3e, 0x2d, 0xd5, 0x1e, 0x7f, 0xf0, 0xbe, 0x15, 0x77, 0x27, 0xc4, 0xbc, 0x42, 0x80, 0x7f, 0x17, 0xbd, 0x39, 0x01, 0x41, 0x04, 0xe6, 0xc2, 0x6e, 0xf6, 0x7d, 0xc6, 0x10, 0xd2, 0xcd, 0x19, 0x24, 0x84, 0x78, 0x9a, 0x6c, 0xf9, 0xae, 0xa9, 0x93, 0x0b, 0x94, 0x4b, 0x7e, 0x2d, 0xb5, 0x34, 0x2b, 0x9d, 0x9e, 0x5b, 0x9f, 0xf7, 0x9a, 0xff, 0x9a, 0x2e, 0xe1, 0x97, 0x8d, 0xd7, 0xfd, 0x01, 0xdf, 0xc5, 0x22, 0xee, 0x02, 0x28, 0x3d, 0x3b, 0x06, 0xa9, 0xd0, 0x3a, 0xcf, 0x80, 0x96, 0x96, 0x8d, 0x7d, 0xbb, 0x0f, 0x91, 0x78, 0xff, 0xff, 0xff, 0xff, 0x02, 0x8b, 0xa7, 0x94, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xba, 0xde, 0xec, 0xfd, 0xef, 0x05, 0x07, 0x24, 0x7f, 0xc8, 0xf7, 0x42, 0x41, 0xd7, 0x3b, 0xc0, 0x39, 0x97, 0x2d, 0x7b, 0x88, 0xac, 0x40, 0x94, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xc1, 0x09, 0x32, 0x48, 0x3f, 0xec, 0x93, 0xed, 0x51, 0xf5, 0xfe, 0x95, 0xe7, 0x25, 0x59, 0xf2, 0xcc, 0x70, 0x43, 0xf9, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00};
+ vector<unsigned char> vch(ch, ch + sizeof(ch) -1);
+ CDataStream spendStream(vch, SER_DISK, CLIENT_VERSION);
+ CTransaction spendingTx;
+ spendStream >> spendingTx;
+
+ CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(uint256("0xb4749f017444b051c44dfd2720e88f314ff94f3dd6d56d40ef65854fcd7fff6b"));
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match tx hash");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ // byte-reversed tx hash
+ filter.insert(ParseHex("6bff7fcd4f8565ef406dd5d63d4ff94f318fe82027fd4dc451b04474019f74b4"));
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match manually serialized tx hash");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(ParseHex("30450220070aca44506c5cef3a16ed519d7c3c39f8aab192c4e1c90d065f37b8a4af6141022100a8e160b856c2d43d27d8fba71e5aef6405b8643ac4cb7cb3c462aced7f14711a01"));
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match input signature");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(ParseHex("046d11fee51b0e60666d5049a9101a72741df480b96ee26488a4d3466b95c9a40ac5eeef87e10a5cd336c19a84565f80fa6c547957b7700ff4dfbdefe76036c339"));
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match input pub key");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(ParseHex("04943fdd508053c75000106d3bc6e2754dbcff19"));
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match output address");
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(spendingTx, spendingTx.GetHash()), "Simple Bloom filter didn't add output");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(ParseHex("a266436d2965547608b9e15d9032a7b9d64fa431"));
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match output address");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(COutPoint(uint256("0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 0));
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match COutPoint");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ COutPoint prevOutPoint(uint256("0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 0);
+ {
+ vector<unsigned char> data(32 + sizeof(unsigned int));
+ memcpy(&data[0], prevOutPoint.hash.begin(), 32);
+ memcpy(&data[32], &prevOutPoint.n, sizeof(unsigned int));
+ filter.insert(data);
+ }
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match manually serialized COutPoint");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(uint256("00000009e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436"));
+ BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter matched random tx hash");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(ParseHex("0000006d2965547608b9e15d9032a7b9d64fa431"));
+ BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter matched random address");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(COutPoint(uint256("0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 1));
+ BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter matched COutPoint for an output we didn't care about");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(COutPoint(uint256("0x000000d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 0));
+ BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter matched COutPoint for an output we didn't care about");
+}
+
+BOOST_AUTO_TEST_CASE(merkle_block_1)
+{
+ // Random real block (0000000000013b8ab2cd513b0261a14096412195a72a0c4827d229dcc7e0f7af)
+ // With 9 txes
+ CBlock block;
+ CDataStream stream(ParseHex("0100000090f0a9f110702f808219ebea1173056042a714bad51b916cb6800000000000005275289558f51c9966699404ae2294730c3c9f9bda53523ce50e9b95e558da2fdb261b4d4c86041b1ab1bf930901000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07044c86041b0146ffffffff0100f2052a01000000434104e18f7afbe4721580e81e8414fc8c24d7cfacf254bb5c7b949450c3e997c2dc1242487a8169507b631eb3771f2b425483fb13102c4eb5d858eef260fe70fbfae0ac00000000010000000196608ccbafa16abada902780da4dc35dafd7af05fa0da08cf833575f8cf9e836000000004a493046022100dab24889213caf43ae6adc41cf1c9396c08240c199f5225acf45416330fd7dbd022100fe37900e0644bf574493a07fc5edba06dbc07c311b947520c2d514bc5725dcb401ffffffff0100f2052a010000001976a914f15d1921f52e4007b146dfa60f369ed2fc393ce288ac000000000100000001fb766c1288458c2bafcfec81e48b24d98ec706de6b8af7c4e3c29419bfacb56d000000008c493046022100f268ba165ce0ad2e6d93f089cfcd3785de5c963bb5ea6b8c1b23f1ce3e517b9f022100da7c0f21adc6c401887f2bfd1922f11d76159cbc597fbd756a23dcbb00f4d7290141042b4e8625a96127826915a5b109852636ad0da753c9e1d5606a50480cd0c40f1f8b8d898235e571fe9357d9ec842bc4bba1827daaf4de06d71844d0057707966affffffff0280969800000000001976a9146963907531db72d0ed1a0cfb471ccb63923446f388ac80d6e34c000000001976a914f0688ba1c0d1ce182c7af6741e02658c7d4dfcd388ac000000000100000002c40297f730dd7b5a99567eb8d27b78758f607507c52292d02d4031895b52f2ff010000008b483045022100f7edfd4b0aac404e5bab4fd3889e0c6c41aa8d0e6fa122316f68eddd0a65013902205b09cc8b2d56e1cd1f7f2fafd60a129ed94504c4ac7bdc67b56fe67512658b3e014104732012cb962afa90d31b25d8fb0e32c94e513ab7a17805c14ca4c3423e18b4fb5d0e676841733cb83abaf975845c9f6f2a8097b7d04f4908b18368d6fc2d68ecffffffffca5065ff9617cbcba45eb23726df6498a9b9cafed4f54cbab9d227b0035ddefb000000008a473044022068010362a13c7f9919fa832b2dee4e788f61f6f5d344a7c2a0da6ae740605658022006d1af525b9a14a35c003b78b72bd59738cd676f845d1ff3fc25049e01003614014104732012cb962afa90d31b25d8fb0e32c94e513ab7a17805c14ca4c3423e18b4fb5d0e676841733cb83abaf975845c9f6f2a8097b7d04f4908b18368d6fc2d68ecffffffff01001ec4110200000043410469ab4181eceb28985b9b4e895c13fa5e68d85761b7eee311db5addef76fa8621865134a221bd01f28ec9999ee3e021e60766e9d1f3458c115fb28650605f11c9ac000000000100000001cdaf2f758e91c514655e2dc50633d1e4c84989f8aa90a0dbc883f0d23ed5c2fa010000008b48304502207ab51be6f12a1962ba0aaaf24a20e0b69b27a94fac5adf45aa7d2d18ffd9236102210086ae728b370e5329eead9accd880d0cb070aea0c96255fae6c4f1ddcce1fd56e014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff02404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37c32f5c388ac002d3101000000001976a9141befba0cdc1ad56529371864d9f6cb042faa06b588ac000000000100000001b4a47603e71b61bc3326efd90111bf02d2f549b067f4c4a8fa183b57a0f800cb010000008a4730440220177c37f9a505c3f1a1f0ce2da777c339bd8339ffa02c7cb41f0a5804f473c9230220585b25a2ee80eb59292e52b987dad92acb0c64eced92ed9ee105ad153cdb12d001410443bd44f683467e549dae7d20d1d79cbdb6df985c6e9c029c8d0c6cb46cc1a4d3cf7923c5021b27f7a0b562ada113bc85d5fda5a1b41e87fe6e8802817cf69996ffffffff0280651406000000001976a9145505614859643ab7b547cd7f1f5e7e2a12322d3788ac00aa0271000000001976a914ea4720a7a52fc166c55ff2298e07baf70ae67e1b88ac00000000010000000586c62cd602d219bb60edb14a3e204de0705176f9022fe49a538054fb14abb49e010000008c493046022100f2bc2aba2534becbdf062eb993853a42bbbc282083d0daf9b4b585bd401aa8c9022100b1d7fd7ee0b95600db8535bbf331b19eed8d961f7a8e54159c53675d5f69df8c014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff03ad0e58ccdac3df9dc28a218bcf6f1997b0a93306faaa4b3a28ae83447b2179010000008b483045022100be12b2937179da88599e27bb31c3525097a07cdb52422d165b3ca2f2020ffcf702200971b51f853a53d644ebae9ec8f3512e442b1bcb6c315a5b491d119d10624c83014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff2acfcab629bbc8685792603762c921580030ba144af553d271716a95089e107b010000008b483045022100fa579a840ac258871365dd48cd7552f96c8eea69bd00d84f05b283a0dab311e102207e3c0ee9234814cfbb1b659b83671618f45abc1326b9edcc77d552a4f2a805c0014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffffdcdc6023bbc9944a658ddc588e61eacb737ddf0a3cd24f113b5a8634c517fcd2000000008b4830450221008d6df731df5d32267954bd7d2dda2302b74c6c2a6aa5c0ca64ecbabc1af03c75022010e55c571d65da7701ae2da1956c442df81bbf076cdbac25133f99d98a9ed34c014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffffe15557cd5ce258f479dfd6dc6514edf6d7ed5b21fcfa4a038fd69f06b83ac76e010000008b483045022023b3e0ab071eb11de2eb1cc3a67261b866f86bf6867d4558165f7c8c8aca2d86022100dc6e1f53a91de3efe8f63512850811f26284b62f850c70ca73ed5de8771fb451014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff01404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37c32f5c388ac00000000010000000166d7577163c932b4f9690ca6a80b6e4eb001f0a2fa9023df5595602aae96ed8d000000008a4730440220262b42546302dfb654a229cefc86432b89628ff259dc87edd1154535b16a67e102207b4634c020a97c3e7bbd0d4d19da6aa2269ad9dded4026e896b213d73ca4b63f014104979b82d02226b3a4597523845754d44f13639e3bf2df5e82c6aab2bdc79687368b01b1ab8b19875ae3c90d661a3d0a33161dab29934edeb36aa01976be3baf8affffffff02404b4c00000000001976a9144854e695a02af0aeacb823ccbc272134561e0a1688ac40420f00000000001976a914abee93376d6b37b5c2940655a6fcaf1c8e74237988ac0000000001000000014e3f8ef2e91349a9059cb4f01e54ab2597c1387161d3da89919f7ea6acdbb371010000008c49304602210081f3183471a5ca22307c0800226f3ef9c353069e0773ac76bb580654d56aa523022100d4c56465bdc069060846f4fbf2f6b20520b2a80b08b168b31e66ddb9c694e240014104976c79848e18251612f8940875b2b08d06e6dc73b9840e8860c066b7e87432c477e9a59a453e71e6d76d5fe34058b800a098fc1740ce3012e8fc8a00c96af966ffffffff02c0e1e400000000001976a9144134e75a6fcb6042034aab5e18570cf1f844f54788ac404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37c32f5c388ac00000000"), SER_NETWORK, PROTOCOL_VERSION);
+ stream >> block;
+
+ CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ // Match the last transaction
+ filter.insert(uint256("0x74d681e0e03bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20"));
+
+ CMerkleBlock merkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 1);
+ pair<unsigned int, uint256> pair = merkleBlock.vMatchedTxn[0];
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256("0x74d681e0e03bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 8);
+
+ vector<uint256> vMatched;
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot);
+ BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
+ for (unsigned int i = 0; i < vMatched.size(); i++)
+ BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
+
+ // Also match the 8th transaction
+ filter.insert(uint256("0xdd1fd2a6fc16404faf339881a90adbde7f4f728691ac62e8f168809cdfae1053"));
+ merkleBlock = CMerkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 2);
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[1] == pair);
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256("0xdd1fd2a6fc16404faf339881a90adbde7f4f728691ac62e8f168809cdfae1053"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 7);
+
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot);
+ BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
+ for (unsigned int i = 0; i < vMatched.size(); i++)
+ BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
+}
+
+BOOST_AUTO_TEST_CASE(merkle_block_2)
+{
+ // Random real block (000000005a4ded781e667e06ceefafb71410b511fe0d5adc3e5a27ecbec34ae6)
+ // With 4 txes
+ CBlock block;
+ CDataStream stream(ParseHex("0100000075616236cc2126035fadb38deb65b9102cc2c41c09cdf29fc051906800000000fe7d5e12ef0ff901f6050211249919b1c0653771832b3a80c66cea42847f0ae1d4d26e49ffff001d00f0a4410401000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d029105ffffffff0100f2052a010000004341046d8709a041d34357697dfcb30a9d05900a6294078012bf3bb09c6f9b525f1d16d5503d7905db1ada9501446ea00728668fc5719aa80be2fdfc8a858a4dbdd4fbac00000000010000000255605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c268d28350000000049483045022100aa46504baa86df8a33b1192b1b9367b4d729dc41e389f2c04f3e5c7f0559aae702205e82253a54bf5c4f65b7428551554b2045167d6d206dfe6a2e198127d3f7df1501ffffffff55605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c268d2835010000004847304402202329484c35fa9d6bb32a55a70c0982f606ce0e3634b69006138683bcd12cbb6602200c28feb1e2555c3210f1dddb299738b4ff8bbe9667b68cb8764b5ac17b7adf0001ffffffff0200e1f505000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d8f000000004341044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45afac0000000001000000025f9a06d3acdceb56be1bfeaa3e8a25e62d182fa24fefe899d1c17f1dad4c2028000000004847304402205d6058484157235b06028c30736c15613a28bdb768ee628094ca8b0030d4d6eb0220328789c9a2ec27ddaec0ad5ef58efded42e6ea17c2e1ce838f3d6913f5e95db601ffffffff5f9a06d3acdceb56be1bfeaa3e8a25e62d182fa24fefe899d1c17f1dad4c2028010000004a493046022100c45af050d3cea806cedd0ab22520c53ebe63b987b8954146cdca42487b84bdd6022100b9b027716a6b59e640da50a864d6dd8a0ef24c76ce62391fa3eabaf4d2886d2d01ffffffff0200e1f505000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d8f000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac000000000100000002e2274e5fea1bf29d963914bd301aa63b64daaf8a3e88f119b5046ca5738a0f6b0000000048473044022016e7a727a061ea2254a6c358376aaa617ac537eb836c77d646ebda4c748aac8b0220192ce28bf9f2c06a6467e6531e27648d2b3e2e2bae85159c9242939840295ba501ffffffffe2274e5fea1bf29d963914bd301aa63b64daaf8a3e88f119b5046ca5738a0f6b010000004a493046022100b7a1a755588d4190118936e15cd217d133b0e4a53c3c15924010d5648d8925c9022100aaef031874db2114f2d869ac2de4ae53908fbfea5b2b1862e181626bb9005c9f01ffffffff0200e1f505000000004341044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45afac00180d8f000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00000000"), SER_NETWORK, PROTOCOL_VERSION);
+ stream >> block;
+
+ CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ // Match the first transaction
+ filter.insert(uint256("0xe980fe9f792d014e73b95203dc1335c5f9ce19ac537a419e6df5b47aecb93b70"));
+
+ CMerkleBlock merkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 1);
+ pair<unsigned int, uint256> pair = merkleBlock.vMatchedTxn[0];
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256("0xe980fe9f792d014e73b95203dc1335c5f9ce19ac537a419e6df5b47aecb93b70"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 0);
+
+ vector<uint256> vMatched;
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot);
+ BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
+ for (unsigned int i = 0; i < vMatched.size(); i++)
+ BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
+
+ // Match an output from the second transaction (the pubkey for address 1DZTzaBHUDM7T3QvUKBz4qXMRpkg8jsfB5)
+ // This should match the third transaction because it spends the output matched
+ // It also matches the fourth transaction, which spends to the pubkey again
+ filter.insert(ParseHex("044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45af"));
+
+ merkleBlock = CMerkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 4);
+
+ BOOST_CHECK(pair == merkleBlock.vMatchedTxn[0]);
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[1].second == uint256("0x28204cad1d7fc1d199e8ef4fa22f182de6258a3eaafe1bbe56ebdcacd3069a5f"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[1].first == 1);
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[2].second == uint256("0x6b0f8a73a56c04b519f1883e8aafda643ba61a30bd1439969df21bea5f4e27e2"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[2].first == 2);
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[3].second == uint256("0x3c1d7e82342158e4109df2e0b6348b6e84e403d8b4046d7007663ace63cddb23"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[3].first == 3);
+
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot);
+ BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
+ for (unsigned int i = 0; i < vMatched.size(); i++)
+ BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
+}
+
+BOOST_AUTO_TEST_CASE(merkle_block_2_with_update_none)
+{
+ // Random real block (000000005a4ded781e667e06ceefafb71410b511fe0d5adc3e5a27ecbec34ae6)
+ // With 4 txes
+ CBlock block;
+ CDataStream stream(ParseHex("0100000075616236cc2126035fadb38deb65b9102cc2c41c09cdf29fc051906800000000fe7d5e12ef0ff901f6050211249919b1c0653771832b3a80c66cea42847f0ae1d4d26e49ffff001d00f0a4410401000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d029105ffffffff0100f2052a010000004341046d8709a041d34357697dfcb30a9d05900a6294078012bf3bb09c6f9b525f1d16d5503d7905db1ada9501446ea00728668fc5719aa80be2fdfc8a858a4dbdd4fbac00000000010000000255605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c268d28350000000049483045022100aa46504baa86df8a33b1192b1b9367b4d729dc41e389f2c04f3e5c7f0559aae702205e82253a54bf5c4f65b7428551554b2045167d6d206dfe6a2e198127d3f7df1501ffffffff55605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c268d2835010000004847304402202329484c35fa9d6bb32a55a70c0982f606ce0e3634b69006138683bcd12cbb6602200c28feb1e2555c3210f1dddb299738b4ff8bbe9667b68cb8764b5ac17b7adf0001ffffffff0200e1f505000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d8f000000004341044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45afac0000000001000000025f9a06d3acdceb56be1bfeaa3e8a25e62d182fa24fefe899d1c17f1dad4c2028000000004847304402205d6058484157235b06028c30736c15613a28bdb768ee628094ca8b0030d4d6eb0220328789c9a2ec27ddaec0ad5ef58efded42e6ea17c2e1ce838f3d6913f5e95db601ffffffff5f9a06d3acdceb56be1bfeaa3e8a25e62d182fa24fefe899d1c17f1dad4c2028010000004a493046022100c45af050d3cea806cedd0ab22520c53ebe63b987b8954146cdca42487b84bdd6022100b9b027716a6b59e640da50a864d6dd8a0ef24c76ce62391fa3eabaf4d2886d2d01ffffffff0200e1f505000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d8f000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac000000000100000002e2274e5fea1bf29d963914bd301aa63b64daaf8a3e88f119b5046ca5738a0f6b0000000048473044022016e7a727a061ea2254a6c358376aaa617ac537eb836c77d646ebda4c748aac8b0220192ce28bf9f2c06a6467e6531e27648d2b3e2e2bae85159c9242939840295ba501ffffffffe2274e5fea1bf29d963914bd301aa63b64daaf8a3e88f119b5046ca5738a0f6b010000004a493046022100b7a1a755588d4190118936e15cd217d133b0e4a53c3c15924010d5648d8925c9022100aaef031874db2114f2d869ac2de4ae53908fbfea5b2b1862e181626bb9005c9f01ffffffff0200e1f505000000004341044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45afac00180d8f000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00000000"), SER_NETWORK, PROTOCOL_VERSION);
+ stream >> block;
+
+ CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_NONE);
+ // Match the first transaction
+ filter.insert(uint256("0xe980fe9f792d014e73b95203dc1335c5f9ce19ac537a419e6df5b47aecb93b70"));
+
+ CMerkleBlock merkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 1);
+ pair<unsigned int, uint256> pair = merkleBlock.vMatchedTxn[0];
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256("0xe980fe9f792d014e73b95203dc1335c5f9ce19ac537a419e6df5b47aecb93b70"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 0);
+
+ vector<uint256> vMatched;
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot);
+ BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
+ for (unsigned int i = 0; i < vMatched.size(); i++)
+ BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
+
+ // Match an output from the second transaction (the pubkey for address 1DZTzaBHUDM7T3QvUKBz4qXMRpkg8jsfB5)
+ // This should not match the third transaction though it spends the output matched
+ // It will match the fourth transaction, which has another pay-to-pubkey output to the same address
+ filter.insert(ParseHex("044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45af"));
+
+ merkleBlock = CMerkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 3);
+
+ BOOST_CHECK(pair == merkleBlock.vMatchedTxn[0]);
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[1].second == uint256("0x28204cad1d7fc1d199e8ef4fa22f182de6258a3eaafe1bbe56ebdcacd3069a5f"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[1].first == 1);
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[2].second == uint256("0x3c1d7e82342158e4109df2e0b6348b6e84e403d8b4046d7007663ace63cddb23"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[2].first == 3);
+
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot);
+ BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
+ for (unsigned int i = 0; i < vMatched.size(); i++)
+ BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
+}
+
+BOOST_AUTO_TEST_CASE(merkle_block_3_and_serialize)
+{
+ // Random real block (000000000000dab0130bbcc991d3d7ae6b81aa6f50a798888dfe62337458dc45)
+ // With one tx
+ CBlock block;
+ CDataStream stream(ParseHex("0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d630101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08044c86041b020a02ffffffff0100f2052a01000000434104ecd3229b0571c3be876feaac0442a9f13c5a572742927af1dc623353ecf8c202225f64868137a18cdd85cbbb4c74fbccfd4f49639cf1bdc94a5672bb15ad5d4cac00000000"), SER_NETWORK, PROTOCOL_VERSION);
+ stream >> block;
+
+ CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ // Match the only transaction
+ filter.insert(uint256("0x63194f18be0af63f2c6bc9dc0f777cbefed3d9415c4af83f3ee3a3d669c00cb5"));
+
+ CMerkleBlock merkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 1);
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256("0x63194f18be0af63f2c6bc9dc0f777cbefed3d9415c4af83f3ee3a3d669c00cb5"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 0);
+
+ vector<uint256> vMatched;
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot);
+ BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
+ for (unsigned int i = 0; i < vMatched.size(); i++)
+ BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
+
+ CDataStream merkleStream(SER_NETWORK, PROTOCOL_VERSION);
+ merkleStream << merkleBlock;
+
+ vector<unsigned char> vch = ParseHex("0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d630100000001b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f19630101");
+ vector<char> expected(vch.size());
+
+ for (unsigned int i = 0; i < vch.size(); i++)
+ expected[i] = (char)vch[i];
+
+ BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), expected.end(), merkleStream.begin(), merkleStream.end());
+}
+
+BOOST_AUTO_TEST_CASE(merkle_block_4)
+{
+ // Random real block (000000000000b731f2eef9e8c63173adfb07e41bd53eb0ef0a6b720d6cb6dea4)
+ // With 7 txes
+ CBlock block;
+ CDataStream stream(ParseHex("0100000082bb869cf3a793432a66e826e05a6fc37469f8efb7421dc880670100000000007f16c5962e8bd963659c793ce370d95f093bc7e367117b3c30c1f8fdd0d9728776381b4d4c86041b554b85290701000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07044c86041b0136ffffffff0100f2052a01000000434104eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a2252247d97a46a91ac000000000100000001bcad20a6a29827d1424f08989255120bf7f3e9e3cdaaa6bb31b0737fe048724300000000494830450220356e834b046cadc0f8ebb5a8a017b02de59c86305403dad52cd77b55af062ea10221009253cd6c119d4729b77c978e1e2aa19f5ea6e0e52b3f16e32fa608cd5bab753901ffffffff02008d380c010000001976a9142b4b8072ecbba129b6453c63e129e643207249ca88ac0065cd1d000000001976a9141b8dd13b994bcfc787b32aeadf58ccb3615cbd5488ac000000000100000003fdacf9b3eb077412e7a968d2e4f11b9a9dee312d666187ed77ee7d26af16cb0b000000008c493046022100ea1608e70911ca0de5af51ba57ad23b9a51db8d28f82c53563c56a05c20f5a87022100a8bdc8b4a8acc8634c6b420410150775eb7f2474f5615f7fccd65af30f310fbf01410465fdf49e29b06b9a1582287b6279014f834edc317695d125ef623c1cc3aaece245bd69fcad7508666e9c74a49dc9056d5fc14338ef38118dc4afae5fe2c585caffffffff309e1913634ecb50f3c4f83e96e70b2df071b497b8973a3e75429df397b5af83000000004948304502202bdb79c596a9ffc24e96f4386199aba386e9bc7b6071516e2b51dda942b3a1ed022100c53a857e76b724fc14d45311eac5019650d415c3abb5428f3aae16d8e69bec2301ffffffff2089e33491695080c9edc18a428f7d834db5b6d372df13ce2b1b0e0cbcb1e6c10000000049483045022100d4ce67c5896ee251c810ac1ff9ceccd328b497c8f553ab6e08431e7d40bad6b5022033119c0c2b7d792d31f1187779c7bd95aefd93d90a715586d73801d9b47471c601ffffffff0100714460030000001976a914c7b55141d097ea5df7a0ed330cf794376e53ec8d88ac0000000001000000045bf0e214aa4069a3e792ecee1e1bf0c1d397cde8dd08138f4b72a00681743447000000008b48304502200c45de8c4f3e2c1821f2fc878cba97b1e6f8807d94930713aa1c86a67b9bf1e40221008581abfef2e30f957815fc89978423746b2086375ca8ecf359c85c2a5b7c88ad01410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffffd669f7d7958d40fc59d2253d88e0f248e29b599c80bbcec344a83dda5f9aa72c000000008a473044022078124c8beeaa825f9e0b30bff96e564dd859432f2d0cb3b72d3d5d93d38d7e930220691d233b6c0f995be5acb03d70a7f7a65b6bc9bdd426260f38a1346669507a3601410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95fffffffff878af0d93f5229a68166cf051fd372bb7a537232946e0a46f53636b4dafdaa4000000008c493046022100c717d1714551663f69c3c5759bdbb3a0fcd3fab023abc0e522fe6440de35d8290221008d9cbe25bffc44af2b18e81c58eb37293fd7fe1c2e7b46fc37ee8c96c50ab1e201410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffff27f2b668859cd7f2f894aa0fd2d9e60963bcd07c88973f425f999b8cbfd7a1e2000000008c493046022100e00847147cbf517bcc2f502f3ddc6d284358d102ed20d47a8aa788a62f0db780022100d17b2d6fa84dcaf1c95d88d7e7c30385aecf415588d749afd3ec81f6022cecd701410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffff0100c817a8040000001976a914b6efd80d99179f4f4ff6f4dd0a007d018c385d2188ac000000000100000001834537b2f1ce8ef9373a258e10545ce5a50b758df616cd4356e0032554ebd3c4000000008b483045022100e68f422dd7c34fdce11eeb4509ddae38201773dd62f284e8aa9d96f85099d0b002202243bd399ff96b649a0fad05fa759d6a882f0af8c90cf7632c2840c29070aec20141045e58067e815c2f464c6a2a15f987758374203895710c2d452442e28496ff38ba8f5fd901dc20e29e88477167fe4fc299bf818fd0d9e1632d467b2a3d9503b1aaffffffff0280d7e636030000001976a914f34c3e10eb387efe872acb614c89e78bfca7815d88ac404b4c00000000001976a914a84e272933aaf87e1715d7786c51dfaeb5b65a6f88ac00000000010000000143ac81c8e6f6ef307dfe17f3d906d999e23e0189fda838c5510d850927e03ae7000000008c4930460221009c87c344760a64cb8ae6685a3eec2c1ac1bed5b88c87de51acd0e124f266c16602210082d07c037359c3a257b5c63ebd90f5a5edf97b2ac1c434b08ca998839f346dd40141040ba7e521fa7946d12edbb1d1e95a15c34bd4398195e86433c92b431cd315f455fe30032ede69cad9d1e1ed6c3c4ec0dbfced53438c625462afb792dcb098544bffffffff0240420f00000000001976a9144676d1b820d63ec272f1900d59d43bc6463d96f888ac40420f00000000001976a914648d04341d00d7968b3405c034adc38d4d8fb9bd88ac00000000010000000248cc917501ea5c55f4a8d2009c0567c40cfe037c2e71af017d0a452ff705e3f1000000008b483045022100bf5fdc86dc5f08a5d5c8e43a8c9d5b1ed8c65562e280007b52b133021acd9acc02205e325d613e555f772802bf413d36ba807892ed1a690a77811d3033b3de226e0a01410429fa713b124484cb2bd7b5557b2c0b9df7b2b1fee61825eadc5ae6c37a9920d38bfccdc7dc3cb0c47d7b173dbc9db8d37db0a33ae487982c59c6f8606e9d1791ffffffff41ed70551dd7e841883ab8f0b16bf04176b7d1480e4f0af9f3d4c3595768d068000000008b4830450221008513ad65187b903aed1102d1d0c47688127658c51106753fed0151ce9c16b80902201432b9ebcb87bd04ceb2de66035fbbaf4bf8b00d1cfe41f1a1f7338f9ad79d210141049d4cf80125bf50be1709f718c07ad15d0fc612b7da1f5570dddc35f2a352f0f27c978b06820edca9ef982c35fda2d255afba340068c5035552368bc7200c1488ffffffff0100093d00000000001976a9148edb68822f1ad580b043c7b3df2e400f8699eb4888ac00000000"), SER_NETWORK, PROTOCOL_VERSION);
+ stream >> block;
+
+ CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ // Match the last transaction
+ filter.insert(uint256("0x0a2a92f0bda4727d0a13eaddf4dd9ac6b5c61a1429e6b2b818f19b15df0ac154"));
+
+ CMerkleBlock merkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 1);
+ pair<unsigned int, uint256> pair = merkleBlock.vMatchedTxn[0];
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256("0x0a2a92f0bda4727d0a13eaddf4dd9ac6b5c61a1429e6b2b818f19b15df0ac154"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 6);
+
+ vector<uint256> vMatched;
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot);
+ BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
+ for (unsigned int i = 0; i < vMatched.size(); i++)
+ BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
+
+ // Also match the 4th transaction
+ filter.insert(uint256("0x02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041"));
+ merkleBlock = CMerkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 2);
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256("0x02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 3);
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[1] == pair);
+
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot);
+ BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
+ for (unsigned int i = 0; i < vMatched.size(); i++)
+ BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
+}
+
+BOOST_AUTO_TEST_CASE(merkle_block_4_test_p2pubkey_only)
+{
+ // Random real block (000000000000b731f2eef9e8c63173adfb07e41bd53eb0ef0a6b720d6cb6dea4)
+ // With 7 txes
+ CBlock block;
+ CDataStream stream(ParseHex("0100000082bb869cf3a793432a66e826e05a6fc37469f8efb7421dc880670100000000007f16c5962e8bd963659c793ce370d95f093bc7e367117b3c30c1f8fdd0d9728776381b4d4c86041b554b85290701000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07044c86041b0136ffffffff0100f2052a01000000434104eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a2252247d97a46a91ac000000000100000001bcad20a6a29827d1424f08989255120bf7f3e9e3cdaaa6bb31b0737fe048724300000000494830450220356e834b046cadc0f8ebb5a8a017b02de59c86305403dad52cd77b55af062ea10221009253cd6c119d4729b77c978e1e2aa19f5ea6e0e52b3f16e32fa608cd5bab753901ffffffff02008d380c010000001976a9142b4b8072ecbba129b6453c63e129e643207249ca88ac0065cd1d000000001976a9141b8dd13b994bcfc787b32aeadf58ccb3615cbd5488ac000000000100000003fdacf9b3eb077412e7a968d2e4f11b9a9dee312d666187ed77ee7d26af16cb0b000000008c493046022100ea1608e70911ca0de5af51ba57ad23b9a51db8d28f82c53563c56a05c20f5a87022100a8bdc8b4a8acc8634c6b420410150775eb7f2474f5615f7fccd65af30f310fbf01410465fdf49e29b06b9a1582287b6279014f834edc317695d125ef623c1cc3aaece245bd69fcad7508666e9c74a49dc9056d5fc14338ef38118dc4afae5fe2c585caffffffff309e1913634ecb50f3c4f83e96e70b2df071b497b8973a3e75429df397b5af83000000004948304502202bdb79c596a9ffc24e96f4386199aba386e9bc7b6071516e2b51dda942b3a1ed022100c53a857e76b724fc14d45311eac5019650d415c3abb5428f3aae16d8e69bec2301ffffffff2089e33491695080c9edc18a428f7d834db5b6d372df13ce2b1b0e0cbcb1e6c10000000049483045022100d4ce67c5896ee251c810ac1ff9ceccd328b497c8f553ab6e08431e7d40bad6b5022033119c0c2b7d792d31f1187779c7bd95aefd93d90a715586d73801d9b47471c601ffffffff0100714460030000001976a914c7b55141d097ea5df7a0ed330cf794376e53ec8d88ac0000000001000000045bf0e214aa4069a3e792ecee1e1bf0c1d397cde8dd08138f4b72a00681743447000000008b48304502200c45de8c4f3e2c1821f2fc878cba97b1e6f8807d94930713aa1c86a67b9bf1e40221008581abfef2e30f957815fc89978423746b2086375ca8ecf359c85c2a5b7c88ad01410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffffd669f7d7958d40fc59d2253d88e0f248e29b599c80bbcec344a83dda5f9aa72c000000008a473044022078124c8beeaa825f9e0b30bff96e564dd859432f2d0cb3b72d3d5d93d38d7e930220691d233b6c0f995be5acb03d70a7f7a65b6bc9bdd426260f38a1346669507a3601410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95fffffffff878af0d93f5229a68166cf051fd372bb7a537232946e0a46f53636b4dafdaa4000000008c493046022100c717d1714551663f69c3c5759bdbb3a0fcd3fab023abc0e522fe6440de35d8290221008d9cbe25bffc44af2b18e81c58eb37293fd7fe1c2e7b46fc37ee8c96c50ab1e201410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffff27f2b668859cd7f2f894aa0fd2d9e60963bcd07c88973f425f999b8cbfd7a1e2000000008c493046022100e00847147cbf517bcc2f502f3ddc6d284358d102ed20d47a8aa788a62f0db780022100d17b2d6fa84dcaf1c95d88d7e7c30385aecf415588d749afd3ec81f6022cecd701410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffff0100c817a8040000001976a914b6efd80d99179f4f4ff6f4dd0a007d018c385d2188ac000000000100000001834537b2f1ce8ef9373a258e10545ce5a50b758df616cd4356e0032554ebd3c4000000008b483045022100e68f422dd7c34fdce11eeb4509ddae38201773dd62f284e8aa9d96f85099d0b002202243bd399ff96b649a0fad05fa759d6a882f0af8c90cf7632c2840c29070aec20141045e58067e815c2f464c6a2a15f987758374203895710c2d452442e28496ff38ba8f5fd901dc20e29e88477167fe4fc299bf818fd0d9e1632d467b2a3d9503b1aaffffffff0280d7e636030000001976a914f34c3e10eb387efe872acb614c89e78bfca7815d88ac404b4c00000000001976a914a84e272933aaf87e1715d7786c51dfaeb5b65a6f88ac00000000010000000143ac81c8e6f6ef307dfe17f3d906d999e23e0189fda838c5510d850927e03ae7000000008c4930460221009c87c344760a64cb8ae6685a3eec2c1ac1bed5b88c87de51acd0e124f266c16602210082d07c037359c3a257b5c63ebd90f5a5edf97b2ac1c434b08ca998839f346dd40141040ba7e521fa7946d12edbb1d1e95a15c34bd4398195e86433c92b431cd315f455fe30032ede69cad9d1e1ed6c3c4ec0dbfced53438c625462afb792dcb098544bffffffff0240420f00000000001976a9144676d1b820d63ec272f1900d59d43bc6463d96f888ac40420f00000000001976a914648d04341d00d7968b3405c034adc38d4d8fb9bd88ac00000000010000000248cc917501ea5c55f4a8d2009c0567c40cfe037c2e71af017d0a452ff705e3f1000000008b483045022100bf5fdc86dc5f08a5d5c8e43a8c9d5b1ed8c65562e280007b52b133021acd9acc02205e325d613e555f772802bf413d36ba807892ed1a690a77811d3033b3de226e0a01410429fa713b124484cb2bd7b5557b2c0b9df7b2b1fee61825eadc5ae6c37a9920d38bfccdc7dc3cb0c47d7b173dbc9db8d37db0a33ae487982c59c6f8606e9d1791ffffffff41ed70551dd7e841883ab8f0b16bf04176b7d1480e4f0af9f3d4c3595768d068000000008b4830450221008513ad65187b903aed1102d1d0c47688127658c51106753fed0151ce9c16b80902201432b9ebcb87bd04ceb2de66035fbbaf4bf8b00d1cfe41f1a1f7338f9ad79d210141049d4cf80125bf50be1709f718c07ad15d0fc612b7da1f5570dddc35f2a352f0f27c978b06820edca9ef982c35fda2d255afba340068c5035552368bc7200c1488ffffffff0100093d00000000001976a9148edb68822f1ad580b043c7b3df2e400f8699eb4888ac00000000"), SER_NETWORK, PROTOCOL_VERSION);
+ stream >> block;
+
+ CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_P2PUBKEY_ONLY);
+ // Match the generation pubkey
+ filter.insert(ParseHex("04eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a2252247d97a46a91"));
+ // ...and the output address of the 4th transaction
+ filter.insert(ParseHex("b6efd80d99179f4f4ff6f4dd0a007d018c385d21"));
+
+ CMerkleBlock merkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ // We should match the generation outpoint
+ BOOST_CHECK(filter.contains(COutPoint(uint256("0x147caa76786596590baa4e98f5d9f48b86c7765e489f7a6ff3360fe5c674360b"), 0)));
+ // ... but not the 4th transaction's output (its not pay-2-pubkey)
+ BOOST_CHECK(!filter.contains(COutPoint(uint256("0x02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041"), 0)));
+}
+
+BOOST_AUTO_TEST_CASE(merkle_block_4_test_update_none)
+{
+ // Random real block (000000000000b731f2eef9e8c63173adfb07e41bd53eb0ef0a6b720d6cb6dea4)
+ // With 7 txes
+ CBlock block;
+ CDataStream stream(ParseHex("0100000082bb869cf3a793432a66e826e05a6fc37469f8efb7421dc880670100000000007f16c5962e8bd963659c793ce370d95f093bc7e367117b3c30c1f8fdd0d9728776381b4d4c86041b554b85290701000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07044c86041b0136ffffffff0100f2052a01000000434104eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a2252247d97a46a91ac000000000100000001bcad20a6a29827d1424f08989255120bf7f3e9e3cdaaa6bb31b0737fe048724300000000494830450220356e834b046cadc0f8ebb5a8a017b02de59c86305403dad52cd77b55af062ea10221009253cd6c119d4729b77c978e1e2aa19f5ea6e0e52b3f16e32fa608cd5bab753901ffffffff02008d380c010000001976a9142b4b8072ecbba129b6453c63e129e643207249ca88ac0065cd1d000000001976a9141b8dd13b994bcfc787b32aeadf58ccb3615cbd5488ac000000000100000003fdacf9b3eb077412e7a968d2e4f11b9a9dee312d666187ed77ee7d26af16cb0b000000008c493046022100ea1608e70911ca0de5af51ba57ad23b9a51db8d28f82c53563c56a05c20f5a87022100a8bdc8b4a8acc8634c6b420410150775eb7f2474f5615f7fccd65af30f310fbf01410465fdf49e29b06b9a1582287b6279014f834edc317695d125ef623c1cc3aaece245bd69fcad7508666e9c74a49dc9056d5fc14338ef38118dc4afae5fe2c585caffffffff309e1913634ecb50f3c4f83e96e70b2df071b497b8973a3e75429df397b5af83000000004948304502202bdb79c596a9ffc24e96f4386199aba386e9bc7b6071516e2b51dda942b3a1ed022100c53a857e76b724fc14d45311eac5019650d415c3abb5428f3aae16d8e69bec2301ffffffff2089e33491695080c9edc18a428f7d834db5b6d372df13ce2b1b0e0cbcb1e6c10000000049483045022100d4ce67c5896ee251c810ac1ff9ceccd328b497c8f553ab6e08431e7d40bad6b5022033119c0c2b7d792d31f1187779c7bd95aefd93d90a715586d73801d9b47471c601ffffffff0100714460030000001976a914c7b55141d097ea5df7a0ed330cf794376e53ec8d88ac0000000001000000045bf0e214aa4069a3e792ecee1e1bf0c1d397cde8dd08138f4b72a00681743447000000008b48304502200c45de8c4f3e2c1821f2fc878cba97b1e6f8807d94930713aa1c86a67b9bf1e40221008581abfef2e30f957815fc89978423746b2086375ca8ecf359c85c2a5b7c88ad01410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffffd669f7d7958d40fc59d2253d88e0f248e29b599c80bbcec344a83dda5f9aa72c000000008a473044022078124c8beeaa825f9e0b30bff96e564dd859432f2d0cb3b72d3d5d93d38d7e930220691d233b6c0f995be5acb03d70a7f7a65b6bc9bdd426260f38a1346669507a3601410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95fffffffff878af0d93f5229a68166cf051fd372bb7a537232946e0a46f53636b4dafdaa4000000008c493046022100c717d1714551663f69c3c5759bdbb3a0fcd3fab023abc0e522fe6440de35d8290221008d9cbe25bffc44af2b18e81c58eb37293fd7fe1c2e7b46fc37ee8c96c50ab1e201410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffff27f2b668859cd7f2f894aa0fd2d9e60963bcd07c88973f425f999b8cbfd7a1e2000000008c493046022100e00847147cbf517bcc2f502f3ddc6d284358d102ed20d47a8aa788a62f0db780022100d17b2d6fa84dcaf1c95d88d7e7c30385aecf415588d749afd3ec81f6022cecd701410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffff0100c817a8040000001976a914b6efd80d99179f4f4ff6f4dd0a007d018c385d2188ac000000000100000001834537b2f1ce8ef9373a258e10545ce5a50b758df616cd4356e0032554ebd3c4000000008b483045022100e68f422dd7c34fdce11eeb4509ddae38201773dd62f284e8aa9d96f85099d0b002202243bd399ff96b649a0fad05fa759d6a882f0af8c90cf7632c2840c29070aec20141045e58067e815c2f464c6a2a15f987758374203895710c2d452442e28496ff38ba8f5fd901dc20e29e88477167fe4fc299bf818fd0d9e1632d467b2a3d9503b1aaffffffff0280d7e636030000001976a914f34c3e10eb387efe872acb614c89e78bfca7815d88ac404b4c00000000001976a914a84e272933aaf87e1715d7786c51dfaeb5b65a6f88ac00000000010000000143ac81c8e6f6ef307dfe17f3d906d999e23e0189fda838c5510d850927e03ae7000000008c4930460221009c87c344760a64cb8ae6685a3eec2c1ac1bed5b88c87de51acd0e124f266c16602210082d07c037359c3a257b5c63ebd90f5a5edf97b2ac1c434b08ca998839f346dd40141040ba7e521fa7946d12edbb1d1e95a15c34bd4398195e86433c92b431cd315f455fe30032ede69cad9d1e1ed6c3c4ec0dbfced53438c625462afb792dcb098544bffffffff0240420f00000000001976a9144676d1b820d63ec272f1900d59d43bc6463d96f888ac40420f00000000001976a914648d04341d00d7968b3405c034adc38d4d8fb9bd88ac00000000010000000248cc917501ea5c55f4a8d2009c0567c40cfe037c2e71af017d0a452ff705e3f1000000008b483045022100bf5fdc86dc5f08a5d5c8e43a8c9d5b1ed8c65562e280007b52b133021acd9acc02205e325d613e555f772802bf413d36ba807892ed1a690a77811d3033b3de226e0a01410429fa713b124484cb2bd7b5557b2c0b9df7b2b1fee61825eadc5ae6c37a9920d38bfccdc7dc3cb0c47d7b173dbc9db8d37db0a33ae487982c59c6f8606e9d1791ffffffff41ed70551dd7e841883ab8f0b16bf04176b7d1480e4f0af9f3d4c3595768d068000000008b4830450221008513ad65187b903aed1102d1d0c47688127658c51106753fed0151ce9c16b80902201432b9ebcb87bd04ceb2de66035fbbaf4bf8b00d1cfe41f1a1f7338f9ad79d210141049d4cf80125bf50be1709f718c07ad15d0fc612b7da1f5570dddc35f2a352f0f27c978b06820edca9ef982c35fda2d255afba340068c5035552368bc7200c1488ffffffff0100093d00000000001976a9148edb68822f1ad580b043c7b3df2e400f8699eb4888ac00000000"), SER_NETWORK, PROTOCOL_VERSION);
+ stream >> block;
+
+ CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_NONE);
+ // Match the generation pubkey
+ filter.insert(ParseHex("04eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a2252247d97a46a91"));
+ // ...and the output address of the 4th transaction
+ filter.insert(ParseHex("b6efd80d99179f4f4ff6f4dd0a007d018c385d21"));
+
+ CMerkleBlock merkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ // We shouldn't match any outpoints (UPDATE_NONE)
+ BOOST_CHECK(!filter.contains(COutPoint(uint256("0x147caa76786596590baa4e98f5d9f48b86c7765e489f7a6ff3360fe5c674360b"), 0)));
+ BOOST_CHECK(!filter.contains(COutPoint(uint256("0x02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041"), 0)));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/canonical_tests.cpp b/src/test/canonical_tests.cpp
new file mode 100644
index 000000000..42d21f8ac
--- /dev/null
+++ b/src/test/canonical_tests.cpp
@@ -0,0 +1,87 @@
+//
+// Unit tests for canonical signatures
+
+#include "json/json_spirit_writer_template.h"
+#include <boost/test/unit_test.hpp>
+#include <openssl/ecdsa.h>
+
+#include "key.h"
+#include "script.h"
+#include "util.h"
+
+using namespace std;
+using namespace json_spirit;
+
+
+// In script_tests.cpp
+extern Array read_json(const std::string& filename);
+
+BOOST_AUTO_TEST_SUITE(canonical_tests)
+
+// OpenSSL-based test for canonical signature (without test for hashtype byte)
+bool static IsCanonicalSignature_OpenSSL_inner(const std::vector<unsigned char>& vchSig)
+{
+ if (vchSig.size() == 0)
+ return false;
+ const unsigned char *input = &vchSig[0];
+ ECDSA_SIG *psig = NULL;
+ d2i_ECDSA_SIG(&psig, &input, vchSig.size());
+ if (psig == NULL)
+ return false;
+ unsigned char buf[256];
+ unsigned char *pbuf = buf;
+ unsigned int nLen = i2d_ECDSA_SIG(psig, NULL);
+ if (nLen != vchSig.size()) {
+ ECDSA_SIG_free(psig);
+ return false;
+ }
+ nLen = i2d_ECDSA_SIG(psig, &pbuf);
+ ECDSA_SIG_free(psig);
+ return (memcmp(&vchSig[0], &buf[0], nLen) == 0);
+}
+
+// OpenSSL-based test for canonical signature
+bool static IsCanonicalSignature_OpenSSL(const std::vector<unsigned char> &vchSignature) {
+ if (vchSignature.size() < 1)
+ return false;
+ if (vchSignature.size() > 127)
+ return false;
+ if (vchSignature[vchSignature.size() - 1] & 0x7C)
+ return false;
+
+ std::vector<unsigned char> vchSig(vchSignature);
+ vchSig.pop_back();
+ if (!IsCanonicalSignature_OpenSSL_inner(vchSig))
+ return false;
+ return true;
+}
+
+BOOST_AUTO_TEST_CASE(script_canon)
+{
+ Array tests = read_json("sig_canonical.json");
+
+ BOOST_FOREACH(Value &tv, tests) {
+ string test = tv.get_str();
+ if (IsHex(test)) {
+ std::vector<unsigned char> sig = ParseHex(test);
+ BOOST_CHECK_MESSAGE(IsCanonicalSignature(sig), test);
+ BOOST_CHECK_MESSAGE(IsCanonicalSignature_OpenSSL(sig), test);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(script_noncanon)
+{
+ Array tests = read_json("sig_noncanonical.json");
+
+ BOOST_FOREACH(Value &tv, tests) {
+ string test = tv.get_str();
+ if (IsHex(test)) {
+ std::vector<unsigned char> sig = ParseHex(test);
+ BOOST_CHECK_MESSAGE(!IsCanonicalSignature(sig), test);
+ BOOST_CHECK_MESSAGE(!IsCanonicalSignature_OpenSSL(sig), test);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/compress_tests.cpp b/src/test/compress_tests.cpp
new file mode 100644
index 000000000..71b86bcb4
--- /dev/null
+++ b/src/test/compress_tests.cpp
@@ -0,0 +1,62 @@
+#include <boost/test/unit_test.hpp>
+
+#include <string>
+#include <vector>
+
+#include "main.h"
+
+// amounts 0.00000001 .. 0.00100000
+#define NUM_MULTIPLES_UNIT 100000
+
+// amounts 0.01 .. 100.00
+#define NUM_MULTIPLES_CENT 10000
+
+// amounts 1 .. 10000
+#define NUM_MULTIPLES_1BTC 10000
+
+// amounts 50 .. 21000000
+#define NUM_MULTIPLES_50BTC 420000
+
+using namespace std;
+
+BOOST_AUTO_TEST_SUITE(compress_tests)
+
+bool static TestEncode(uint64 in) {
+ return in == CTxOutCompressor::DecompressAmount(CTxOutCompressor::CompressAmount(in));
+}
+
+bool static TestDecode(uint64 in) {
+ return in == CTxOutCompressor::CompressAmount(CTxOutCompressor::DecompressAmount(in));
+}
+
+bool static TestPair(uint64 dec, uint64 enc) {
+ return CTxOutCompressor::CompressAmount(dec) == enc &&
+ CTxOutCompressor::DecompressAmount(enc) == dec;
+}
+
+BOOST_AUTO_TEST_CASE(compress_amounts)
+{
+ BOOST_CHECK(TestPair( 0, 0x0));
+ BOOST_CHECK(TestPair( 1, 0x1));
+ BOOST_CHECK(TestPair( CENT, 0x7));
+ BOOST_CHECK(TestPair( COIN, 0x9));
+ BOOST_CHECK(TestPair( 50*COIN, 0x32));
+ BOOST_CHECK(TestPair(21000000*COIN, 0x1406f40));
+
+ for (uint64 i = 1; i <= NUM_MULTIPLES_UNIT; i++)
+ BOOST_CHECK(TestEncode(i));
+
+ for (uint64 i = 1; i <= NUM_MULTIPLES_CENT; i++)
+ BOOST_CHECK(TestEncode(i * CENT));
+
+ for (uint64 i = 1; i <= NUM_MULTIPLES_1BTC; i++)
+ BOOST_CHECK(TestEncode(i * COIN));
+
+ for (uint64 i = 1; i <= NUM_MULTIPLES_50BTC; i++)
+ BOOST_CHECK(TestEncode(i * 50 * COIN));
+
+ for (uint64 i = 0; i < 100000; i++)
+ BOOST_CHECK(TestDecode(i));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/data/base58_encode_decode.json b/src/test/data/base58_encode_decode.json
new file mode 100644
index 000000000..9448f256d
--- /dev/null
+++ b/src/test/data/base58_encode_decode.json
@@ -0,0 +1,14 @@
+[
+["", ""],
+["61", "2g"],
+["626262", "a3gV"],
+["636363", "aPEr"],
+["73696d706c792061206c6f6e6720737472696e67", "2cFupjhnEsSn59qHXstmK2ffpLv2"],
+["00eb15231dfceb60925886b67d065299925915aeb172c06647", "1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L"],
+["516b6fcd0f", "ABnLTmg"],
+["bf4f89001e670274dd", "3SEo3LWLoPntC"],
+["572e4794", "3EFU7m"],
+["ecac89cad93923c02321", "EJDM8drfXA6uyA"],
+["10c8511e", "Rt5zm"],
+["00000000000000000000", "1111111111"]
+]
diff --git a/src/test/data/base58_keys_invalid.json b/src/test/data/base58_keys_invalid.json
new file mode 100644
index 000000000..a088620f1
--- /dev/null
+++ b/src/test/data/base58_keys_invalid.json
@@ -0,0 +1,152 @@
+[
+ [
+ ""
+ ],
+ [
+ "x"
+ ],
+ [
+ "37qgekLpCCHrQuSjvX3fs496FWTGsHFHizjJAs6NPcR47aefnnCWECAhHV6E3g4YN7u7Yuwod5Y"
+ ],
+ [
+ "dzb7VV1Ui55BARxv7ATxAtCUeJsANKovDGWFVgpTbhq9gvPqP3yv"
+ ],
+ [
+ "MuNu7ZAEDFiHthiunm7dPjwKqrVNCM3mAz6rP9zFveQu14YA8CxExSJTHcVP9DErn6u84E6Ej7S"
+ ],
+ [
+ "rPpQpYknyNQ5AEHuY6H8ijJJrYc2nDKKk9jjmKEXsWzyAQcFGpDLU2Zvsmoi8JLR7hAwoy3RQWf"
+ ],
+ [
+ "4Uc3FmN6NQ6zLBK5QQBXRBUREaaHwCZYsGCueHauuDmJpZKn6jkEskMB2Zi2CNgtb5r6epWEFfUJq"
+ ],
+ [
+ "7aQgR5DFQ25vyXmqZAWmnVCjL3PkBcdVkBUpjrjMTcghHx3E8wb"
+ ],
+ [
+ "17QpPprjeg69fW1DV8DcYYCKvWjYhXvWkov6MJ1iTTvMFj6weAqW7wybZeH57WTNxXVCRH4veVs"
+ ],
+ [
+ "KxuACDviz8Xvpn1xAh9MfopySZNuyajYMZWz16Dv2mHHryznWUp3"
+ ],
+ [
+ "7nK3GSmqdXJQtdohvGfJ7KsSmn3TmGqExug49583bDAL91pVSGq5xS9SHoAYL3Wv3ijKTit65th"
+ ],
+ [
+ "cTivdBmq7bay3RFGEBBuNfMh2P1pDCgRYN2Wbxmgwr4ki3jNUL2va"
+ ],
+ [
+ "gjMV4vjNjyMrna4fsAr8bWxAbwtmMUBXJS3zL4NJt5qjozpbQLmAfK1uA3CquSqsZQMpoD1g2nk"
+ ],
+ [
+ "emXm1naBMoVzPjbk7xpeTVMFy4oDEe25UmoyGgKEB1gGWsK8kRGs"
+ ],
+ [
+ "7VThQnNRj1o3Zyvc7XHPRrjDf8j2oivPTeDXnRPYWeYGE4pXeRJDZgf28ppti5hsHWXS2GSobdqyo"
+ ],
+ [
+ "1G9u6oCVCPh2o8m3t55ACiYvG1y5BHewUkDSdiQarDcYXXhFHYdzMdYfUAhfxn5vNZBwpgUNpso"
+ ],
+ [
+ "31QQ7ZMLkScDiB4VyZjuptr7AEc9j1SjstF7pRoLhHTGkW4Q2y9XELobQmhhWxeRvqcukGd1XCq"
+ ],
+ [
+ "DHqKSnpxa8ZdQyH8keAhvLTrfkyBMQxqngcQA5N8LQ9KVt25kmGN"
+ ],
+ [
+ "2LUHcJPbwLCy9GLH1qXmfmAwvadWw4bp4PCpDfduLqV17s6iDcy1imUwhQJhAoNoN1XNmweiJP4i"
+ ],
+ [
+ "7USRzBXAnmck8fX9HmW7RAb4qt92VFX6soCnts9s74wxm4gguVhtG5of8fZGbNPJA83irHVY6bCos"
+ ],
+ [
+ "1DGezo7BfVebZxAbNT3XGujdeHyNNBF3vnficYoTSp4PfK2QaML9bHzAMxke3wdKdHYWmsMTJVu"
+ ],
+ [
+ "2D12DqDZKwCxxkzs1ZATJWvgJGhQ4cFi3WrizQ5zLAyhN5HxuAJ1yMYaJp8GuYsTLLxTAz6otCfb"
+ ],
+ [
+ "8AFJzuTujXjw1Z6M3fWhQ1ujDW7zsV4ePeVjVo7D1egERqSW9nZ"
+ ],
+ [
+ "163Q17qLbTCue8YY3AvjpUhotuaodLm2uqMhpYirsKjVqnxJRWTEoywMVY3NbBAHuhAJ2cF9GAZ"
+ ],
+ [
+ "2MnmgiRH4eGLyLc9eAqStzk7dFgBjFtUCtu"
+ ],
+ [
+ "461QQ2sYWxU7H2PV4oBwJGNch8XVTYYbZxU"
+ ],
+ [
+ "2UCtv53VttmQYkVU4VMtXB31REvQg4ABzs41AEKZ8UcB7DAfVzdkV9JDErwGwyj5AUHLkmgZeobs"
+ ],
+ [
+ "cSNjAsnhgtiFMi6MtfvgscMB2Cbhn2v1FUYfviJ1CdjfidvmeW6mn"
+ ],
+ [
+ "gmsow2Y6EWAFDFE1CE4Hd3Tpu2BvfmBfG1SXsuRARbnt1WjkZnFh1qGTiptWWbjsq2Q6qvpgJVj"
+ ],
+ [
+ "nksUKSkzS76v8EsSgozXGMoQFiCoCHzCVajFKAXqzK5on9ZJYVHMD5CKwgmX3S3c7M1U3xabUny"
+ ],
+ [
+ "L3favK1UzFGgdzYBF2oBT5tbayCo4vtVBLJhg2iYuMeePxWG8SQc"
+ ],
+ [
+ "7VxLxGGtYT6N99GdEfi6xz56xdQ8nP2dG1CavuXx7Rf2PrvNMTBNevjkfgs9JmkcGm6EXpj8ipyPZ"
+ ],
+ [
+ "2mbZwFXF6cxShaCo2czTRB62WTx9LxhTtpP"
+ ],
+ [
+ "dB7cwYdcPSgiyAwKWL3JwCVwSk6epU2txw"
+ ],
+ [
+ "HPhFUhUAh8ZQQisH8QQWafAxtQYju3SFTX"
+ ],
+ [
+ "4ctAH6AkHzq5ioiM1m9T3E2hiYEev5mTsB"
+ ],
+ [
+ "Hn1uFi4dNexWrqARpjMqgT6cX1UsNPuV3cHdGg9ExyXw8HTKadbktRDtdeVmY3M1BxJStiL4vjJ"
+ ],
+ [
+ "Sq3fDbvutABmnAHHExJDgPLQn44KnNC7UsXuT7KZecpaYDMU9Txs"
+ ],
+ [
+ "6TqWyrqdgUEYDQU1aChMuFMMEimHX44qHFzCUgGfqxGgZNMUVWJ"
+ ],
+ [
+ "giqJo7oWqFxNKWyrgcBxAVHXnjJ1t6cGoEffce5Y1y7u649Noj5wJ4mmiUAKEVVrYAGg2KPB3Y4"
+ ],
+ [
+ "cNzHY5e8vcmM3QVJUcjCyiKMYfeYvyueq5qCMV3kqcySoLyGLYUK"
+ ],
+ [
+ "37uTe568EYc9WLoHEd9jXEvUiWbq5LFLscNyqvAzLU5vBArUJA6eydkLmnMwJDjkL5kXc2VK7ig"
+ ],
+ [
+ "EsYbG4tWWWY45G31nox838qNdzksbPySWc"
+ ],
+ [
+ "nbuzhfwMoNzA3PaFnyLcRxE9bTJPDkjZ6Rf6Y6o2ckXZfzZzXBT"
+ ],
+ [
+ "cQN9PoxZeCWK1x56xnz6QYAsvR11XAce3Ehp3gMUdfSQ53Y2mPzx"
+ ],
+ [
+ "1Gm3N3rkef6iMbx4voBzaxtXcmmiMTqZPhcuAepRzYUJQW4qRpEnHvMojzof42hjFRf8PE2jPde"
+ ],
+ [
+ "2TAq2tuN6x6m233bpT7yqdYQPELdTDJn1eU"
+ ],
+ [
+ "ntEtnnGhqPii4joABvBtSEJG6BxjT2tUZqE8PcVYgk3RHpgxgHDCQxNbLJf7ardf1dDk2oCQ7Cf"
+ ],
+ [
+ "Ky1YjoZNgQ196HJV3HpdkecfhRBmRZdMJk89Hi5KGfpfPwS2bUbfd"
+ ],
+ [
+ "2A1q1YsMZowabbvta7kTy2Fd6qN4r5ZCeG3qLpvZBMzCixMUdkN2Y4dHB1wPsZAeVXUGD83MfRED"
+ ]
+]
diff --git a/src/test/data/base58_keys_valid.json b/src/test/data/base58_keys_valid.json
new file mode 100644
index 000000000..e1e252e22
--- /dev/null
+++ b/src/test/data/base58_keys_valid.json
@@ -0,0 +1,452 @@
+[
+ [
+ "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",
+ "65a16059864a2fdbc7c99a4723a8395bc6f188eb",
+ {
+ "addrType": "pubkey",
+ "isPrivkey": false,
+ "isTestnet": false
+ }
+ ],
+ [
+ "3CMNFxN1oHBc4R1EpboAL5yzHGgE611Xou",
+ "74f209f6ea907e2ea48f74fae05782ae8a665257",
+ {
+ "addrType": "script",
+ "isPrivkey": false,
+ "isTestnet": false
+ }
+ ],
+ [
+ "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs",
+ "53c0307d6851aa0ce7825ba883c6bd9ad242b486",
+ {
+ "addrType": "pubkey",
+ "isPrivkey": false,
+ "isTestnet": true
+ }
+ ],
+ [
+ "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br",
+ "6349a418fc4578d10a372b54b45c280cc8c4382f",
+ {
+ "addrType": "script",
+ "isPrivkey": false,
+ "isTestnet": true
+ }
+ ],
+ [
+ "5Kd3NBUAdUnhyzenEwVLy9pBKxSwXvE9FMPyR4UKZvpe6E3AgLr",
+ "eddbdc1168f1daeadbd3e44c1e3f8f5a284c2029f78ad26af98583a499de5b19",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "isTestnet": false
+ }
+ ],
+ [
+ "Kz6UJmQACJmLtaQj5A3JAge4kVTNQ8gbvXuwbmCj7bsaabudb3RD",
+ "55c9bccb9ed68446d1b75273bbce89d7fe013a8acd1625514420fb2aca1a21c4",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "isTestnet": false
+ }
+ ],
+ [
+ "9213qJab2HNEpMpYNBa7wHGFKKbkDn24jpANDs2huN3yi4J11ko",
+ "36cb93b9ab1bdabf7fb9f2c04f1b9cc879933530ae7842398eef5a63a56800c2",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "isTestnet": true
+ }
+ ],
+ [
+ "cTpB4YiyKiBcPxnefsDpbnDxFDffjqJob8wGCEDXxgQ7zQoMXJdH",
+ "b9f4892c9e8282028fea1d2667c4dc5213564d41fc5783896a0d843fc15089f3",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "isTestnet": true
+ }
+ ],
+ [
+ "1Ax4gZtb7gAit2TivwejZHYtNNLT18PUXJ",
+ "6d23156cbbdcc82a5a47eee4c2c7c583c18b6bf4",
+ {
+ "addrType": "pubkey",
+ "isPrivkey": false,
+ "isTestnet": false
+ }
+ ],
+ [
+ "3QjYXhTkvuj8qPaXHTTWb5wjXhdsLAAWVy",
+ "fcc5460dd6e2487c7d75b1963625da0e8f4c5975",
+ {
+ "addrType": "script",
+ "isPrivkey": false,
+ "isTestnet": false
+ }
+ ],
+ [
+ "n3ZddxzLvAY9o7184TB4c6FJasAybsw4HZ",
+ "f1d470f9b02370fdec2e6b708b08ac431bf7a5f7",
+ {
+ "addrType": "pubkey",
+ "isPrivkey": false,
+ "isTestnet": true
+ }
+ ],
+ [
+ "2NBFNJTktNa7GZusGbDbGKRZTxdK9VVez3n",
+ "c579342c2c4c9220205e2cdc285617040c924a0a",
+ {
+ "addrType": "script",
+ "isPrivkey": false,
+ "isTestnet": true
+ }
+ ],
+ [
+ "5K494XZwps2bGyeL71pWid4noiSNA2cfCibrvRWqcHSptoFn7rc",
+ "a326b95ebae30164217d7a7f57d72ab2b54e3be64928a19da0210b9568d4015e",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "isTestnet": false
+ }
+ ],
+ [
+ "L1RrrnXkcKut5DEMwtDthjwRcTTwED36thyL1DebVrKuwvohjMNi",
+ "7d998b45c219a1e38e99e7cbd312ef67f77a455a9b50c730c27f02c6f730dfb4",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "isTestnet": false
+ }
+ ],
+ [
+ "93DVKyFYwSN6wEo3E2fCrFPUp17FtrtNi2Lf7n4G3garFb16CRj",
+ "d6bca256b5abc5602ec2e1c121a08b0da2556587430bcf7e1898af2224885203",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "isTestnet": true
+ }
+ ],
+ [
+ "cTDVKtMGVYWTHCb1AFjmVbEbWjvKpKqKgMaR3QJxToMSQAhmCeTN",
+ "a81ca4e8f90181ec4b61b6a7eb998af17b2cb04de8a03b504b9e34c4c61db7d9",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "isTestnet": true
+ }
+ ],
+ [
+ "1C5bSj1iEGUgSTbziymG7Cn18ENQuT36vv",
+ "7987ccaa53d02c8873487ef919677cd3db7a6912",
+ {
+ "addrType": "pubkey",
+ "isPrivkey": false,
+ "isTestnet": false
+ }
+ ],
+ [
+ "3AnNxabYGoTxYiTEZwFEnerUoeFXK2Zoks",
+ "63bcc565f9e68ee0189dd5cc67f1b0e5f02f45cb",
+ {
+ "addrType": "script",
+ "isPrivkey": false,
+ "isTestnet": false
+ }
+ ],
+ [
+ "n3LnJXCqbPjghuVs8ph9CYsAe4Sh4j97wk",
+ "ef66444b5b17f14e8fae6e7e19b045a78c54fd79",
+ {
+ "addrType": "pubkey",
+ "isPrivkey": false,
+ "isTestnet": true
+ }
+ ],
+ [
+ "2NB72XtkjpnATMggui83aEtPawyyKvnbX2o",
+ "c3e55fceceaa4391ed2a9677f4a4d34eacd021a0",
+ {
+ "addrType": "script",
+ "isPrivkey": false,
+ "isTestnet": true
+ }
+ ],
+ [
+ "5KaBW9vNtWNhc3ZEDyNCiXLPdVPHCikRxSBWwV9NrpLLa4LsXi9",
+ "e75d936d56377f432f404aabb406601f892fd49da90eb6ac558a733c93b47252",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "isTestnet": false
+ }
+ ],
+ [
+ "L1axzbSyynNYA8mCAhzxkipKkfHtAXYF4YQnhSKcLV8YXA874fgT",
+ "8248bd0375f2f75d7e274ae544fb920f51784480866b102384190b1addfbaa5c",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "isTestnet": false
+ }
+ ],
+ [
+ "927CnUkUbasYtDwYwVn2j8GdTuACNnKkjZ1rpZd2yBB1CLcnXpo",
+ "44c4f6a096eac5238291a94cc24c01e3b19b8d8cef72874a079e00a242237a52",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "isTestnet": true
+ }
+ ],
+ [
+ "cUcfCMRjiQf85YMzzQEk9d1s5A4K7xL5SmBCLrezqXFuTVefyhY7",
+ "d1de707020a9059d6d3abaf85e17967c6555151143db13dbb06db78df0f15c69",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "isTestnet": true
+ }
+ ],
+ [
+ "1Gqk4Tv79P91Cc1STQtU3s1W6277M2CVWu",
+ "adc1cc2081a27206fae25792f28bbc55b831549d",
+ {
+ "addrType": "pubkey",
+ "isPrivkey": false,
+ "isTestnet": false
+ }
+ ],
+ [
+ "33vt8ViH5jsr115AGkW6cEmEz9MpvJSwDk",
+ "188f91a931947eddd7432d6e614387e32b244709",
+ {
+ "addrType": "script",
+ "isPrivkey": false,
+ "isTestnet": false
+ }
+ ],
+ [
+ "mhaMcBxNh5cqXm4aTQ6EcVbKtfL6LGyK2H",
+ "1694f5bc1a7295b600f40018a618a6ea48eeb498",
+ {
+ "addrType": "pubkey",
+ "isPrivkey": false,
+ "isTestnet": true
+ }
+ ],
+ [
+ "2MxgPqX1iThW3oZVk9KoFcE5M4JpiETssVN",
+ "3b9b3fd7a50d4f08d1a5b0f62f644fa7115ae2f3",
+ {
+ "addrType": "script",
+ "isPrivkey": false,
+ "isTestnet": true
+ }
+ ],
+ [
+ "5HtH6GdcwCJA4ggWEL1B3jzBBUB8HPiBi9SBc5h9i4Wk4PSeApR",
+ "091035445ef105fa1bb125eccfb1882f3fe69592265956ade751fd095033d8d0",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "isTestnet": false
+ }
+ ],
+ [
+ "L2xSYmMeVo3Zek3ZTsv9xUrXVAmrWxJ8Ua4cw8pkfbQhcEFhkXT8",
+ "ab2b4bcdfc91d34dee0ae2a8c6b6668dadaeb3a88b9859743156f462325187af",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "isTestnet": false
+ }
+ ],
+ [
+ "92xFEve1Z9N8Z641KQQS7ByCSb8kGjsDzw6fAmjHN1LZGKQXyMq",
+ "b4204389cef18bbe2b353623cbf93e8678fbc92a475b664ae98ed594e6cf0856",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "isTestnet": true
+ }
+ ],
+ [
+ "cVM65tdYu1YK37tNoAyGoJTR13VBYFva1vg9FLuPAsJijGvG6NEA",
+ "e7b230133f1b5489843260236b06edca25f66adb1be455fbd38d4010d48faeef",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "isTestnet": true
+ }
+ ],
+ [
+ "1JwMWBVLtiqtscbaRHai4pqHokhFCbtoB4",
+ "c4c1b72491ede1eedaca00618407ee0b772cad0d",
+ {
+ "addrType": "pubkey",
+ "isPrivkey": false,
+ "isTestnet": false
+ }
+ ],
+ [
+ "3QCzvfL4ZRvmJFiWWBVwxfdaNBT8EtxB5y",
+ "f6fe69bcb548a829cce4c57bf6fff8af3a5981f9",
+ {
+ "addrType": "script",
+ "isPrivkey": false,
+ "isTestnet": false
+ }
+ ],
+ [
+ "mizXiucXRCsEriQCHUkCqef9ph9qtPbZZ6",
+ "261f83568a098a8638844bd7aeca039d5f2352c0",
+ {
+ "addrType": "pubkey",
+ "isPrivkey": false,
+ "isTestnet": true
+ }
+ ],
+ [
+ "2NEWDzHWwY5ZZp8CQWbB7ouNMLqCia6YRda",
+ "e930e1834a4d234702773951d627cce82fbb5d2e",
+ {
+ "addrType": "script",
+ "isPrivkey": false,
+ "isTestnet": true
+ }
+ ],
+ [
+ "5KQmDryMNDcisTzRp3zEq9e4awRmJrEVU1j5vFRTKpRNYPqYrMg",
+ "d1fab7ab7385ad26872237f1eb9789aa25cc986bacc695e07ac571d6cdac8bc0",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "isTestnet": false
+ }
+ ],
+ [
+ "L39Fy7AC2Hhj95gh3Yb2AU5YHh1mQSAHgpNixvm27poizcJyLtUi",
+ "b0bbede33ef254e8376aceb1510253fc3550efd0fcf84dcd0c9998b288f166b3",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "isTestnet": false
+ }
+ ],
+ [
+ "91cTVUcgydqyZLgaANpf1fvL55FH53QMm4BsnCADVNYuWuqdVys",
+ "037f4192c630f399d9271e26c575269b1d15be553ea1a7217f0cb8513cef41cb",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "isTestnet": true
+ }
+ ],
+ [
+ "cQspfSzsgLeiJGB2u8vrAiWpCU4MxUT6JseWo2SjXy4Qbzn2fwDw",
+ "6251e205e8ad508bab5596bee086ef16cd4b239e0cc0c5d7c4e6035441e7d5de",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "isTestnet": true
+ }
+ ],
+ [
+ "19dcawoKcZdQz365WpXWMhX6QCUpR9SY4r",
+ "5eadaf9bb7121f0f192561a5a62f5e5f54210292",
+ {
+ "addrType": "pubkey",
+ "isPrivkey": false,
+ "isTestnet": false
+ }
+ ],
+ [
+ "37Sp6Rv3y4kVd1nQ1JV5pfqXccHNyZm1x3",
+ "3f210e7277c899c3a155cc1c90f4106cbddeec6e",
+ {
+ "addrType": "script",
+ "isPrivkey": false,
+ "isTestnet": false
+ }
+ ],
+ [
+ "myoqcgYiehufrsnnkqdqbp69dddVDMopJu",
+ "c8a3c2a09a298592c3e180f02487cd91ba3400b5",
+ {
+ "addrType": "pubkey",
+ "isPrivkey": false,
+ "isTestnet": true
+ }
+ ],
+ [
+ "2N7FuwuUuoTBrDFdrAZ9KxBmtqMLxce9i1C",
+ "99b31df7c9068d1481b596578ddbb4d3bd90baeb",
+ {
+ "addrType": "script",
+ "isPrivkey": false,
+ "isTestnet": true
+ }
+ ],
+ [
+ "5KL6zEaMtPRXZKo1bbMq7JDjjo1bJuQcsgL33je3oY8uSJCR5b4",
+ "c7666842503db6dc6ea061f092cfb9c388448629a6fe868d068c42a488b478ae",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "isTestnet": false
+ }
+ ],
+ [
+ "KwV9KAfwbwt51veZWNscRTeZs9CKpojyu1MsPnaKTF5kz69H1UN2",
+ "07f0803fc5399e773555ab1e8939907e9badacc17ca129e67a2f5f2ff84351dd",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "isTestnet": false
+ }
+ ],
+ [
+ "93N87D6uxSBzwXvpokpzg8FFmfQPmvX4xHoWQe3pLdYpbiwT5YV",
+ "ea577acfb5d1d14d3b7b195c321566f12f87d2b77ea3a53f68df7ebf8604a801",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "isTestnet": true
+ }
+ ],
+ [
+ "cMxXusSihaX58wpJ3tNuuUcZEQGt6DKJ1wEpxys88FFaQCYjku9h",
+ "0b3b34f0958d8a268193a9814da92c3e8b58b4a4378a542863e34ac289cd830c",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "isTestnet": true
+ }
+ ],
+ [
+ "13p1ijLwsnrcuyqcTvJXkq2ASdXqcnEBLE",
+ "1ed467017f043e91ed4c44b4e8dd674db211c4e6",
+ {
+ "addrType": "pubkey",
+ "isPrivkey": false,
+ "isTestnet": false
+ }
+ ],
+ [
+ "3ALJH9Y951VCGcVZYAdpA3KchoP9McEj1G",
+ "5ece0cadddc415b1980f001785947120acdb36fc",
+ {
+ "addrType": "script",
+ "isPrivkey": false,
+ "isTestnet": false
+ }
+ ]
+]
diff --git a/src/test/data/sig_canonical.json b/src/test/data/sig_canonical.json
new file mode 100644
index 000000000..e43a08629
--- /dev/null
+++ b/src/test/data/sig_canonical.json
@@ -0,0 +1,7 @@
+[
+ "300602010002010001",
+ "3008020200ff020200ff01",
+ "304402203932c892e2e550f3af8ee4ce9c215a87f9bb831dcac87b2838e2c2eaa891df0c022030b61dd36543125d56b9f9f3a1f9353189e5af33cdda8d77a5209aec03978fa001",
+ "30450220076045be6f9eca28ff1ec606b833d0b87e70b2a630f5e3a496b110967a40f90a0221008fffd599910eefe00bc803c688c2eca1d2ba7f6b180620eaa03488e6585db6ba01",
+ "3046022100876045be6f9eca28ff1ec606b833d0b87e70b2a630f5e3a496b110967a40f90a0221008fffd599910eefe00bc803c688c2eca1d2ba7f6b180620eaa03488e6585db6ba01"
+]
diff --git a/src/test/data/sig_noncanonical.json b/src/test/data/sig_noncanonical.json
new file mode 100644
index 000000000..d9a6c1cdd
--- /dev/null
+++ b/src/test/data/sig_noncanonical.json
@@ -0,0 +1,22 @@
+[
+ "non-hex strings are ignored",
+
+ "too short:", "30050201FF020001",
+ "too long:", "30470221005990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105022200002d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
+ "hashtype:", "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed11",
+ "type:", "314402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
+ "total length:", "304502205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
+ "S len oob:", "301F01205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb101",
+ "R+S:", "304502205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed0001",
+
+ "R type:", "304401205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
+ "R len = 0:", "3024020002202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
+ "R<0:", "304402208990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
+ "R padded:", "30450221005990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
+
+
+ "S type:", "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610501202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
+ "S len = 0:", "302402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105020001",
+ "S<0:", "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61050220fd5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
+ "S padded:", "304502205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61050221002d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01"
+]
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 4558a76a2..af284653d 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -49,19 +49,20 @@ struct {
BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
{
CReserveKey reservekey(pwalletMain);
- CBlock *pblock;
+ CBlockTemplate *pblocktemplate;
CTransaction tx;
CScript script;
uint256 hash;
// Simple block creation, nothing special yet:
- BOOST_CHECK(pblock = CreateNewBlock(reservekey));
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(reservekey));
// We can't make transactions until we have inputs
// Therefore, load 100 blocks :)
std::vector<CTransaction*>txFirst;
for (unsigned int i = 0; i < sizeof(blockinfo)/sizeof(*blockinfo); ++i)
{
+ CBlock *pblock = &pblocktemplate->block; // pointer for convenience
pblock->nVersion = 1;
pblock->nTime = pindexBest->GetMedianTimePast()+1;
pblock->vtx[0].vin[0].scriptSig = CScript();
@@ -72,13 +73,15 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
txFirst.push_back(new CTransaction(pblock->vtx[0]));
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
pblock->nNonce = blockinfo[i].nonce;
- assert(ProcessBlock(NULL, pblock));
+ CValidationState state;
+ BOOST_CHECK(ProcessBlock(state, NULL, pblock));
+ BOOST_CHECK(state.IsValid());
pblock->hashPrevBlock = pblock->GetHash();
}
- delete pblock;
+ delete pblocktemplate;
// Just to make sure we can still make simple blocks
- BOOST_CHECK(pblock = CreateNewBlock(reservekey));
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(reservekey));
// block sigops > limit: 1000 CHECKMULTISIG + 1
tx.vin.resize(1);
@@ -95,8 +98,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
mempool.addUnchecked(hash, tx);
tx.vin[0].prevout.hash = hash;
}
- BOOST_CHECK(pblock = CreateNewBlock(reservekey));
- delete pblock;
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(reservekey));
+ delete pblocktemplate;
mempool.clear();
// block size > limit
@@ -115,15 +118,15 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
mempool.addUnchecked(hash, tx);
tx.vin[0].prevout.hash = hash;
}
- BOOST_CHECK(pblock = CreateNewBlock(reservekey));
- delete pblock;
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(reservekey));
+ delete pblocktemplate;
mempool.clear();
// orphan in mempool
hash = tx.GetHash();
mempool.addUnchecked(hash, tx);
- BOOST_CHECK(pblock = CreateNewBlock(reservekey));
- delete pblock;
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(reservekey));
+ delete pblocktemplate;
mempool.clear();
// child with higher priority than parent
@@ -140,8 +143,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.vout[0].nValue = 5900000000LL;
hash = tx.GetHash();
mempool.addUnchecked(hash, tx);
- BOOST_CHECK(pblock = CreateNewBlock(reservekey));
- delete pblock;
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(reservekey));
+ delete pblocktemplate;
mempool.clear();
// coinbase in mempool
@@ -151,8 +154,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.vout[0].nValue = 0;
hash = tx.GetHash();
mempool.addUnchecked(hash, tx);
- BOOST_CHECK(pblock = CreateNewBlock(reservekey));
- delete pblock;
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(reservekey));
+ delete pblocktemplate;
mempool.clear();
// invalid (pre-p2sh) txn in mempool
@@ -169,8 +172,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.vout[0].nValue -= 1000000;
hash = tx.GetHash();
mempool.addUnchecked(hash,tx);
- BOOST_CHECK(pblock = CreateNewBlock(reservekey));
- delete pblock;
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(reservekey));
+ delete pblocktemplate;
mempool.clear();
// double spend txn pair in mempool
@@ -183,18 +186,18 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.vout[0].scriptPubKey = CScript() << OP_2;
hash = tx.GetHash();
mempool.addUnchecked(hash, tx);
- BOOST_CHECK(pblock = CreateNewBlock(reservekey));
- delete pblock;
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(reservekey));
+ delete pblocktemplate;
mempool.clear();
// subsidy changing
int nHeight = pindexBest->nHeight;
pindexBest->nHeight = 209999;
- BOOST_CHECK(pblock = CreateNewBlock(reservekey));
- delete pblock;
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(reservekey));
+ delete pblocktemplate;
pindexBest->nHeight = 210000;
- BOOST_CHECK(pblock = CreateNewBlock(reservekey));
- delete pblock;
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(reservekey));
+ delete pblocktemplate;
pindexBest->nHeight = nHeight;
}
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index 6bc5e3b99..7297bb9a7 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -20,8 +20,6 @@ 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,
- bool fValidatePayToScriptHash, int nHashType);
BOOST_AUTO_TEST_SUITE(multisig_tests)
@@ -44,6 +42,8 @@ sign_multisig(CScript scriptPubKey, vector<CKey> keys, CTransaction transaction,
BOOST_AUTO_TEST_CASE(multisig_verify)
{
+ unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
+
CKey key[4];
for (int i = 0; i < 4; i++)
key[i].MakeNewKey(true);
@@ -80,19 +80,19 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
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, true, 0));
+ BOOST_CHECK(VerifyScript(s, a_and_b, txTo[0], 0, flags, 0));
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, true, 0), strprintf("a&b 1: %d", i));
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, txTo[0], 0, flags, 0), 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, true, 0), strprintf("a&b 2: %d", i));
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, txTo[0], 0, flags, 0), strprintf("a&b 2: %d", i));
}
// Test a OR b:
@@ -102,16 +102,16 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
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, true, 0), strprintf("a|b: %d", i));
+ BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, txTo[1], 0, flags, 0), strprintf("a|b: %d", i));
else
- BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, txTo[1], 0, true, 0), strprintf("a|b: %d", i));
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, txTo[1], 0, flags, 0), strprintf("a|b: %d", i));
}
s.clear();
s << OP_0 << OP_0;
- BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, true, 0));
+ BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, flags, 0));
s.clear();
s << OP_0 << OP_1;
- BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, true, 0));
+ BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, flags, 0));
for (int i = 0; i < 4; i++)
@@ -121,9 +121,9 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
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, true, 0), strprintf("escrow 1: %d %d", i, j));
+ BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, txTo[2], 0, flags, 0), strprintf("escrow 1: %d %d", i, j));
else
- BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, txTo[2], 0, true, 0), strprintf("escrow 2: %d %d", i, j));
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, txTo[2], 0, flags, 0), strprintf("escrow 2: %d %d", i, j));
}
}
diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp
new file mode 100644
index 000000000..cf0942161
--- /dev/null
+++ b/src/test/pmt_tests.cpp
@@ -0,0 +1,98 @@
+#include <boost/test/unit_test.hpp>
+
+#include "uint256.h"
+#include "main.h"
+
+using namespace std;
+
+class CPartialMerkleTreeTester : public CPartialMerkleTree
+{
+public:
+ // flip one bit in one of the hashes - this should break the authentication
+ void Damage() {
+ unsigned int n = rand() % vHash.size();
+ int bit = rand() % 256;
+ uint256 &hash = vHash[n];
+ hash ^= ((uint256)1 << bit);
+ }
+};
+
+BOOST_AUTO_TEST_SUITE(pmt_tests)
+
+BOOST_AUTO_TEST_CASE(pmt_test1)
+{
+ static const unsigned int nTxCounts[] = {1, 4, 7, 17, 56, 100, 127, 256, 312, 513, 1000, 4095};
+
+ for (int n = 0; n < 12; n++) {
+ unsigned int nTx = nTxCounts[n];
+
+ // build a block with some dummy transactions
+ CBlock block;
+ for (unsigned int j=0; j<nTx; j++) {
+ CTransaction tx;
+ tx.nLockTime = rand(); // actual transaction data doesn't matter; just make the nLockTime's unique
+ block.vtx.push_back(tx);
+ }
+
+ // calculate actual merkle root and height
+ uint256 merkleRoot1 = block.BuildMerkleTree();
+ std::vector<uint256> vTxid(nTx, 0);
+ for (unsigned int j=0; j<nTx; j++)
+ vTxid[j] = block.vtx[j].GetHash();
+ int nHeight = 1, nTx_ = nTx;
+ while (nTx_ > 1) {
+ nTx_ = (nTx_+1)/2;
+ nHeight++;
+ }
+
+ // check with random subsets with inclusion chances 1, 1/2, 1/4, ..., 1/128
+ for (int att = 1; att < 15; att++) {
+ // build random subset of txid's
+ std::vector<bool> vMatch(nTx, false);
+ std::vector<uint256> vMatchTxid1;
+ for (unsigned int j=0; j<nTx; j++) {
+ bool fInclude = (rand() & ((1 << (att/2)) - 1)) == 0;
+ vMatch[j] = fInclude;
+ if (fInclude)
+ vMatchTxid1.push_back(vTxid[j]);
+ }
+
+ // build the partial merkle tree
+ CPartialMerkleTree pmt1(vTxid, vMatch);
+
+ // serialize
+ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ ss << pmt1;
+
+ // verify CPartialMerkleTree's size guarantees
+ unsigned int n = std::min<unsigned int>(nTx, 1 + vMatchTxid1.size()*nHeight);
+ BOOST_CHECK(ss.size() <= 10 + (258*n+7)/8);
+
+ // deserialize into a tester copy
+ CPartialMerkleTreeTester pmt2;
+ ss >> pmt2;
+
+ // extract merkle root and matched txids from copy
+ std::vector<uint256> vMatchTxid2;
+ uint256 merkleRoot2 = pmt2.ExtractMatches(vMatchTxid2);
+
+ // check that it has the same merkle root as the original, and a valid one
+ BOOST_CHECK(merkleRoot1 == merkleRoot2);
+ BOOST_CHECK(merkleRoot2 != 0);
+
+ // check that it contains the matched transactions (in the same order!)
+ BOOST_CHECK(vMatchTxid1 == vMatchTxid2);
+
+ // check that random bit flips break the authentication
+ for (int j=0; j<4; j++) {
+ CPartialMerkleTreeTester pmt3(pmt2);
+ pmt3.Damage();
+ std::vector<uint256> vMatchTxid3;
+ uint256 merkleRoot3 = pmt3.ExtractMatches(vMatchTxid3);
+ BOOST_CHECK(merkleRoot3 != merkleRoot1);
+ }
+ }
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index eb820ade6..f8fe443b8 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -1,5 +1,6 @@
-#include <boost/test/unit_test.hpp>
+#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
+#include <boost/test/unit_test.hpp>
#include "base58.h"
#include "util.h"
@@ -22,14 +23,7 @@ createArgs(int nRequired, const char* address1=NULL, const char* address2=NULL)
return result;
}
-// This can be removed this when addmultisigaddress is enabled on main net:
-struct TestNetFixture
-{
- TestNetFixture() { fTestNet = true; }
- ~TestNetFixture() { fTestNet = false; }
-};
-
-BOOST_FIXTURE_TEST_CASE(rpc_addmultisig, TestNetFixture)
+BOOST_AUTO_TEST_CASE(rpc_addmultisig)
{
rpcfn_type addmultisig = tableRPC["addmultisigaddress"]->actor;
@@ -66,4 +60,91 @@ BOOST_FIXTURE_TEST_CASE(rpc_addmultisig, TestNetFixture)
BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), runtime_error);
}
+static Value CallRPC(string args)
+{
+ vector<string> vArgs;
+ boost::split(vArgs, args, boost::is_any_of(" \t"));
+ string strMethod = vArgs[0];
+ vArgs.erase(vArgs.begin());
+ Array params = RPCConvertValues(strMethod, vArgs);
+
+ rpcfn_type method = tableRPC[strMethod]->actor;
+ try {
+ Value result = (*method)(params, false);
+ return result;
+ }
+ catch (Object& objError)
+ {
+ throw runtime_error(find_value(objError, "message").get_str());
+ }
+}
+
+BOOST_AUTO_TEST_CASE(rpc_rawparams)
+{
+ // Test raw transaction API argument handling
+ Value r;
+
+ BOOST_CHECK_THROW(CallRPC("getrawtransaction"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("getrawtransaction not_hex"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("getrawtransaction a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed not_int"), runtime_error);
+
+ BOOST_CHECK_NO_THROW(CallRPC("listunspent"));
+ BOOST_CHECK_THROW(CallRPC("listunspent string"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("listunspent 0 string"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("listunspent 0 1 not_array"), runtime_error);
+ BOOST_CHECK_NO_THROW(r=CallRPC("listunspent 0 1 []"));
+ BOOST_CHECK_THROW(r=CallRPC("listunspent 0 1 [] extra"), runtime_error);
+ BOOST_CHECK(r.get_array().empty());
+
+ BOOST_CHECK_THROW(CallRPC("createrawtransaction"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("createrawtransaction null null"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("createrawtransaction not_array"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("createrawtransaction [] []"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("createrawtransaction {} {}"), runtime_error);
+ BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [] {}"));
+ BOOST_CHECK_THROW(CallRPC("createrawtransaction [] {} extra"), runtime_error);
+
+ BOOST_CHECK_THROW(CallRPC("decoderawtransaction"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("decoderawtransaction null"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("decoderawtransaction DEADBEEF"), runtime_error);
+ string rawtx = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000";
+ BOOST_CHECK_NO_THROW(r = CallRPC(string("decoderawtransaction ")+rawtx));
+ BOOST_CHECK_EQUAL(find_value(r.get_obj(), "version").get_int(), 1);
+ BOOST_CHECK_EQUAL(find_value(r.get_obj(), "locktime").get_int(), 0);
+ BOOST_CHECK_THROW(r = CallRPC(string("decoderawtransaction ")+rawtx+" extra"), runtime_error);
+
+ BOOST_CHECK_THROW(CallRPC("signrawtransaction"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("signrawtransaction null"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("signrawtransaction ff00"), runtime_error);
+ BOOST_CHECK_NO_THROW(CallRPC(string("signrawtransaction ")+rawtx));
+ BOOST_CHECK_NO_THROW(CallRPC(string("signrawtransaction ")+rawtx+" null null NONE|ANYONECANPAY"));
+ BOOST_CHECK_NO_THROW(CallRPC(string("signrawtransaction ")+rawtx+" [] [] NONE|ANYONECANPAY"));
+ BOOST_CHECK_THROW(CallRPC(string("signrawtransaction ")+rawtx+" null null badenum"), runtime_error);
+
+ // Only check failure cases for sendrawtransaction, there's no network to send to...
+ BOOST_CHECK_THROW(CallRPC("sendrawtransaction"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("sendrawtransaction null"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("sendrawtransaction DEADBEEF"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC(string("sendrawtransaction ")+rawtx+" extra"), runtime_error);
+}
+
+BOOST_AUTO_TEST_CASE(rpc_rawsign)
+{
+ Value r;
+ // input is a 1-of-2 multisig (so is output):
+ string prevout =
+ "[{\"txid\":\"b4cc287e58f87cdae59417329f710f3ecd75a4ee1d2872b7248f50977c8493f3\","
+ "\"vout\":1,\"scriptPubKey\":\"a914b10c9df5f7edf436c697f02f1efdba4cf399615187\","
+ "\"redeemScript\":\"512103debedc17b3df2badbcdd86d5feb4562b86fe182e5998abd8bcd4f122c6155b1b21027e940bb73ab8732bfdf7f9216ecefca5b94d6df834e77e108f68e66f126044c052ae\"}]";
+ r = CallRPC(string("createrawtransaction ")+prevout+" "+
+ "{\"3HqAe9LtNBjnsfM4CyYaWTnvCaUYT7v4oZ\":11}");
+ string notsigned = r.get_str();
+ string privkey1 = "\"KzsXybp9jX64P5ekX1KUxRQ79Jht9uzW7LorgwE65i5rWACL6LQe\"";
+ string privkey2 = "\"Kyhdf5LuKTRx4ge69ybABsiUAWjVRK4XGxAKk2FQLp2HjGMy87Z4\"";
+ r = CallRPC(string("signrawtransaction ")+notsigned+" "+prevout+" "+"[]");
+ BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == false);
+ r = CallRPC(string("signrawtransaction ")+notsigned+" "+prevout+" "+"["+privkey1+","+privkey2+"]");
+ BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == true);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp
index eabfcd030..b5107193f 100644
--- a/src/test/script_P2SH_tests.cpp
+++ b/src/test/script_P2SH_tests.cpp
@@ -13,8 +13,6 @@ 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,
- bool fValidatePayToScriptHash, int nHashType);
// Helpers:
static std::vector<unsigned char>
@@ -40,7 +38,7 @@ Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict)
txTo.vin[0].scriptSig = scriptSig;
txTo.vout[0].nValue = 1;
- return VerifyScript(scriptSig, scriptPubKey, txTo, 0, fStrict, 0);
+ return VerifyScript(scriptSig, scriptPubKey, txTo, 0, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, 0);
}
@@ -105,7 +103,7 @@ BOOST_AUTO_TEST_CASE(sign)
{
CScript sigSave = txTo[i].vin[0].scriptSig;
txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig;
- bool sigOK = VerifySignature(txFrom, txTo[i], 0, true, 0);
+ bool sigOK = VerifySignature(CCoins(txFrom, 0), txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, 0);
if (i == j)
BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j));
else
@@ -243,7 +241,8 @@ BOOST_AUTO_TEST_CASE(switchover)
BOOST_AUTO_TEST_CASE(AreInputsStandard)
{
- std::map<uint256, std::pair<CTxIndex, CTransaction> > mapInputs;
+ CCoinsView coinsDummy;
+ CCoinsViewCache coins(coinsDummy);
CBasicKeyStore keystore;
CKey key[3];
vector<CKey> keys;
@@ -264,23 +263,29 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
CScript pay1of3; pay1of3.SetMultisig(1, keys);
txFrom.vout[0].scriptPubKey = payScriptHash1;
+ txFrom.vout[0].nValue = 1000;
txFrom.vout[1].scriptPubKey = pay1;
+ txFrom.vout[1].nValue = 2000;
txFrom.vout[2].scriptPubKey = pay1of3;
+ txFrom.vout[2].nValue = 3000;
// Last three non-standard:
CScript empty;
keystore.AddCScript(empty);
txFrom.vout[3].scriptPubKey = empty;
+ txFrom.vout[3].nValue = 4000;
// Can't use SetPayToScriptHash, it checks for the empty Script. So:
txFrom.vout[4].scriptPubKey << OP_HASH160 << Hash160(empty) << OP_EQUAL;
+ txFrom.vout[4].nValue = 5000;
CScript oneOfEleven;
oneOfEleven << OP_1;
for (int i = 0; i < 11; i++)
oneOfEleven << key[0].GetPubKey();
oneOfEleven << OP_11 << OP_CHECKMULTISIG;
txFrom.vout[5].scriptPubKey.SetDestination(oneOfEleven.GetID());
+ txFrom.vout[5].nValue = 6000;
- mapInputs[txFrom.GetHash()] = make_pair(CTxIndex(), txFrom);
+ coins.SetCoins(txFrom.GetHash(), CCoins(txFrom, 0));
CTransaction txTo;
txTo.vout.resize(1);
@@ -297,21 +302,22 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
txTo.vin[2].prevout.hash = txFrom.GetHash();
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2));
- BOOST_CHECK(txTo.AreInputsStandard(mapInputs));
- BOOST_CHECK_EQUAL(txTo.GetP2SHSigOpCount(mapInputs), 1);
+ BOOST_CHECK(txTo.AreInputsStandard(coins));
+ BOOST_CHECK_EQUAL(txTo.GetP2SHSigOpCount(coins), 1);
// Make sure adding crap to the scriptSigs makes them non-standard:
for (int i = 0; i < 3; i++)
{
CScript t = txTo.vin[i].scriptSig;
txTo.vin[i].scriptSig = (CScript() << 11) + t;
- BOOST_CHECK(!txTo.AreInputsStandard(mapInputs));
+ BOOST_CHECK(!txTo.AreInputsStandard(coins));
txTo.vin[i].scriptSig = t;
}
CTransaction txToNonStd;
txToNonStd.vout.resize(1);
txToNonStd.vout[0].scriptPubKey.SetDestination(key[1].GetPubKey().GetID());
+ txToNonStd.vout[0].nValue = 1000;
txToNonStd.vin.resize(2);
txToNonStd.vin[0].prevout.n = 4;
txToNonStd.vin[0].prevout.hash = txFrom.GetHash();
@@ -320,11 +326,11 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
txToNonStd.vin[1].prevout.hash = txFrom.GetHash();
txToNonStd.vin[1].scriptSig << OP_0 << Serialize(oneOfEleven);
- BOOST_CHECK(!txToNonStd.AreInputsStandard(mapInputs));
- BOOST_CHECK_EQUAL(txToNonStd.GetP2SHSigOpCount(mapInputs), 11);
+ BOOST_CHECK(!txToNonStd.AreInputsStandard(coins));
+ BOOST_CHECK_EQUAL(txToNonStd.GetP2SHSigOpCount(coins), 11);
txToNonStd.vin[0].scriptSig.clear();
- BOOST_CHECK(!txToNonStd.AreInputsStandard(mapInputs));
+ BOOST_CHECK(!txToNonStd.AreInputsStandard(coins));
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 61d9a64ee..5d5a1525f 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -20,8 +20,8 @@ using namespace json_spirit;
using namespace boost::algorithm;
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,
- bool fValidatePayToScriptHash, int nHashType);
+
+static const unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
CScript
ParseScript(string s)
@@ -79,7 +79,7 @@ ParseScript(string s)
{
BOOST_ERROR("Parse error: " << s);
return CScript();
- }
+ }
}
return result;
@@ -143,7 +143,7 @@ BOOST_AUTO_TEST_CASE(script_valid)
CScript scriptPubKey = ParseScript(scriptPubKeyString);
CTransaction tx;
- BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, tx, 0, true, SIGHASH_NONE), strTest);
+ BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, tx, 0, flags, SIGHASH_NONE), strTest);
}
}
@@ -167,7 +167,7 @@ BOOST_AUTO_TEST_CASE(script_invalid)
CScript scriptPubKey = ParseScript(scriptPubKeyString);
CTransaction tx;
- BOOST_CHECK_MESSAGE(!VerifyScript(scriptSig, scriptPubKey, tx, 0, true, SIGHASH_NONE), strTest);
+ BOOST_CHECK_MESSAGE(!VerifyScript(scriptSig, scriptPubKey, tx, 0, flags, SIGHASH_NONE), strTest);
}
}
@@ -181,18 +181,18 @@ BOOST_AUTO_TEST_CASE(script_PushData)
static const unsigned char pushdata4[] = { OP_PUSHDATA4, 1, 0, 0, 0, 0x5a };
vector<vector<unsigned char> > directStack;
- BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), CTransaction(), 0, 0));
+ BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), CTransaction(), 0, true, 0));
vector<vector<unsigned char> > pushdata1Stack;
- BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), CTransaction(), 0, 0));
+ BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), CTransaction(), 0, true, 0));
BOOST_CHECK(pushdata1Stack == directStack);
vector<vector<unsigned char> > pushdata2Stack;
- BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), CTransaction(), 0, 0));
+ BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), CTransaction(), 0, true, 0));
BOOST_CHECK(pushdata2Stack == directStack);
vector<vector<unsigned char> > pushdata4Stack;
- BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), CTransaction(), 0, 0));
+ BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), CTransaction(), 0, true, 0));
BOOST_CHECK(pushdata4Stack == directStack);
}
@@ -206,7 +206,7 @@ sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transac
// NOTE: CHECKMULTISIG has an unfortunate bug; it requires
// one extra item on the stack, before the signatures.
// Putting OP_0 on the stack is the workaround;
- // fixing the bug would mean splitting the blockchain (old
+ // fixing the bug would mean splitting the block chain (old
// clients would not accept new CHECKMULTISIG transactions,
// and vice-versa)
//
@@ -250,15 +250,15 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
txTo12.vout[0].nValue = 1;
CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12);
- BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, true, 0));
+ BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, flags, 0));
txTo12.vout[0].nValue = 2;
- BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, true, 0));
+ BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, flags, 0));
CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12);
- BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, txTo12, 0, true, 0));
+ BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, txTo12, 0, flags, 0));
CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12);
- BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, txTo12, 0, true, 0));
+ BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, txTo12, 0, flags, 0));
}
BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
@@ -286,46 +286,46 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
std::vector<CKey> keys;
keys.push_back(key1); keys.push_back(key2);
CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, txTo23, 0, true, 0));
+ BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, txTo23, 0, flags, 0));
keys.clear();
keys.push_back(key1); keys.push_back(key3);
CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, txTo23, 0, true, 0));
+ BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, txTo23, 0, flags, 0));
keys.clear();
keys.push_back(key2); keys.push_back(key3);
CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, txTo23, 0, true, 0));
+ BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, txTo23, 0, flags, 0));
keys.clear();
keys.push_back(key2); keys.push_back(key2); // Can't re-use sig
CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, txTo23, 0, true, 0));
+ BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, txTo23, 0, flags, 0));
keys.clear();
keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order
CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, txTo23, 0, true, 0));
+ BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, txTo23, 0, flags, 0));
keys.clear();
keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order
CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, txTo23, 0, true, 0));
+ BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, txTo23, 0, flags, 0));
keys.clear();
keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys
CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, txTo23, 0, true, 0));
+ BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, txTo23, 0, flags, 0));
keys.clear();
keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys
CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, txTo23, 0, true, 0));
+ BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, txTo23, 0, flags, 0));
keys.clear(); // Must have signatures
CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, txTo23, 0, true, 0));
+ BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, txTo23, 0, flags, 0));
}
BOOST_AUTO_TEST_CASE(script_combineSigs)
diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp
new file mode 100644
index 000000000..90ac89f8c
--- /dev/null
+++ b/src/test/serialize_tests.cpp
@@ -0,0 +1,45 @@
+#include <boost/test/unit_test.hpp>
+
+#include <string>
+#include <vector>
+
+#include "serialize.h"
+
+using namespace std;
+
+BOOST_AUTO_TEST_SUITE(serialize_tests)
+
+BOOST_AUTO_TEST_CASE(varints)
+{
+ // encode
+
+ CDataStream ss(SER_DISK, 0);
+ CDataStream::size_type size = 0;
+ for (int i = 0; i < 100000; i++) {
+ ss << VARINT(i);
+ size += ::GetSerializeSize(VARINT(i), 0, 0);
+ BOOST_CHECK(size == ss.size());
+ }
+
+ for (uint64 i = 0; i < 100000000000ULL; i += 999999937) {
+ ss << VARINT(i);
+ size += ::GetSerializeSize(VARINT(i), 0, 0);
+ BOOST_CHECK(size == ss.size());
+ }
+
+ // decode
+ for (int i = 0; i < 100000; i++) {
+ int j;
+ ss >> VARINT(j);
+ BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
+ }
+
+ for (uint64 i = 0; i < 100000000000ULL; i += 999999937) {
+ uint64 j;
+ ss >> VARINT(j);
+ BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
+ }
+
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index bcf090787..1116507a3 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -1,9 +1,12 @@
#define BOOST_TEST_MODULE Bitcoin Test Suite
#include <boost/test/unit_test.hpp>
+#include <boost/filesystem.hpp>
#include "db.h"
+#include "txdb.h"
#include "main.h"
#include "wallet.h"
+#include "util.h"
CWallet* pwalletMain;
CClientUIInterface uiInterface;
@@ -12,21 +15,38 @@ extern bool fPrintToConsole;
extern void noui_connect();
struct TestingSetup {
+ CCoinsViewDB *pcoinsdbview;
+ boost::filesystem::path pathTemp;
+
TestingSetup() {
fPrintToDebugger = true; // don't want to write to debug.log file
noui_connect();
bitdb.MakeMock();
- LoadBlockIndex(true);
+ pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000)));
+ boost::filesystem::create_directories(pathTemp);
+ mapArgs["-datadir"] = pathTemp.string();
+ pblocktree = new CBlockTreeDB(1 << 20, true);
+ pcoinsdbview = new CCoinsViewDB(1 << 23, true);
+ pcoinsTip = new CCoinsViewCache(*pcoinsdbview);
+ InitBlockIndex();
bool fFirstRun;
pwalletMain = new CWallet("wallet.dat");
pwalletMain->LoadWallet(fFirstRun);
RegisterWallet(pwalletMain);
+ nScriptCheckThreads = 3;
+ for (int i=0; i < nScriptCheckThreads-1; i++)
+ NewThread(ThreadScriptCheck, NULL);
}
~TestingSetup()
{
+ ThreadScriptCheckQuit();
delete pwalletMain;
pwalletMain = NULL;
+ delete pcoinsTip;
+ delete pcoinsdbview;
+ delete pblocktree;
bitdb.Flush(true);
+ boost::filesystem::remove_all(pathTemp);
}
};
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index c23045886..f44d46fdb 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -66,7 +66,9 @@ BOOST_AUTO_TEST_CASE(tx_valid)
CTransaction tx;
stream >> tx;
- BOOST_CHECK_MESSAGE(tx.CheckTransaction(), strTest);
+ CValidationState state;
+ BOOST_CHECK_MESSAGE(tx.CheckTransaction(state), strTest);
+ BOOST_CHECK(state.IsValid());
for (unsigned int i = 0; i < tx.vin.size(); i++)
{
@@ -76,7 +78,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
break;
}
- BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], tx, i, test[2].get_bool(), 0), strTest);
+ BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], tx, i, test[2].get_bool() ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, 0), strTest);
}
}
}
@@ -133,7 +135,8 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
CTransaction tx;
stream >> tx;
- fValid = tx.CheckTransaction();
+ CValidationState state;
+ fValid = tx.CheckTransaction(state) && state.IsValid();
for (unsigned int i = 0; i < tx.vin.size() && fValid; i++)
{
@@ -143,7 +146,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
break;
}
- fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], tx, i, test[2].get_bool(), 0);
+ fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], tx, i, test[2].get_bool() ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, 0);
}
BOOST_CHECK_MESSAGE(!fValid, strTest);
@@ -159,11 +162,12 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests)
CDataStream stream(vch, SER_DISK, CLIENT_VERSION);
CTransaction tx;
stream >> tx;
- BOOST_CHECK_MESSAGE(tx.CheckTransaction(), "Simple deserialized transaction should be valid.");
+ CValidationState state;
+ BOOST_CHECK_MESSAGE(tx.CheckTransaction(state) && state.IsValid(), "Simple deserialized transaction should be valid.");
// Check that duplicate txins fail
tx.vin.push_back(tx.vin[0]);
- BOOST_CHECK_MESSAGE(!tx.CheckTransaction(), "Transaction with duplicate txins should be invalid.");
+ BOOST_CHECK_MESSAGE(!tx.CheckTransaction(state) || !state.IsValid(), "Transaction with duplicate txins should be invalid.");
}
//
@@ -173,7 +177,7 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests)
// paid to a TX_PUBKEYHASH.
//
static std::vector<CTransaction>
-SetupDummyInputs(CBasicKeyStore& keystoreRet, MapPrevTx& inputsRet)
+SetupDummyInputs(CBasicKeyStore& keystoreRet, CCoinsView & coinsRet)
{
std::vector<CTransaction> dummyTransactions;
dummyTransactions.resize(2);
@@ -192,14 +196,14 @@ SetupDummyInputs(CBasicKeyStore& keystoreRet, MapPrevTx& inputsRet)
dummyTransactions[0].vout[0].scriptPubKey << key[0].GetPubKey() << OP_CHECKSIG;
dummyTransactions[0].vout[1].nValue = 50*CENT;
dummyTransactions[0].vout[1].scriptPubKey << key[1].GetPubKey() << OP_CHECKSIG;
- inputsRet[dummyTransactions[0].GetHash()] = make_pair(CTxIndex(), dummyTransactions[0]);
+ coinsRet.SetCoins(dummyTransactions[0].GetHash(), CCoins(dummyTransactions[0], 0));
dummyTransactions[1].vout.resize(2);
dummyTransactions[1].vout[0].nValue = 21*CENT;
dummyTransactions[1].vout[0].scriptPubKey.SetDestination(key[2].GetPubKey().GetID());
dummyTransactions[1].vout[1].nValue = 22*CENT;
dummyTransactions[1].vout[1].scriptPubKey.SetDestination(key[3].GetPubKey().GetID());
- inputsRet[dummyTransactions[1].GetHash()] = make_pair(CTxIndex(), dummyTransactions[1]);
+ coinsRet.SetCoins(dummyTransactions[1].GetHash(), CCoins(dummyTransactions[1], 0));
return dummyTransactions;
}
@@ -207,8 +211,9 @@ SetupDummyInputs(CBasicKeyStore& keystoreRet, MapPrevTx& inputsRet)
BOOST_AUTO_TEST_CASE(test_Get)
{
CBasicKeyStore keystore;
- MapPrevTx dummyInputs;
- std::vector<CTransaction> dummyTransactions = SetupDummyInputs(keystore, dummyInputs);
+ CCoinsView coinsDummy;
+ CCoinsViewCache coins(coinsDummy);
+ std::vector<CTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
CTransaction t1;
t1.vin.resize(3);
@@ -225,25 +230,24 @@ BOOST_AUTO_TEST_CASE(test_Get)
t1.vout[0].nValue = 90*CENT;
t1.vout[0].scriptPubKey << OP_1;
- BOOST_CHECK(t1.AreInputsStandard(dummyInputs));
- BOOST_CHECK_EQUAL(t1.GetValueIn(dummyInputs), (50+21+22)*CENT);
+ BOOST_CHECK(t1.AreInputsStandard(coins));
+ BOOST_CHECK_EQUAL(t1.GetValueIn(coins), (50+21+22)*CENT);
// Adding extra junk to the scriptSig should make it non-standard:
t1.vin[0].scriptSig << OP_11;
- BOOST_CHECK(!t1.AreInputsStandard(dummyInputs));
+ BOOST_CHECK(!t1.AreInputsStandard(coins));
// ... as should not having enough:
t1.vin[0].scriptSig = CScript();
- BOOST_CHECK(!t1.AreInputsStandard(dummyInputs));
+ BOOST_CHECK(!t1.AreInputsStandard(coins));
}
BOOST_AUTO_TEST_CASE(test_GetThrow)
{
CBasicKeyStore keystore;
- MapPrevTx dummyInputs;
- std::vector<CTransaction> dummyTransactions = SetupDummyInputs(keystore, dummyInputs);
-
- MapPrevTx missingInputs;
+ CCoinsView coinsDummy;
+ CCoinsViewCache coins(coinsDummy);
+ std::vector<CTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
CTransaction t1;
t1.vin.resize(3);
@@ -256,9 +260,6 @@ BOOST_AUTO_TEST_CASE(test_GetThrow)
t1.vout.resize(2);
t1.vout[0].nValue = 90*CENT;
t1.vout[0].scriptPubKey << OP_1;
-
- BOOST_CHECK_THROW(t1.AreInputsStandard(missingInputs), runtime_error);
- BOOST_CHECK_THROW(t1.GetValueIn(missingInputs), runtime_error);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 3a4c035a3..f56969cba 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -104,11 +104,11 @@ BOOST_AUTO_TEST_CASE(util_HexStr)
BOOST_AUTO_TEST_CASE(util_DateTimeStrFormat)
{
/*These are platform-dependant and thus removed to avoid useless test failures
- BOOST_CHECK_EQUAL(DateTimeStrFormat("%x %H:%M:%S", 0), "01/01/70 00:00:00");
- BOOST_CHECK_EQUAL(DateTimeStrFormat("%x %H:%M:%S", 0x7FFFFFFF), "01/19/38 03:14:07");
+ BOOST_CHECK_EQUAL(DateTimeStrFormat("%Y-%m-%d %H:%M:%S", 0), "1970-01-01 00:00:00");
+ BOOST_CHECK_EQUAL(DateTimeStrFormat("%Y-%m-%d %H:%M:%S", 0x7FFFFFFF), "2038-01-19 03:14:07");
// Formats used within Bitcoin
- BOOST_CHECK_EQUAL(DateTimeStrFormat("%x %H:%M:%S", 1317425777), "09/30/11 23:36:17");
- BOOST_CHECK_EQUAL(DateTimeStrFormat("%x %H:%M", 1317425777), "09/30/11 23:36");
+ BOOST_CHECK_EQUAL(DateTimeStrFormat("%Y-%m-%d %H:%M:%S", 1317425777), "2011-09-30 23:36:17");
+ BOOST_CHECK_EQUAL(DateTimeStrFormat("%Y-%m-%d %H:%M", 1317425777), "2011-09-30 23:36");
*/
}