From 67a9b8a0914242b1366cec243bc1b7a0b035734f Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Sun, 19 Jun 2016 13:11:08 -0500 Subject: [PATCH 01/11] Adding rapidcheck dependency, adding CKey properties Adding rapidcheck dependency, adding CKey properties Successfully compiling bitcoin with rapidcheck dependency Adding new property file for CKey Serialization symmetry for CKey -> CBitcoinSecret -> CKey Adding generators for CPrivKey, CPubKey, and uint256 [depends] Rework rapidcheck.mk --- configure.ac | 6 +++++ depends/packages/packages.mk | 2 +- depends/packages/rapidcheck.mk | 13 ++++++++++ src/Makefile.test.include | 4 ++- src/test/gen/crypto_gen.h | 50 +++++++++++++++++++++++++++++++++++++ src/test/key_properties.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 depends/packages/rapidcheck.mk create mode 100644 src/test/gen/crypto_gen.h create mode 100644 src/test/key_properties.cpp diff --git a/configure.ac b/configure.ac index 36727004887..61fd9ba288d 100644 --- a/configure.ac +++ b/configure.ac @@ -654,6 +654,12 @@ if test x$use_upnp != xno; then ) fi +dnl check for rapidcheck +AC_CHECK_HEADERS( + [rapidcheck.h], + [AC_CHECK_LIB([rapidcheck], [main],[], [])], + []) + BITCOIN_QT_INIT dnl sets $bitcoin_enable_qt, $bitcoin_enable_qt_test, $bitcoin_enable_qt_dbus diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 088723ebd0d..4d2b424a7c7 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -1,4 +1,4 @@ -packages:=boost openssl libevent zeromq +packages:=boost openssl libevent zeromq rapidcheck native_packages := native_ccache qt_native_packages = native_protobuf diff --git a/depends/packages/rapidcheck.mk b/depends/packages/rapidcheck.mk new file mode 100644 index 00000000000..36e4e8f4955 --- /dev/null +++ b/depends/packages/rapidcheck.mk @@ -0,0 +1,13 @@ +package=rapidcheck +$(package)_version=f5d3afa +$(package)_download_path=https://bitcoin-10596.firebaseapp.com/depends +$(package)_file_name=$(package)-$($(package)_version).tar.gz +$(package)_sha256_hash=78cdb8d0185b602e32e66f4e5d1a6ceec1f801dd9641b8a9456c386b1eaaf0e5 + +define $(package)_config_cmds + cmake -DCMAKE_INSTALL_PREFIX=$(build_prefix) +endef + +define $(package)_build_cmds + $(MAKE) +endef diff --git a/src/Makefile.test.include b/src/Makefile.test.include index ee1c11ff1f6..3a97802bbec 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -44,6 +44,7 @@ BITCOIN_TESTS =\ test/getarg_tests.cpp \ test/hash_tests.cpp \ test/key_tests.cpp \ + test/key_properties.cpp \ test/limitedmap_tests.cpp \ test/dbwrapper_tests.cpp \ test/main_tests.cpp \ @@ -84,7 +85,8 @@ BITCOIN_TESTS =\ test/versionbits_tests.cpp \ test/uint256_tests.cpp \ test/univalue_tests.cpp \ - test/util_tests.cpp + test/util_tests.cpp \ + test/gen/crypto_gen.h if ENABLE_WALLET BITCOIN_TESTS += \ diff --git a/src/test/gen/crypto_gen.h b/src/test/gen/crypto_gen.h new file mode 100644 index 00000000000..4bf7d53ac91 --- /dev/null +++ b/src/test/gen/crypto_gen.h @@ -0,0 +1,50 @@ +#include "key.h" +#include "random.h" +#include "uint256.h" +#include +#include + +namespace rc { + + /** Generator for a new CKey */ + template<> + struct Arbitrary { + static Gen arbitrary() { + return gen::map([](int x) { + CKey key; + key.MakeNewKey(true); + return key; + }); + }; + }; + + /** Generator for a CPrivKey */ + template<> + struct Arbitrary { + static Gen arbitrary() { + return gen::map([](CKey key) { + return key.GetPrivKey(); + }); + }; + }; + + /** Generator for a new CPubKey */ + template<> + struct Arbitrary { + static Gen arbitrary() { + return gen::map([](CKey key) { + return key.GetPubKey(); + }); + }; + }; + + /** Generates a arbitrary uint256 */ + template<> + struct Arbitrary { + static Gen arbitrary() { + return gen::map([](int x) { + return GetRandHash(); + }); + }; + }; +} diff --git a/src/test/key_properties.cpp b/src/test/key_properties.cpp new file mode 100644 index 00000000000..038b25745fc --- /dev/null +++ b/src/test/key_properties.cpp @@ -0,0 +1,56 @@ +// Copyright (c) 2012-2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "key.h" + +#include "base58.h" +#include "script/script.h" +#include "uint256.h" +#include "util.h" +#include "utilstrencodings.h" +#include "test/test_bitcoin.h" +#include +#include + +#include +#include +#include +#include + +#include "test/gen/crypto_gen.h" +/** Generator for a new CKey */ +BOOST_FIXTURE_TEST_SUITE(key_properties, BasicTestingSetup) + +/** Check CKey uniqueness */ +RC_BOOST_PROP(key_uniqueness, (CKey key1, CKey key2)) { + RC_ASSERT(!(key1 == key2)); +} + +/** Verify that a private key generates the correct public key */ +RC_BOOST_PROP(key_generates_correct_pubkey, (CKey key)) { + CPubKey pubKey = key.GetPubKey(); + RC_ASSERT(key.VerifyPubKey(pubKey)); +} + +/** Serialization symmetry CKey -> CBitcoinSecret -> CKey */ +RC_BOOST_PROP(key_bitcoinsecret_symmetry, (CKey key)) { + CBitcoinSecret secret; + secret.SetKey(key); + RC_ASSERT(secret.GetKey() == key); +} + +/** Create a CKey using the 'Set' function must give us the same key */ +RC_BOOST_PROP(key_set_symmetry, (CKey key)) { + CKey key1; + key1.Set(key.begin(), key.end(), key.IsCompressed()); + RC_ASSERT(key1 == key); +} + +/** Create a CKey, sign a piece of data, then verify it with the public key */ +RC_BOOST_PROP(key_sign_symmetry, (CKey key, uint256 hash)) { + std::vector vchSig; + key.Sign(hash,vchSig,0); + CPubKey pubKey = key.GetPubKey(); + RC_ASSERT(pubKey.Verify(hash,vchSig)); +} +BOOST_AUTO_TEST_SUITE_END() From e3f2f472e7969af3a946ad1d21a00669aa5811d6 Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Sun, 28 Aug 2016 17:54:42 -0500 Subject: [PATCH 02/11] Adding Bloom filter properties and bloom filter generator --- src/Makefile.test.include | 5 ++++- src/test/bloom_properties.cpp | 30 ++++++++++++++++++++++++++++++ src/test/gen/bloom_gen.h | 32 ++++++++++++++++++++++++++++++++ src/test/key_properties.cpp | 2 +- 4 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 src/test/bloom_properties.cpp create mode 100644 src/test/gen/bloom_gen.h diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 3a97802bbec..e16a7fe5fe2 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -36,6 +36,8 @@ BITCOIN_TESTS =\ test/bloom_tests.cpp \ test/bswap_tests.cpp \ test/checkqueue_tests.cpp \ + test/bloom_properties.cpp \ + test/Checkpoints_tests.cpp \ test/coins_tests.cpp \ test/compress_tests.cpp \ test/crypto_tests.cpp \ @@ -86,7 +88,8 @@ BITCOIN_TESTS =\ test/uint256_tests.cpp \ test/univalue_tests.cpp \ test/util_tests.cpp \ - test/gen/crypto_gen.h + test/gen/crypto_gen.h \ + test/gen/bloom_gen.h if ENABLE_WALLET BITCOIN_TESTS += \ diff --git a/src/test/bloom_properties.cpp b/src/test/bloom_properties.cpp new file mode 100644 index 00000000000..28f7ca88b95 --- /dev/null +++ b/src/test/bloom_properties.cpp @@ -0,0 +1,30 @@ +// Copyright (c) 2012-2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "key.h" + +//#include "base58.h" +//#include "script/script.h" +//#include "uint256.h" +//#include "util.h" +//#include "utilstrencodings.h" +#include "test/test_bitcoin.h" +//#include +//#include + +#include +#include +#include +#include + +#include "test/gen/bloom_gen.h" +#include "test/gen/crypto_gen.h" + +BOOST_FIXTURE_TEST_SUITE(bloom_properties, BasicTestingSetup) + +RC_BOOST_PROP(no_false_negatives, (CBloomFilter bloomFilter, uint256 hash)) { + bloomFilter.insert(hash); + RC_ASSERT(bloomFilter.contains(hash)); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/gen/bloom_gen.h b/src/test/gen/bloom_gen.h new file mode 100644 index 00000000000..158500802e2 --- /dev/null +++ b/src/test/gen/bloom_gen.h @@ -0,0 +1,32 @@ +#include +#include +#include +#include "bloom.h" +namespace rc { + /** Generates a double between 0,1 exclusive */ + Gen betweenZeroAndOne = gen::suchThat([](double x) { + return fmod(x,1) != 0 ; + }); + /** Generates the C++ primitives used to create a bloom filter */ + Gen> bloomFilterPrimitives = gen::tuple(gen::inRange(1,100), + betweenZeroAndOne, + gen::arbitrary(), + gen::inRange(0,3)); + + + /** Generator for a new CBloomFilter*/ + template<> + struct Arbitrary { + static Gen arbitrary() { + return gen::map(bloomFilterPrimitives, [](std::tuple filterPrimitives) { + //need to generate numElements, fpRate, nTweakIn, bloomFlag + unsigned int numElements; + double fpRate; + unsigned int nTweakIn; + unsigned int bloomFlag; + std::tie(numElements, fpRate, nTweakIn, bloomFlag) = filterPrimitives; + return CBloomFilter(numElements,fpRate,nTweakIn,bloomFlag); + }); + }; + }; +} diff --git a/src/test/key_properties.cpp b/src/test/key_properties.cpp index 038b25745fc..009578de5a1 100644 --- a/src/test/key_properties.cpp +++ b/src/test/key_properties.cpp @@ -18,7 +18,7 @@ #include #include "test/gen/crypto_gen.h" -/** Generator for a new CKey */ + BOOST_FIXTURE_TEST_SUITE(key_properties, BasicTestingSetup) /** Check CKey uniqueness */ From 2737955754ddfded8a72780e4f55cef1c4d928ba Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Sun, 4 Sep 2016 20:57:53 -0500 Subject: [PATCH 03/11] Adding serialization symmetry for CBloomFilter --- src/test/bloom_properties.cpp | 10 ++++++++++ src/test/gen/bloom_gen.h | 6 ++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/test/bloom_properties.cpp b/src/test/bloom_properties.cpp index 28f7ca88b95..37ef8e5f969 100644 --- a/src/test/bloom_properties.cpp +++ b/src/test/bloom_properties.cpp @@ -27,4 +27,14 @@ RC_BOOST_PROP(no_false_negatives, (CBloomFilter bloomFilter, uint256 hash)) { RC_ASSERT(bloomFilter.contains(hash)); } +RC_BOOST_PROP(serialization_symmetry, (CBloomFilter bloomFilter)) { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << bloomFilter; + CBloomFilter bloomFilter2; + ss >> bloomFilter2; + CDataStream ss1(SER_NETWORK, PROTOCOL_VERSION); + ss << bloomFilter; + ss1 << bloomFilter2; + RC_ASSERT(ss.str() == ss1.str()); +} BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/gen/bloom_gen.h b/src/test/gen/bloom_gen.h index 158500802e2..35f9062e747 100644 --- a/src/test/gen/bloom_gen.h +++ b/src/test/gen/bloom_gen.h @@ -5,7 +5,7 @@ namespace rc { /** Generates a double between 0,1 exclusive */ Gen betweenZeroAndOne = gen::suchThat([](double x) { - return fmod(x,1) != 0 ; + return fmod(x,1) != 0; }); /** Generates the C++ primitives used to create a bloom filter */ Gen> bloomFilterPrimitives = gen::tuple(gen::inRange(1,100), @@ -13,13 +13,11 @@ namespace rc { gen::arbitrary(), gen::inRange(0,3)); - /** Generator for a new CBloomFilter*/ template<> struct Arbitrary { static Gen arbitrary() { - return gen::map(bloomFilterPrimitives, [](std::tuple filterPrimitives) { - //need to generate numElements, fpRate, nTweakIn, bloomFlag + return gen::map(bloomFilterPrimitives, [](std::tuple filterPrimitives) { unsigned int numElements; double fpRate; unsigned int nTweakIn; From 179337a889d8730fc91b9f031d97e2b4038e2784 Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Sun, 25 Sep 2016 12:08:44 -0500 Subject: [PATCH 04/11] Adding block header serialization property Fixing generator bug where I wasn't setting all fields on a BlockHeader --- src/Makefile.test.include | 6 ++++-- src/test/block_properties.cpp | 24 ++++++++++++++++++++++++ src/test/gen/block_gen.h | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 src/test/block_properties.cpp create mode 100644 src/test/gen/block_gen.h diff --git a/src/Makefile.test.include b/src/Makefile.test.include index e16a7fe5fe2..6e99d5f9e03 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -33,6 +33,7 @@ BITCOIN_TESTS =\ test/base64_tests.cpp \ test/bip32_tests.cpp \ test/blockencodings_tests.cpp \ + test/block_properties.cpp \ test/bloom_tests.cpp \ test/bswap_tests.cpp \ test/checkqueue_tests.cpp \ @@ -88,8 +89,9 @@ BITCOIN_TESTS =\ test/uint256_tests.cpp \ test/univalue_tests.cpp \ test/util_tests.cpp \ - test/gen/crypto_gen.h \ - test/gen/bloom_gen.h + test/gen/crypto_gen.h \ + test/gen/bloom_gen.h \ + test/gen/block_gen.h if ENABLE_WALLET BITCOIN_TESTS += \ diff --git a/src/test/block_properties.cpp b/src/test/block_properties.cpp new file mode 100644 index 00000000000..326d7c61b9a --- /dev/null +++ b/src/test/block_properties.cpp @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +#include "test/test_bitcoin.h" +#include "primitives/block.h" +#include "test/gen/block_gen.h" + + +BOOST_FIXTURE_TEST_SUITE(block_properties, BasicTestingSetup) + +RC_BOOST_PROP(blockheader_serialization_symmetry, (CBlockHeader header)) { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << header; + CBlockHeader header2; + ss >> header2; + CDataStream ss1(SER_NETWORK, PROTOCOL_VERSION); + ss << header; + ss1 << header2; + RC_ASSERT(ss.str() == ss1.str()); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/gen/block_gen.h b/src/test/gen/block_gen.h new file mode 100644 index 00000000000..4654217a41f --- /dev/null +++ b/src/test/gen/block_gen.h @@ -0,0 +1,35 @@ +#include +#include +#include "primitives/block.h" +#include "uint256.h" +#include "test/gen/crypto_gen.h" +namespace rc { + + Gen> blockHeaderPrimitives = gen::tuple(gen::arbitrary(), + gen::arbitrary(), gen::arbitrary(), + gen::arbitrary(), gen::arbitrary(), gen::arbitrary()); + + /** Generator for a new CBlockHeader */ + template<> + struct Arbitrary { + static Gen arbitrary() { + return gen::map(blockHeaderPrimitives, [](std::tuple headerPrimitives) { + int32_t nVersion; + uint256 hashPrevBlock; + uint256 hashMerkleRoot; + uint32_t nTime; + uint32_t nBits; + uint32_t nNonce; + std::tie(nVersion,hashPrevBlock, hashMerkleRoot, nTime,nBits,nNonce) = headerPrimitives; + CBlockHeader header; + header.nVersion = nVersion; + header.hashPrevBlock = hashPrevBlock; + header.hashMerkleRoot = hashMerkleRoot; + header.nTime = nTime; + header.nBits = nBits; + header.nNonce = nNonce; + return header; + }); + }; + }; +} From 0aa0d0ad1166af5858b490e3e40564d28565db67 Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Sun, 13 Nov 2016 20:50:35 -0600 Subject: [PATCH 05/11] Creating transaction_gen.h, adding generator for COutPoint and serialization symmetry property for COutPoint --- src/Makefile.test.include | 4 +++- src/test/gen/transaction_gen.h | 18 ++++++++++++++++++ src/test/transaction_properties.cpp | 30 ++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 src/test/gen/transaction_gen.h create mode 100644 src/test/transaction_properties.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 6e99d5f9e03..89e40600972 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -84,6 +84,7 @@ BITCOIN_TESTS =\ test/timedata_tests.cpp \ test/torcontrol_tests.cpp \ test/transaction_tests.cpp \ + test/transaction_properties.cpp \ test/txvalidationcache_tests.cpp \ test/versionbits_tests.cpp \ test/uint256_tests.cpp \ @@ -91,7 +92,8 @@ BITCOIN_TESTS =\ test/util_tests.cpp \ test/gen/crypto_gen.h \ test/gen/bloom_gen.h \ - test/gen/block_gen.h + test/gen/block_gen.h \ + test/gen/transaction_gen.h if ENABLE_WALLET BITCOIN_TESTS += \ diff --git a/src/test/gen/transaction_gen.h b/src/test/gen/transaction_gen.h new file mode 100644 index 00000000000..e8fe9e43c09 --- /dev/null +++ b/src/test/gen/transaction_gen.h @@ -0,0 +1,18 @@ +#include +#include +#include "primitives/transaction.h" +#include "test/gen/crypto_gen.h" +namespace rc { + + template<> + struct Arbitrary { + static Gen arbitrary() { + return gen::map(gen::tuple(gen::arbitrary(), gen::arbitrary()), [](std::tuple outPointPrimitives) { + uint32_t nIn; + uint256 nHashIn; + std::tie(nHashIn, nIn) = outPointPrimitives; + return COutPoint(nHashIn, nIn); + }); + }; + }; +} diff --git a/src/test/transaction_properties.cpp b/src/test/transaction_properties.cpp new file mode 100644 index 00000000000..3f8584744af --- /dev/null +++ b/src/test/transaction_properties.cpp @@ -0,0 +1,30 @@ +#include "key.h" + +#include "base58.h" +#include "script/script.h" +#include "uint256.h" +#include "util.h" +#include "utilstrencodings.h" +#include "test/test_bitcoin.h" +#include +#include + +#include +#include +#include +#include + +#include "test/gen/transaction_gen.h" + +BOOST_FIXTURE_TEST_SUITE(transaction_properties, BasicTestingSetup) + +/** Check CKey uniqueness */ +RC_BOOST_PROP(outpoint_serialization_symmetry, (COutPoint outpoint)) { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << outpoint; + COutPoint outpoint2; + ss >> outpoint2; + RC_ASSERT(outpoint2 == outpoint); +} + +BOOST_AUTO_TEST_SUITE_END() From 92a9724249ac99b5165b22b19ce53c4f642803f7 Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Sat, 7 Jan 2017 12:44:20 -0600 Subject: [PATCH 06/11] Adding script generator and script_propertes, first property is CScript serialization symmetry --- src/Makefile.test.include | 7 +++++-- src/test/gen/script_gen.h | 15 +++++++++++++++ src/test/gen/transaction_gen.h | 6 ++++-- src/test/script_properties.cpp | 25 +++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 src/test/gen/script_gen.h create mode 100644 src/test/script_properties.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 89e40600972..8ac846d8142 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -33,8 +33,9 @@ BITCOIN_TESTS =\ test/base64_tests.cpp \ test/bip32_tests.cpp \ test/blockencodings_tests.cpp \ - test/block_properties.cpp \ + test/block_properties.cpp \ test/bloom_tests.cpp \ + test/bloom_properties.cpp \ test/bswap_tests.cpp \ test/checkqueue_tests.cpp \ test/bloom_properties.cpp \ @@ -68,6 +69,7 @@ BITCOIN_TESTS =\ test/sanity_tests.cpp \ test/scheduler_tests.cpp \ test/script_P2SH_tests.cpp \ + test/script_properties.cpp \ test/script_tests.cpp \ test/scriptnum_tests.cpp \ test/serialize_tests.cpp \ @@ -92,7 +94,8 @@ BITCOIN_TESTS =\ test/util_tests.cpp \ test/gen/crypto_gen.h \ test/gen/bloom_gen.h \ - test/gen/block_gen.h \ + test/gen/block_gen.h \ + test/gen/script_gen.h \ test/gen/transaction_gen.h if ENABLE_WALLET diff --git a/src/test/gen/script_gen.h b/src/test/gen/script_gen.h new file mode 100644 index 00000000000..a00128bbb70 --- /dev/null +++ b/src/test/gen/script_gen.h @@ -0,0 +1,15 @@ +#include +#include +#include "test/gen/crypto_gen.h" +#include "script/script.h" + +namespace rc { + template<> + struct Arbitrary { + static Gen arbitrary() { + return gen::map(gen::arbitrary>(), [](std::vector script) { + return CScript(script); + }); + }; + }; +} diff --git a/src/test/gen/transaction_gen.h b/src/test/gen/transaction_gen.h index e8fe9e43c09..8184d65736f 100644 --- a/src/test/gen/transaction_gen.h +++ b/src/test/gen/transaction_gen.h @@ -1,7 +1,8 @@ #include #include #include "primitives/transaction.h" -#include "test/gen/crypto_gen.h" +#include "test/gen/crypto_gen.h" +#include "script/script.h" namespace rc { template<> @@ -14,5 +15,6 @@ namespace rc { return COutPoint(nHashIn, nIn); }); }; - }; + }; + } diff --git a/src/test/script_properties.cpp b/src/test/script_properties.cpp new file mode 100644 index 00000000000..892e773d012 --- /dev/null +++ b/src/test/script_properties.cpp @@ -0,0 +1,25 @@ +#include +#include + +#include +#include +#include +#include + +#include "script/script.h" +#include "test/test_bitcoin.h" +#include "test/gen/script_gen.h" + +BOOST_FIXTURE_TEST_SUITE(script_properties, BasicTestingSetup) + +/** Check CScript serialization symmetry */ +RC_BOOST_PROP(cscript_serialization_symmetry, (CScript script)) { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << static_cast(script); + std::vector deserialized; + ss >> deserialized; + CScript script2 = CScript(deserialized.begin(), deserialized.end()); + RC_ASSERT(script == script2); +} + +BOOST_AUTO_TEST_SUITE_END() From fdc0cf10c0d60bdbd94ee44465eb46e7e19a66e0 Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Sat, 7 Jan 2017 19:41:51 -0600 Subject: [PATCH 07/11] Adding CTransaction generator, adding serialization symmetry property for CTransaction Removing 'oneOrMoreInputs' and 'oneOrMoreOutputs' generators in favor of using rapidcheck's gen::nonEmpty function --- src/test/gen/transaction_gen.h | 59 ++++++++++++++++++++++++++++++++++++- src/test/transaction_properties.cpp | 30 +++++++++++++++++-- 2 files changed, 86 insertions(+), 3 deletions(-) diff --git a/src/test/gen/transaction_gen.h b/src/test/gen/transaction_gen.h index 8184d65736f..6586f85f219 100644 --- a/src/test/gen/transaction_gen.h +++ b/src/test/gen/transaction_gen.h @@ -1,8 +1,9 @@ #include #include #include "primitives/transaction.h" -#include "test/gen/crypto_gen.h" +#include "test/gen/script_gen.h" #include "script/script.h" +#include "amount.h" namespace rc { template<> @@ -17,4 +18,60 @@ namespace rc { }; }; + + template<> + struct Arbitrary { + static Gen arbitrary() { + return gen::map(gen::tuple(gen::arbitrary(), gen::arbitrary(), gen::arbitrary()), [](std::tuple txInPrimitives) { + COutPoint outpoint; + CScript script; + uint32_t sequence; + std::tie(outpoint,script,sequence) = txInPrimitives; + return CTxIn(outpoint,script,sequence); + }); + }; + }; + + template<> + struct Arbitrary { + static Gen arbitrary() { + //why doesn't this generator call work? It seems to cause an infinite loop. + //return gen::arbitrary(); + return gen::inRange(std::numeric_limits::min(),std::numeric_limits::max()); + }; + }; + + template<> + struct Arbitrary { + static Gen arbitrary() { + return gen::map(gen::tuple(gen::arbitrary(), gen::arbitrary()), [](std::tuple txOutPrimitives) { + CAmount amount; + CScript script; + std::tie(amount,script) = txOutPrimitives; + return CTxOut(amount,script); + }); + }; + }; + + + template<> + struct Arbitrary { + static Gen arbitrary() { + return gen::map(gen::tuple(gen::arbitrary(), + gen::nonEmpty>(), gen::nonEmpty>(), gen::arbitrary()), + [](std::tuple, std::vector, uint32_t> txPrimitives) { + CMutableTransaction tx; + int32_t nVersion; + std::vector vin; + std::vector vout; + uint32_t locktime; + std::tie(nVersion, vin, vout, locktime) = txPrimitives; + tx.nVersion=nVersion; + tx.vin=vin; + tx.vout=vout; + tx.nLockTime=locktime; + return CTransaction(tx); + }); + }; + }; } diff --git a/src/test/transaction_properties.cpp b/src/test/transaction_properties.cpp index 3f8584744af..818415050e9 100644 --- a/src/test/transaction_properties.cpp +++ b/src/test/transaction_properties.cpp @@ -6,6 +6,7 @@ #include "util.h" #include "utilstrencodings.h" #include "test/test_bitcoin.h" +#include "streams.h" #include #include @@ -13,12 +14,11 @@ #include #include #include - #include "test/gen/transaction_gen.h" BOOST_FIXTURE_TEST_SUITE(transaction_properties, BasicTestingSetup) -/** Check CKey uniqueness */ +/** Check COutpoint serialization symmetry */ RC_BOOST_PROP(outpoint_serialization_symmetry, (COutPoint outpoint)) { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << outpoint; @@ -26,5 +26,31 @@ RC_BOOST_PROP(outpoint_serialization_symmetry, (COutPoint outpoint)) { ss >> outpoint2; RC_ASSERT(outpoint2 == outpoint); } +/** Check CTxIn serialization symmetry */ +RC_BOOST_PROP(ctxin_serialization_symmetry, (CTxIn txIn)) { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << txIn; + CTxIn txIn2; + ss >> txIn2; + RC_ASSERT(txIn == txIn2); +} + +/** Check CTxOut serialization symmetry */ +RC_BOOST_PROP(ctxout_serialization_symmetry, (CTxOut txOut)) { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << txOut; + CTxOut txOut2; + ss >> txOut2; + RC_ASSERT(txOut == txOut2); +} + +/** Check CTransaction serialization symmetry */ +RC_BOOST_PROP(ctransaction_serialization_symmetry, (CTransaction tx)) { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << tx; + deserialize_type t; + CTransaction tx2(t,ss); + RC_ASSERT(tx == tx2); +} BOOST_AUTO_TEST_SUITE_END() From c767e6b4bcdd0536dac4010c387ea6e221cf0e92 Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Sun, 15 Jan 2017 10:45:07 -0600 Subject: [PATCH 08/11] Adding CTransactionRef and CBlock generators, adding property for CBlock serialization symmetry --- src/test/block_properties.cpp | 8 ++++++++ src/test/gen/block_gen.h | 27 ++++++++++++++++++++++----- src/test/gen/crypto_gen.h | 4 ++++ src/test/gen/script_gen.h | 4 ++++ src/test/gen/transaction_gen.h | 24 ++++++++++++++++++++---- 5 files changed, 58 insertions(+), 9 deletions(-) diff --git a/src/test/block_properties.cpp b/src/test/block_properties.cpp index 326d7c61b9a..856092fdf3f 100644 --- a/src/test/block_properties.cpp +++ b/src/test/block_properties.cpp @@ -21,4 +21,12 @@ RC_BOOST_PROP(blockheader_serialization_symmetry, (CBlockHeader header)) { RC_ASSERT(ss.str() == ss1.str()); } +RC_BOOST_PROP(block_serialization_symmetry, (CBlock block)) { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << block; + CBlock block2; + ss >> block2; + RC_ASSERT(block.GetHash() == block2.GetHash()); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/gen/block_gen.h b/src/test/gen/block_gen.h index 4654217a41f..dc0366a683d 100644 --- a/src/test/gen/block_gen.h +++ b/src/test/gen/block_gen.h @@ -1,19 +1,23 @@ +#ifndef BITCOIN_TEST_GEN_BLOCK_GEN_H +#define BITCOIN_TEST_GEN_BLOCK_GEN_H + #include #include #include "primitives/block.h" #include "uint256.h" #include "test/gen/crypto_gen.h" +#include "test/gen/transaction_gen.h" namespace rc { - + /** Generator for the primitives of a block header */ Gen> blockHeaderPrimitives = gen::tuple(gen::arbitrary(), gen::arbitrary(), gen::arbitrary(), gen::arbitrary(), gen::arbitrary(), gen::arbitrary()); /** Generator for a new CBlockHeader */ template<> - struct Arbitrary { - static Gen arbitrary() { - return gen::map(blockHeaderPrimitives, [](std::tuple headerPrimitives) { + struct Arbitrary { + static Gen arbitrary() { + return gen::map(blockHeaderPrimitives, [](std::tuple headerPrimitives) { int32_t nVersion; uint256 hashPrevBlock; uint256 hashMerkleRoot; @@ -31,5 +35,18 @@ namespace rc { return header; }); }; - }; + }; + + /** Generator for a new CBlock */ + template<> + struct Arbitrary { + static Gen arbitrary() { + return gen::map(gen::arbitrary>(), [](std::vector txRefs) { + CBlock block; + block.vtx = txRefs; + return block; + }); + } + }; } +#endif diff --git a/src/test/gen/crypto_gen.h b/src/test/gen/crypto_gen.h index 4bf7d53ac91..789ba4fffb3 100644 --- a/src/test/gen/crypto_gen.h +++ b/src/test/gen/crypto_gen.h @@ -1,3 +1,6 @@ +#ifndef BITCOIN_TEST_GEN_CRYPTO_GEN_H +#define BITCOIN_TEST_GEN_CRYPTO_GEN_H + #include "key.h" #include "random.h" #include "uint256.h" @@ -48,3 +51,4 @@ namespace rc { }; }; } +#endif diff --git a/src/test/gen/script_gen.h b/src/test/gen/script_gen.h index a00128bbb70..e3fce6aedf5 100644 --- a/src/test/gen/script_gen.h +++ b/src/test/gen/script_gen.h @@ -1,3 +1,6 @@ +#ifndef BITCOIN_TEST_GEN_SCRIPT_GEN_H +#define BITCOIN_TEST_GEN_SCRIPT_GEN_H + #include #include #include "test/gen/crypto_gen.h" @@ -13,3 +16,4 @@ namespace rc { }; }; } +#endif diff --git a/src/test/gen/transaction_gen.h b/src/test/gen/transaction_gen.h index 6586f85f219..58e646c3016 100644 --- a/src/test/gen/transaction_gen.h +++ b/src/test/gen/transaction_gen.h @@ -1,3 +1,6 @@ +#ifndef BITCOIN_TEST_GEN_TRANSACTION_GEN_H +#define BITCOIN_TEST_GEN_TRANSACTION_GEN_H + #include #include #include "primitives/transaction.h" @@ -5,7 +8,7 @@ #include "script/script.h" #include "amount.h" namespace rc { - + /** Generator for a COutPoint */ template<> struct Arbitrary { static Gen arbitrary() { @@ -18,7 +21,7 @@ namespace rc { }; }; - + /** Generator for a CTxIn */ template<> struct Arbitrary { static Gen arbitrary() { @@ -31,7 +34,8 @@ namespace rc { }); }; }; - + + /** Generator for a CAmount */ template<> struct Arbitrary { static Gen arbitrary() { @@ -41,6 +45,7 @@ namespace rc { }; }; + /** Generator for CTxOut */ template<> struct Arbitrary { static Gen arbitrary() { @@ -53,7 +58,7 @@ namespace rc { }; }; - + /** Generator for a CTransaction */ template<> struct Arbitrary { static Gen arbitrary() { @@ -74,4 +79,15 @@ namespace rc { }); }; }; + + /** Generator for a CTransactionRef */ + template<> + struct Arbitrary { + static Gen arbitrary() { + return gen::map(gen::arbitrary(), [](CTransaction tx) { + return MakeTransactionRef(tx); + }); + }; + }; } +#endif From 867d8de4337429b8cec64f2616e52a884da5d867 Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Wed, 18 Jan 2017 23:14:56 -0600 Subject: [PATCH 09/11] Adding Generators outside of the rc name space, adding generator for LoadedBloomFilter --- src/test/gen/block_gen.h | 13 ++++++++----- src/test/gen/bloom_gen.h | 47 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/test/gen/block_gen.h b/src/test/gen/block_gen.h index dc0366a683d..f70a52522f0 100644 --- a/src/test/gen/block_gen.h +++ b/src/test/gen/block_gen.h @@ -7,17 +7,20 @@ #include "uint256.h" #include "test/gen/crypto_gen.h" #include "test/gen/transaction_gen.h" -namespace rc { /** Generator for the primitives of a block header */ - Gen> blockHeaderPrimitives = gen::tuple(gen::arbitrary(), - gen::arbitrary(), gen::arbitrary(), - gen::arbitrary(), gen::arbitrary(), gen::arbitrary()); +rc::Gen> blockHeaderPrimitives() { + return rc::gen::tuple(rc::gen::arbitrary(), + rc::gen::arbitrary(), rc::gen::arbitrary(), + rc::gen::arbitrary(), rc::gen::arbitrary(), rc::gen::arbitrary()); +} + +namespace rc { /** Generator for a new CBlockHeader */ template<> struct Arbitrary { static Gen arbitrary() { - return gen::map(blockHeaderPrimitives, [](std::tuple headerPrimitives) { + return gen::map(blockHeaderPrimitives(), [](std::tuple headerPrimitives) { int32_t nVersion; uint256 hashPrevBlock; uint256 hashMerkleRoot; diff --git a/src/test/gen/bloom_gen.h b/src/test/gen/bloom_gen.h index 35f9062e747..eea071b1a42 100644 --- a/src/test/gen/bloom_gen.h +++ b/src/test/gen/bloom_gen.h @@ -1,23 +1,33 @@ +#ifndef BITCOIN_TEST_GEN_BLOOM_GEN_H +#define BITCOIN_TEST_GEN_BLOOM_GEN_H #include #include #include -#include "bloom.h" +#include "bloom.h" +#include "merkleblock.h" +#include "test/gen/transaction_gen.h" +#include "test/gen/crypto_gen.h" + +/** Generates a double between 0,1 exclusive */ +rc::Gen BetweenZeroAndOne() { + return rc::gen::suchThat([](double x) { + return fmod(x,1) != 0; + }); +} +/** Generates the C++ primitives used to create a bloom filter */ +rc::Gen> BloomFilterPrimitives() { + return rc::gen::tuple(rc::gen::inRange(1,100), + BetweenZeroAndOne(),rc::gen::arbitrary(), + rc::gen::inRange(0,3)); +} + namespace rc { - /** Generates a double between 0,1 exclusive */ - Gen betweenZeroAndOne = gen::suchThat([](double x) { - return fmod(x,1) != 0; - }); - /** Generates the C++ primitives used to create a bloom filter */ - Gen> bloomFilterPrimitives = gen::tuple(gen::inRange(1,100), - betweenZeroAndOne, - gen::arbitrary(), - gen::inRange(0,3)); /** Generator for a new CBloomFilter*/ template<> struct Arbitrary { static Gen arbitrary() { - return gen::map(bloomFilterPrimitives, [](std::tuple filterPrimitives) { + return gen::map(BloomFilterPrimitives(), [](std::tuple filterPrimitives) { unsigned int numElements; double fpRate; unsigned int nTweakIn; @@ -28,3 +38,18 @@ namespace rc { }; }; } + +/** Returns a bloom filter loaded with the given uint256s */ +rc::Gen>> LoadedBloomFilter() { + return rc::gen::map(rc::gen::tuple(rc::gen::arbitrary(),rc::gen::arbitrary>()), + [](std::tuple> primitives) { + std::vector hashes; + CBloomFilter bloomFilter; + std::tie(bloomFilter,hashes) = primitives; + for(unsigned int i = 0; i < hashes.size(); i++) { + bloomFilter.insert(hashes[i]); + } + return std::make_tuple(bloomFilter,hashes); + }); +} +#endif From 607725bbfaa15be7fe7e0a0521d6c0a042d56ae8 Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Sat, 21 Jan 2017 17:38:50 -0600 Subject: [PATCH 10/11] Adding merkleblock_gen.h, merkleblock serialization symmetry test --- src/Makefile.test.include | 6 ++++-- src/test/gen/block_gen.h | 7 ++++--- src/test/gen/bloom_gen.h | 14 ++++++++++++-- src/test/gen/merkleblock_gen.h | 29 +++++++++++++++++++++++++++++ src/test/merkleblock_properties.cpp | 24 ++++++++++++++++++++++++ 5 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 src/test/gen/merkleblock_gen.h create mode 100644 src/test/merkleblock_properties.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 8ac846d8142..06c97774f81 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -33,7 +33,6 @@ BITCOIN_TESTS =\ test/base64_tests.cpp \ test/bip32_tests.cpp \ test/blockencodings_tests.cpp \ - test/block_properties.cpp \ test/bloom_tests.cpp \ test/bloom_properties.cpp \ test/bswap_tests.cpp \ @@ -94,8 +93,11 @@ BITCOIN_TESTS =\ test/util_tests.cpp \ test/gen/crypto_gen.h \ test/gen/bloom_gen.h \ - test/gen/block_gen.h \ test/gen/script_gen.h \ + test/gen/block_gen.h \ + test/gen/merkleblock_gen.h \ + test/block_properties.cpp \ + test/merkleblock_properties.cpp \ test/gen/transaction_gen.h if ENABLE_WALLET diff --git a/src/test/gen/block_gen.h b/src/test/gen/block_gen.h index f70a52522f0..e1e04e2e6fb 100644 --- a/src/test/gen/block_gen.h +++ b/src/test/gen/block_gen.h @@ -7,8 +7,9 @@ #include "uint256.h" #include "test/gen/crypto_gen.h" #include "test/gen/transaction_gen.h" - /** Generator for the primitives of a block header */ -rc::Gen> blockHeaderPrimitives() { + +/** Generator for the primitives of a block header */ +inline rc::Gen> blockHeaderPrimitives() { return rc::gen::tuple(rc::gen::arbitrary(), rc::gen::arbitrary(), rc::gen::arbitrary(), rc::gen::arbitrary(), rc::gen::arbitrary(), rc::gen::arbitrary()); @@ -44,7 +45,7 @@ namespace rc { template<> struct Arbitrary { static Gen arbitrary() { - return gen::map(gen::arbitrary>(), [](std::vector txRefs) { + return gen::map(gen::nonEmpty>(), [](std::vector txRefs) { CBlock block; block.vtx = txRefs; return block; diff --git a/src/test/gen/bloom_gen.h b/src/test/gen/bloom_gen.h index eea071b1a42..076a758974e 100644 --- a/src/test/gen/bloom_gen.h +++ b/src/test/gen/bloom_gen.h @@ -9,13 +9,13 @@ #include "test/gen/crypto_gen.h" /** Generates a double between 0,1 exclusive */ -rc::Gen BetweenZeroAndOne() { +inline rc::Gen BetweenZeroAndOne() { return rc::gen::suchThat([](double x) { return fmod(x,1) != 0; }); } /** Generates the C++ primitives used to create a bloom filter */ -rc::Gen> BloomFilterPrimitives() { +inline rc::Gen> BloomFilterPrimitives() { return rc::gen::tuple(rc::gen::inRange(1,100), BetweenZeroAndOne(),rc::gen::arbitrary(), rc::gen::inRange(0,3)); @@ -49,6 +49,16 @@ rc::Gen>> LoadedBloomFilter() { for(unsigned int i = 0; i < hashes.size(); i++) { bloomFilter.insert(hashes[i]); } + return std::make_tuple(bloomFilter,hashes); + }); +} + +/** Loads an arbitrary bloom filter with the given hashes */ +rc::Gen>> LoadBloomFilter(std::vector& hashes) { + return rc::gen::map(rc::gen::arbitrary(),[&hashes](CBloomFilter bloomFilter) { + for(unsigned int i = 0; i < hashes.size(); i++) { + bloomFilter.insert(hashes[i]); + } return std::make_tuple(bloomFilter,hashes); }); } diff --git a/src/test/gen/merkleblock_gen.h b/src/test/gen/merkleblock_gen.h new file mode 100644 index 00000000000..d54b0466b27 --- /dev/null +++ b/src/test/gen/merkleblock_gen.h @@ -0,0 +1,29 @@ +#ifndef BITCOIN_TEST_GEN_MERKLEBLOCK_GEN_H +#define BITCOIN_TEST_GEN_MERKLEBLOCK_GEN_H + +#include +#include + +#include "merkleblock.h" +#include "test/gen/block_gen.h" +namespace rc { + + template<> + struct Arbitrary { + static Gen arbitrary() { + return gen::map(gen::arbitrary(), [](CBlock block) { + std::set hashes; + for(unsigned int i = 0; i < block.vtx.size(); i++) { + //pretty naive to include every other txid in the merkle block + //but this will work for now. + if (i % 2 == 0) { + hashes.insert(block.vtx[i]->GetHash()); + } + } + return CMerkleBlock(block,hashes); + }); + }; + }; + +} +#endif diff --git a/src/test/merkleblock_properties.cpp b/src/test/merkleblock_properties.cpp new file mode 100644 index 00000000000..9461a10478f --- /dev/null +++ b/src/test/merkleblock_properties.cpp @@ -0,0 +1,24 @@ +#include "test/test_bitcoin.h" + +#include +#include +#include +#include + +#include "merkleblock.h" +#include "test/gen/merkleblock_gen.h" + +BOOST_FIXTURE_TEST_SUITE(merkleblock_properties, BasicTestingSetup) + +RC_BOOST_PROP(merkleblock_serialization_symmetry, (CMerkleBlock merkleBlock)) { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << merkleBlock; + CMerkleBlock merkleBlock2; + ss >> merkleBlock2; + CDataStream ss1(SER_NETWORK, PROTOCOL_VERSION); + ss << merkleBlock; + ss1 << merkleBlock2; + RC_ASSERT(ss.str() == ss1.str()); +} + +BOOST_AUTO_TEST_SUITE_END() From 31a1ca511880f2d921e5e96ba7f53e62add125b7 Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Sat, 11 Mar 2017 13:04:19 -0600 Subject: [PATCH 11/11] Adding merkle_block properties Committing to try and debug mem leak Removing comments, rebasing to master Only adding rapidcheck dependency if tests are enabled Refactoring inclues in generator files, reordering files in Makefile.test.include Undoing change in merkleblock.cpp --- configure.ac | 13 ++++--- src/Makefile.test.include | 15 ++++---- src/test/bloom_properties.cpp | 7 ---- src/test/gen/block_gen.h | 9 ++--- src/test/gen/bloom_gen.h | 50 ++++++++------------------- src/test/gen/crypto_gen.h | 13 ++++--- src/test/gen/merkleblock_gen.h | 68 ++++++++++++++++++++++++++++++++++--- src/test/gen/script_gen.h | 9 ++--- src/test/gen/transaction_gen.h | 21 +++++++----- src/test/merkleblock_properties.cpp | 35 ++++++++++++++++++- src/test/transaction_properties.cpp | 5 +-- 11 files changed, 159 insertions(+), 86 deletions(-) diff --git a/configure.ac b/configure.ac index 61fd9ba288d..d7b92fcdb95 100644 --- a/configure.ac +++ b/configure.ac @@ -654,11 +654,6 @@ if test x$use_upnp != xno; then ) fi -dnl check for rapidcheck -AC_CHECK_HEADERS( - [rapidcheck.h], - [AC_CHECK_LIB([rapidcheck], [main],[], [])], - []) BITCOIN_QT_INIT @@ -747,6 +742,14 @@ if test x$use_tests = xyes; then fi fi +if test x$use_tests = xyes; then + dnl check for rapidcheck + AC_CHECK_HEADERS( + [rapidcheck.h], + [AC_CHECK_LIB([rapidcheck], [main],[], [])], + []) +fi + if test x$use_boost = xyes; then BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB $BOOST_PROGRAM_OPTIONS_LIB $BOOST_THREAD_LIB $BOOST_CHRONO_LIB" diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 06c97774f81..9b22313ee02 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -34,11 +34,8 @@ BITCOIN_TESTS =\ test/bip32_tests.cpp \ test/blockencodings_tests.cpp \ test/bloom_tests.cpp \ - test/bloom_properties.cpp \ test/bswap_tests.cpp \ test/checkqueue_tests.cpp \ - test/bloom_properties.cpp \ - test/Checkpoints_tests.cpp \ test/coins_tests.cpp \ test/compress_tests.cpp \ test/crypto_tests.cpp \ @@ -47,7 +44,6 @@ BITCOIN_TESTS =\ test/getarg_tests.cpp \ test/hash_tests.cpp \ test/key_tests.cpp \ - test/key_properties.cpp \ test/limitedmap_tests.cpp \ test/dbwrapper_tests.cpp \ test/main_tests.cpp \ @@ -68,7 +64,6 @@ BITCOIN_TESTS =\ test/sanity_tests.cpp \ test/scheduler_tests.cpp \ test/script_P2SH_tests.cpp \ - test/script_properties.cpp \ test/script_tests.cpp \ test/scriptnum_tests.cpp \ test/serialize_tests.cpp \ @@ -85,20 +80,24 @@ BITCOIN_TESTS =\ test/timedata_tests.cpp \ test/torcontrol_tests.cpp \ test/transaction_tests.cpp \ - test/transaction_properties.cpp \ test/txvalidationcache_tests.cpp \ test/versionbits_tests.cpp \ test/uint256_tests.cpp \ test/univalue_tests.cpp \ test/util_tests.cpp \ test/gen/crypto_gen.h \ - test/gen/bloom_gen.h \ test/gen/script_gen.h \ + test/gen/transaction_gen.h \ test/gen/block_gen.h \ test/gen/merkleblock_gen.h \ + test/gen/bloom_gen.cpp \ + test/gen/bloom_gen.h \ + test/key_properties.cpp \ + test/script_properties.cpp \ test/block_properties.cpp \ test/merkleblock_properties.cpp \ - test/gen/transaction_gen.h + test/bloom_properties.cpp \ + test/transaction_properties.cpp if ENABLE_WALLET BITCOIN_TESTS += \ diff --git a/src/test/bloom_properties.cpp b/src/test/bloom_properties.cpp index 37ef8e5f969..dd6aa6455e7 100644 --- a/src/test/bloom_properties.cpp +++ b/src/test/bloom_properties.cpp @@ -3,14 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "key.h" -//#include "base58.h" -//#include "script/script.h" -//#include "uint256.h" -//#include "util.h" -//#include "utilstrencodings.h" #include "test/test_bitcoin.h" -//#include -//#include #include #include diff --git a/src/test/gen/block_gen.h b/src/test/gen/block_gen.h index e1e04e2e6fb..4d5285ff616 100644 --- a/src/test/gen/block_gen.h +++ b/src/test/gen/block_gen.h @@ -1,12 +1,13 @@ #ifndef BITCOIN_TEST_GEN_BLOCK_GEN_H #define BITCOIN_TEST_GEN_BLOCK_GEN_H -#include -#include -#include "primitives/block.h" -#include "uint256.h" #include "test/gen/crypto_gen.h" #include "test/gen/transaction_gen.h" +#include "uint256.h" +#include "primitives/block.h" + +#include +#include /** Generator for the primitives of a block header */ inline rc::Gen> blockHeaderPrimitives() { diff --git a/src/test/gen/bloom_gen.h b/src/test/gen/bloom_gen.h index 076a758974e..78ac3cae7dd 100644 --- a/src/test/gen/bloom_gen.h +++ b/src/test/gen/bloom_gen.h @@ -1,28 +1,22 @@ #ifndef BITCOIN_TEST_GEN_BLOOM_GEN_H #define BITCOIN_TEST_GEN_BLOOM_GEN_H -#include -#include -#include + #include "bloom.h" #include "merkleblock.h" -#include "test/gen/transaction_gen.h" -#include "test/gen/crypto_gen.h" + +#include + +#include +#include /** Generates a double between 0,1 exclusive */ -inline rc::Gen BetweenZeroAndOne() { - return rc::gen::suchThat([](double x) { - return fmod(x,1) != 0; - }); -} -/** Generates the C++ primitives used to create a bloom filter */ -inline rc::Gen> BloomFilterPrimitives() { - return rc::gen::tuple(rc::gen::inRange(1,100), - BetweenZeroAndOne(),rc::gen::arbitrary(), - rc::gen::inRange(0,3)); -} +rc::Gen BetweenZeroAndOne(); + +rc::Gen> BloomFilterPrimitives(); namespace rc { + /** Generator for a new CBloomFilter*/ template<> struct Arbitrary { @@ -40,26 +34,10 @@ namespace rc { } /** Returns a bloom filter loaded with the given uint256s */ -rc::Gen>> LoadedBloomFilter() { - return rc::gen::map(rc::gen::tuple(rc::gen::arbitrary(),rc::gen::arbitrary>()), - [](std::tuple> primitives) { - std::vector hashes; - CBloomFilter bloomFilter; - std::tie(bloomFilter,hashes) = primitives; - for(unsigned int i = 0; i < hashes.size(); i++) { - bloomFilter.insert(hashes[i]); - } - return std::make_tuple(bloomFilter,hashes); - }); -} +rc::Gen>> LoadedBloomFilter(); /** Loads an arbitrary bloom filter with the given hashes */ -rc::Gen>> LoadBloomFilter(std::vector& hashes) { - return rc::gen::map(rc::gen::arbitrary(),[&hashes](CBloomFilter bloomFilter) { - for(unsigned int i = 0; i < hashes.size(); i++) { - bloomFilter.insert(hashes[i]); - } - return std::make_tuple(bloomFilter,hashes); - }); -} +rc::Gen>> LoadBloomFilter(std::vector& hashes); + + #endif diff --git a/src/test/gen/crypto_gen.h b/src/test/gen/crypto_gen.h index 789ba4fffb3..9e40ee5c3b7 100644 --- a/src/test/gen/crypto_gen.h +++ b/src/test/gen/crypto_gen.h @@ -6,14 +6,15 @@ #include "uint256.h" #include #include - +#include +#include namespace rc { /** Generator for a new CKey */ template<> struct Arbitrary { static Gen arbitrary() { - return gen::map([](int x) { + return rc::gen::map([](int x) { CKey key; key.MakeNewKey(true); return key; @@ -25,7 +26,7 @@ namespace rc { template<> struct Arbitrary { static Gen arbitrary() { - return gen::map([](CKey key) { + return gen::map(gen::arbitrary(), [](CKey key) { return key.GetPrivKey(); }); }; @@ -35,7 +36,7 @@ namespace rc { template<> struct Arbitrary { static Gen arbitrary() { - return gen::map([](CKey key) { + return gen::map(gen::arbitrary(), [](CKey key) { return key.GetPubKey(); }); }; @@ -45,9 +46,7 @@ namespace rc { template<> struct Arbitrary { static Gen arbitrary() { - return gen::map([](int x) { - return GetRandHash(); - }); + return rc::gen::just(GetRandHash()); }; }; } diff --git a/src/test/gen/merkleblock_gen.h b/src/test/gen/merkleblock_gen.h index d54b0466b27..18db61d4651 100644 --- a/src/test/gen/merkleblock_gen.h +++ b/src/test/gen/merkleblock_gen.h @@ -6,11 +6,13 @@ #include "merkleblock.h" #include "test/gen/block_gen.h" -namespace rc { +#include +namespace rc { + /** Returns a CMerkleblock with the hashes that match inside of the CPartialMerkleTree */ template<> - struct Arbitrary { - static Gen arbitrary() { + struct Arbitrary>> { + static Gen>> arbitrary() { return gen::map(gen::arbitrary(), [](CBlock block) { std::set hashes; for(unsigned int i = 0; i < block.vtx.size(); i++) { @@ -20,10 +22,68 @@ namespace rc { hashes.insert(block.vtx[i]->GetHash()); } } - return CMerkleBlock(block,hashes); + return std::make_pair(CMerkleBlock(block,hashes),hashes); + }); + }; + }; + + + Gen> betweenZeroAnd100 = gen::suchThat>([](std::vector hashes) { + return hashes.size() <= 100; + }); + + /** Returns an arbitrary CMerkleBlock */ + template<> + struct Arbitrary { + static Gen arbitrary() { + return gen::map(gen::arbitrary>>(), + [](std::pair> merkleBlockWithTxIds) { + CMerkleBlock merkleBlock = merkleBlockWithTxIds.first; + std::set insertedHashes = merkleBlockWithTxIds.second; + return merkleBlock; + }); + }; + }; + + + + /** Generates a CPartialMerkleTree and returns the PartialMerkleTree along + * with the txids that should be matched inside of it */ + template<> + struct Arbitrary>> { + static Gen>> arbitrary() { + return gen::map(gen::arbitrary>(), [](std::vector txids) { + //note this use of 'gen::nonEmpty' above, if we have an empty vector of txids + //we will get a memory access violation when calling the CPartialMerkleTree + //constructor below. On one hand we shouldn't every have CPartialMerkleTree + //with no txids, but on the other hand, it seems we should call + //CPartialMerkleTree() inside of CPartialMerkleTree(txids,matches) + //if we have zero txids. + //Some one who knows more than me will have to elaborate if the memory access violation + //is a desirable failure mode or not... + std::vector matches; + std::vector matchedTxs; + for(unsigned int i = 0; i < txids.size(); i++) { + //pretty naive to include every other txid in the merkle block + //but this will work for now. + matches.push_back(i % 2 == 1); + if (i % 2 == 1) { + matchedTxs.push_back(txids[i]); + } + } + return std::make_pair(CPartialMerkleTree(txids,matches),matchedTxs); }); }; }; + template<> + struct Arbitrary { + static Gen arbitrary() { + return gen::map(gen::arbitrary>>(), + [](std::pair> p) { + return p.first; + }); + }; + }; } #endif diff --git a/src/test/gen/script_gen.h b/src/test/gen/script_gen.h index e3fce6aedf5..af207aadbd3 100644 --- a/src/test/gen/script_gen.h +++ b/src/test/gen/script_gen.h @@ -1,12 +1,13 @@ #ifndef BITCOIN_TEST_GEN_SCRIPT_GEN_H #define BITCOIN_TEST_GEN_SCRIPT_GEN_H +#include "script/script.h" #include #include -#include "test/gen/crypto_gen.h" -#include "script/script.h" - -namespace rc { +#include +#include +namespace rc { + template<> struct Arbitrary { static Gen arbitrary() { diff --git a/src/test/gen/transaction_gen.h b/src/test/gen/transaction_gen.h index 58e646c3016..2450abfc71c 100644 --- a/src/test/gen/transaction_gen.h +++ b/src/test/gen/transaction_gen.h @@ -1,23 +1,28 @@ #ifndef BITCOIN_TEST_GEN_TRANSACTION_GEN_H #define BITCOIN_TEST_GEN_TRANSACTION_GEN_H -#include -#include -#include "primitives/transaction.h" +#include "test/gen/crypto_gen.h" #include "test/gen/script_gen.h" + #include "script/script.h" +#include "primitives/transaction.h" #include "amount.h" + +#include +#include +#include + namespace rc { /** Generator for a COutPoint */ template<> struct Arbitrary { static Gen arbitrary() { return gen::map(gen::tuple(gen::arbitrary(), gen::arbitrary()), [](std::tuple outPointPrimitives) { - uint32_t nIn; - uint256 nHashIn; - std::tie(nHashIn, nIn) = outPointPrimitives; - return COutPoint(nHashIn, nIn); - }); + uint32_t nIn; + uint256 nHashIn; + std::tie(nHashIn, nIn) = outPointPrimitives; + return COutPoint(nHashIn, nIn); + }); }; }; diff --git a/src/test/merkleblock_properties.cpp b/src/test/merkleblock_properties.cpp index 9461a10478f..7f9b326a912 100644 --- a/src/test/merkleblock_properties.cpp +++ b/src/test/merkleblock_properties.cpp @@ -8,6 +8,7 @@ #include "merkleblock.h" #include "test/gen/merkleblock_gen.h" +#include BOOST_FIXTURE_TEST_SUITE(merkleblock_properties, BasicTestingSetup) RC_BOOST_PROP(merkleblock_serialization_symmetry, (CMerkleBlock merkleBlock)) { @@ -19,6 +20,38 @@ RC_BOOST_PROP(merkleblock_serialization_symmetry, (CMerkleBlock merkleBlock)) { ss << merkleBlock; ss1 << merkleBlock2; RC_ASSERT(ss.str() == ss1.str()); -} +} + +/** Should find all txids we inserted in the merkle block */ +RC_BOOST_PROP(merkle_block_match_symmetry, (std::pair> t)) { + CMerkleBlock& merkleBlock = t.first; + std::set& insertedHashes = t.second; + for (unsigned int i = 0; i < merkleBlock.vMatchedTxn.size(); i++) { + const auto& h = merkleBlock.vMatchedTxn[i].second; + RC_ASSERT(insertedHashes.find(h) != insertedHashes.end()); + } +} + +RC_BOOST_PROP(partialmerkletree_serialization_symmetry, (CPartialMerkleTree tree)) { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << tree; + CPartialMerkleTree tree2; + ss >> tree2; + CDataStream ss1(SER_NETWORK, PROTOCOL_VERSION); + ss << tree; + ss1 << tree2; + RC_ASSERT(ss.str() == ss1.str()); +} + + +/** Should find all txids we inserted in the PartialMerkleTree */ +RC_BOOST_PROP(partialmerkletree_extract_matches_symmetry, (std::pair> p)) { + CPartialMerkleTree tree = p.first; + std::vector expectedMatches = p.second; + std::vector matches; + std::vector indices; + tree.ExtractMatches(matches,indices); + RC_ASSERT(matches == expectedMatches); +} BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/transaction_properties.cpp b/src/test/transaction_properties.cpp index 818415050e9..ffab91b63f0 100644 --- a/src/test/transaction_properties.cpp +++ b/src/test/transaction_properties.cpp @@ -1,5 +1,7 @@ -#include "key.h" +#include "test/gen/transaction_gen.h" + +#include "key.h" #include "base58.h" #include "script/script.h" #include "uint256.h" @@ -14,7 +16,6 @@ #include #include #include -#include "test/gen/transaction_gen.h" BOOST_FIXTURE_TEST_SUITE(transaction_properties, BasicTestingSetup)