From 53a61258e184849cef519929bbbebc75f0e7ea4b Mon Sep 17 00:00:00 2001 From: Anthony Fieroni Date: Wed, 9 Oct 2019 18:09:30 +0300 Subject: [PATCH] Introduce libclaimtrie Signed-off-by: Anthony Fieroni --- src/Makefile.am | 30 +- src/Makefile.bench.include | 2 +- src/Makefile.qt.include | 2 +- src/Makefile.qttest.include | 2 +- src/Makefile.test.include | 4 +- src/chainparams.cpp | 6 - src/claimscriptop.cpp | 4 +- src/claimscriptop.h | 2 +- src/claimtrie.h | 491 ------------------ src/claimtrie/data.cpp | 84 +++ src/claimtrie/data.h | 131 +++++ .../forks.cpp} | 168 +++--- src/claimtrie/forks.h | 87 ++++ src/claimtrie/hash.cpp | 12 + src/claimtrie/hash.h | 29 ++ src/claimtrie/log.cpp | 23 + src/claimtrie/log.h | 41 ++ .../sqlite/hdr/sqlite_modern_cpp.h | 2 +- .../sqlite/hdr/sqlite_modern_cpp/errors.h | 4 +- .../hdr/sqlite_modern_cpp/lists/error_codes.h | 0 .../sqlite/hdr/sqlite_modern_cpp/log.h | 0 .../sqlite/hdr/sqlite_modern_cpp/sqlcipher.h | 0 .../hdr/sqlite_modern_cpp/type_wrapper.h | 4 +- .../utility/function_traits.h | 2 +- .../utility/uncaught_exceptions.h | 0 .../sqlite_modern_cpp/utility/utf16_utf8.h | 0 src/{ => claimtrie}/sqlite/shell.c | 0 src/{ => claimtrie}/sqlite/sqlite3.c | 0 src/{ => claimtrie}/sqlite/sqlite3.h | 0 src/{ => claimtrie}/sqlite/sqlite3ext.h | 0 src/{claimtrie.cpp => claimtrie/trie.cpp} | 269 +++++----- src/claimtrie/trie.h | 207 ++++++++ src/claimtrie/txoutpoint.cpp | 42 ++ src/claimtrie/txoutpoint.h | 37 ++ src/claimtrie/uints.cpp | 155 ++++++ src/claimtrie/uints.h | 59 +++ src/claimtrie_serial.h | 105 ++++ src/consensus/params.h | 3 - src/init.cpp | 25 +- src/lbry.cpp | 2 - src/lbry.h | 1 - src/logging.h | 5 +- src/miner.cpp | 3 +- src/nameclaim.cpp | 63 +-- src/primitives/transaction.h | 7 + src/rpc/claimtrie.cpp | 26 +- src/serialize.h | 1 + src/test/claimtriebranching_tests.cpp | 12 +- src/test/claimtriecache_tests.cpp | 61 +-- src/test/claimtrieexpirationfork_tests.cpp | 13 +- src/test/claimtriefixture.cpp | 22 +- src/test/claimtriefixture.h | 2 +- src/test/claimtriehashfork_tests.cpp | 27 +- src/test/claimtrienormalization_tests.cpp | 4 +- src/test/claimtrierpc_tests.cpp | 8 +- src/test/test_bitcoin.cpp | 42 +- src/test/test_bitcoin.h | 8 +- src/uint256.h | 20 +- src/undo.h | 2 +- src/validation.h | 2 +- src/wallet/rpcwallet.cpp | 3 +- 61 files changed, 1461 insertions(+), 905 deletions(-) delete mode 100644 src/claimtrie.h create mode 100644 src/claimtrie/data.cpp create mode 100644 src/claimtrie/data.h rename src/{claimtrieforks.cpp => claimtrie/forks.cpp} (73%) create mode 100644 src/claimtrie/forks.h create mode 100644 src/claimtrie/hash.cpp create mode 100644 src/claimtrie/hash.h create mode 100644 src/claimtrie/log.cpp create mode 100644 src/claimtrie/log.h rename src/{ => claimtrie}/sqlite/hdr/sqlite_modern_cpp.h (99%) rename src/{ => claimtrie}/sqlite/hdr/sqlite_modern_cpp/errors.h (99%) rename src/{ => claimtrie}/sqlite/hdr/sqlite_modern_cpp/lists/error_codes.h (100%) rename src/{ => claimtrie}/sqlite/hdr/sqlite_modern_cpp/log.h (100%) rename src/{ => claimtrie}/sqlite/hdr/sqlite_modern_cpp/sqlcipher.h (100%) rename src/{ => claimtrie}/sqlite/hdr/sqlite_modern_cpp/type_wrapper.h (99%) rename src/{ => claimtrie}/sqlite/hdr/sqlite_modern_cpp/utility/function_traits.h (98%) rename src/{ => claimtrie}/sqlite/hdr/sqlite_modern_cpp/utility/uncaught_exceptions.h (100%) rename src/{ => claimtrie}/sqlite/hdr/sqlite_modern_cpp/utility/utf16_utf8.h (100%) rename src/{ => claimtrie}/sqlite/shell.c (100%) rename src/{ => claimtrie}/sqlite/sqlite3.c (100%) rename src/{ => claimtrie}/sqlite/sqlite3.h (100%) rename src/{ => claimtrie}/sqlite/sqlite3ext.h (100%) rename src/{claimtrie.cpp => claimtrie/trie.cpp} (89%) create mode 100644 src/claimtrie/trie.h create mode 100644 src/claimtrie/txoutpoint.cpp create mode 100644 src/claimtrie/txoutpoint.h create mode 100644 src/claimtrie/uints.cpp create mode 100644 src/claimtrie/uints.h create mode 100644 src/claimtrie_serial.h diff --git a/src/Makefile.am b/src/Makefile.am index c77cc3375..d81340626 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,6 +29,7 @@ LIBBITCOIN_COMMON=libbitcoin_common.a LIBBITCOIN_CONSENSUS=libbitcoin_consensus.a LIBBITCOIN_CLI=libbitcoin_cli.a LIBBITCOIN_UTIL=libbitcoin_util.a +LIBCLAIMTRIE=claimtrie/libclaimtrie.a LIBBITCOIN_CRYPTO_BASE=crypto/libbitcoin_crypto_base.a LIBBITCOINQT=qt/libbitcoinqt.a LIBSECP256K1=secp256k1/libsecp256k1.la @@ -63,6 +64,7 @@ $(LIBSECP256K1): $(wildcard secp256k1/src/*.h) $(wildcard secp256k1/src/*.c) $(w # Make is not made aware of per-object dependencies to avoid limiting building parallelization # But to build the less dependent modules first, we manually select their order here: EXTRA_LIBRARIES += \ + $(LIBCLAIMTRIE) \ $(LIBBITCOIN_CRYPTO) \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_COMMON) \ @@ -103,7 +105,7 @@ BITCOIN_CORE_H = \ checkpoints.h \ checkqueue.h \ claimscriptop.h \ - claimtrie.h \ + claimtrie_serial.h \ clientversion.h \ coins.h \ compat.h \ @@ -170,8 +172,6 @@ BITCOIN_CORE_H = \ script/standard.h \ shutdown.h \ streams.h \ - sqlite/sqlite3.h \ - sqlite/hdr/sqlite_modern_cpp.h \ support/allocators/secure.h \ support/allocators/zeroafterfree.h \ support/cleanse.h \ @@ -223,7 +223,6 @@ libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h # server: shared between lbrycrdd and lbrycrd-qt libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -libbitcoin_server_a_CFLAGS = $(PIE_FLAGS) libbitcoin_server_a_SOURCES = \ addrdb.cpp \ addrman.cpp \ @@ -232,8 +231,6 @@ libbitcoin_server_a_SOURCES = \ chain.cpp \ checkpoints.cpp \ claimscriptop.cpp \ - claimtrie.cpp \ - claimtrieforks.cpp \ consensus/tx_verify.cpp \ httprpc.cpp \ httpserver.cpp \ @@ -263,7 +260,6 @@ libbitcoin_server_a_SOURCES = \ rpc/server.cpp \ rpc/util.cpp \ script/sigcache.cpp \ - sqlite/sqlite3.c \ shutdown.cpp \ timedata.cpp \ torcontrol.cpp \ @@ -415,6 +411,20 @@ libbitcoin_common_a_SOURCES = \ warnings.cpp \ $(BITCOIN_CORE_H) +# claimtrie: shared between all executables. +claimtrie_libclaimtrie_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) +claimtrie_libclaimtrie_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +claimtrie_libclaimtrie_a_CFLAGS = $(PIE_FLAGS) +claimtrie_libclaimtrie_a_SOURCES = \ + claimtrie/sqlite/sqlite3.c \ + claimtrie/data.cpp \ + claimtrie/forks.cpp \ + claimtrie/hash.cpp \ + claimtrie/log.cpp \ + claimtrie/trie.cpp \ + claimtrie/txoutpoint.cpp \ + claimtrie/uints.cpp + # util: shared between all executables. # This library *must* be included to make sure that the glibc # backward-compatibility objects and their sanity checks are linked. @@ -482,7 +492,7 @@ lbrycrdd_LDADD = \ $(LIBMEMENV) \ $(LIBSECP256K1) -lbrycrdd_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(ICU_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) +lbrycrdd_LDADD += $(BOOST_LIBS) $(LIBCLAIMTRIE) $(BOOST_LOCALE_LIB) $(BDB_LIBS) $(CRYPTO_LIBS) $(ICU_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) # lbrycrd-cli binary # lbrycrd_cli_SOURCES = bitcoin-cli.cpp @@ -500,7 +510,7 @@ lbrycrd_cli_LDADD = \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_CRYPTO) -lbrycrd_cli_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) $(ICU_LIBS) $(EVENT_LIBS) +lbrycrd_cli_LDADD += $(BOOST_LIBS) $(LIBCLAIMTRIE) $(BOOST_LOCALE_LIB) $(CRYPTO_LIBS) $(ICU_LIBS) $(EVENT_LIBS) # # bitcoin-tx binary # @@ -521,7 +531,7 @@ lbrycrd_tx_LDADD = \ $(LIBBITCOIN_CRYPTO) \ $(LIBSECP256K1) -lbrycrd_tx_LDADD += $(BOOST_LIBS) $(ICU_LIBS) $(CRYPTO_LIBS) +lbrycrd_tx_LDADD += $(BOOST_LIBS) $(LIBCLAIMTRIE) $(BOOST_LOCALE_LIB) $(ICU_LIBS) $(CRYPTO_LIBS) # # bitcoinconsensus library # diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index 0462ce04f..37120d9f7 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -55,7 +55,7 @@ if ENABLE_WALLET bench_bench_bitcoin_SOURCES += bench/coin_selection.cpp endif -bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(ICU_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) +bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(LIBCLAIMTRIE) $(BOOST_LOCALE_LIB) $(BDB_LIBS) $(CRYPTO_LIBS) $(ICU_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) bench_bench_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) CLEAN_BITCOIN_BENCH = bench/*.gcda bench/*.gcno $(GENERATED_BENCH_FILES) diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 98371539a..98455c8da 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -409,7 +409,7 @@ if ENABLE_ZMQ qt_lbrycrd_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) endif qt_lbrycrd_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \ - $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(ICU_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ + $(BOOST_LIBS) $(LIBCLAIMTRIE) $(BOOST_LOCALE_LIB) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(ICU_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) qt_lbrycrd_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) qt_lbrycrd_qt_LIBTOOLFLAGS = $(AM_LIBTOOLFLAGS) --tag CXX diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index 450e9faf7..2e98abacb 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -63,7 +63,7 @@ if ENABLE_ZMQ qt_test_test_lbrycrd_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) endif qt_test_test_lbrycrd_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) \ - $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \ + $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(LIBCLAIMTRIE) $(BOOST_LOCALE_LIB) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \ $(QR_LIBS) $(PROTOBUF_LIBS) $(ICU_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) qt_test_test_lbrycrd_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 25a6df16f..437f8df51 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -126,7 +126,7 @@ test_test_lbrycrd_LDADD += $(LIBBITCOIN_WALLET) endif test_test_lbrycrd_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) \ - $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) + $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(LIBCLAIMTRIE) $(BOOST_LOCALE_LIB) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) test_test_lbrycrd_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_test_lbrycrd_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(CRYPTO_LIBS) $(ICU_LIBS) $(MINIUPNPC_LIBS) @@ -155,7 +155,7 @@ test_test_lbrycrd_fuzzy_LDADD = \ $(LIBBITCOIN_CRYPTO_SHANI) \ $(LIBSECP256K1) -test_test_lbrycrd_fuzzy_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) $(ICU_LIBS) +test_test_lbrycrd_fuzzy_LDADD += $(BOOST_LIBS) $(LIBCLAIMTRIE) $(BOOST_LOCALE_LIB) $(CRYPTO_LIBS) $(ICU_LIBS) nodist_test_test_lbrycrd_SOURCES = $(GENERATED_TEST_FILES) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 672ee7d29..ab4c5fb98 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -143,8 +143,6 @@ public: consensus.nAllowMinDiffMinHeight = -1; consensus.nAllowMinDiffMaxHeight = -1; consensus.nNormalizedNameForkHeight = 539940; // targeting 21 March 2019 - consensus.nMinTakeoverWorkaroundHeight = 496850; - consensus.nMaxTakeoverWorkaroundHeight = 658300; // targeting 30 Oct 2019 consensus.nWitnessForkHeight = 680770; // targeting 11 Dec 2019 consensus.nAllClaimsInMerkleForkHeight = 658310; // targeting 30 Oct 2019 consensus.fPowAllowMinDifficultyBlocks = false; @@ -261,8 +259,6 @@ public: consensus.nAllowMinDiffMinHeight = 277299; consensus.nAllowMinDiffMaxHeight = 1100000; consensus.nNormalizedNameForkHeight = 993380; // targeting, 21 Feb 2019 - consensus.nMinTakeoverWorkaroundHeight = 99; - consensus.nMaxTakeoverWorkaroundHeight = 1198550; // targeting 30 Sep 2019 consensus.nWitnessForkHeight = 1198600; consensus.nAllClaimsInMerkleForkHeight = 1198560; // targeting 30 Sep 2019 consensus.fPowAllowMinDifficultyBlocks = true; @@ -368,8 +364,6 @@ public: consensus.nAllowMinDiffMinHeight = -1; consensus.nAllowMinDiffMaxHeight = -1; consensus.nNormalizedNameForkHeight = 250; // SDK depends upon this number - consensus.nMinTakeoverWorkaroundHeight = -1; - consensus.nMaxTakeoverWorkaroundHeight = -1; consensus.nWitnessForkHeight = 150; consensus.nAllClaimsInMerkleForkHeight = 350; consensus.fPowAllowMinDifficultyBlocks = false; diff --git a/src/claimscriptop.cpp b/src/claimscriptop.cpp index ff99bd711..1b5605257 100644 --- a/src/claimscriptop.cpp +++ b/src/claimscriptop.cpp @@ -39,7 +39,7 @@ bool CClaimScriptAddOp::supportClaim(CClaimTrieCache& trieCache, const std::stri { LogPrint(BCLog::CLAIMS, "+++ Support added: %s, c: %.6s, t: %.6s:%d, h: %.6d, a: %d\n", name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValue); - return trieCache.addSupport(name, point, nValue, claimId, nHeight, -1, metadata); + return trieCache.addSupport(name, point, claimId, nValue, nHeight, -1, metadata); } CClaimScriptUndoAddOp::CClaimScriptUndoAddOp(const COutPoint& point, int nHeight) : point(point), nHeight(nHeight) @@ -164,7 +164,7 @@ bool CClaimScriptUndoSpendOp::supportClaim(CClaimTrieCache& trieCache, const std { LogPrint(BCLog::CLAIMS, "+++ Undoing support spend: %s, c: %.6s, t: %.6s:%d, h: %.6d, vh: %d\n", name, claimId.GetHex(), point.hash.GetHex(), point.n, nHeight, nValidHeight); - return trieCache.addSupport(name, point, nValue, claimId, nHeight, nValidHeight, metadata); + return trieCache.addSupport(name, point, claimId, nValue, nHeight, nValidHeight, metadata); } static std::string vchToString(const std::vector& name) diff --git a/src/claimscriptop.h b/src/claimscriptop.h index b36fb2cd0..4a3f67410 100644 --- a/src/claimscriptop.h +++ b/src/claimscriptop.h @@ -6,7 +6,7 @@ #define CLAIMSCRIPTOP_H #include "amount.h" -#include "claimtrie.h" +#include "claimtrie/forks.h" #include "hash.h" #include "primitives/transaction.h" #include "script/script.h" diff --git a/src/claimtrie.h b/src/claimtrie.h deleted file mode 100644 index 076287852..000000000 --- a/src/claimtrie.h +++ /dev/null @@ -1,491 +0,0 @@ -#ifndef BITCOIN_CLAIMTRIE_H -#define BITCOIN_CLAIMTRIE_H - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -namespace sqlite -{ - inline int bind_col_in_db(sqlite3_stmt* stmt, int inx, const uint160& val) { - return sqlite3_bind_blob(stmt, inx, val.begin(), int(val.size()), SQLITE_STATIC); - } - - inline int bind_col_in_db(sqlite3_stmt* stmt, int inx, const uint256& val) { - return sqlite3_bind_blob(stmt, inx, val.begin(), int(val.size()), SQLITE_STATIC); - } - - inline void store_result_in_db(sqlite3_context* db, const uint160& val) { - sqlite3_result_blob(db, val.begin(), int(val.size()), SQLITE_TRANSIENT); // I think we need transient here but I'm not 100% sure - } - - inline void store_result_in_db(sqlite3_context* db, const uint256& val) { - sqlite3_result_blob(db, val.begin(), int(val.size()), SQLITE_TRANSIENT); - } -} - -#include - -namespace sqlite { - template<> - struct has_sqlite_type : std::true_type {}; - - template<> - struct has_sqlite_type : std::true_type {}; - - inline uint160 get_col_from_db(sqlite3_stmt* stmt, int inx, result_type) { - uint160 ret; - auto ptr = sqlite3_column_blob(stmt, inx); - if (!ptr) return ret; - int bytes = sqlite3_column_bytes(stmt, inx); - assert(bytes == ret.size()); - std::memcpy(ret.begin(), ptr, bytes); - return ret; - } - - inline uint256 get_col_from_db(sqlite3_stmt* stmt, int inx, result_type) { - uint256 ret; - auto ptr = sqlite3_column_blob(stmt, inx); - if (!ptr) return ret; - int bytes = sqlite3_column_bytes(stmt, inx); - assert(bytes == ret.size()); - std::memcpy(ret.begin(), ptr, bytes); - return ret; - } - -} - -uint256 getValueHash(const COutPoint& outPoint, int nHeightOfLastTakeover); - -struct CClaimValue -{ - COutPoint outPoint; - uint160 claimId; - CAmount nAmount = 0; - CAmount nEffectiveAmount = 0; - int nHeight = 0; - int nValidAtHeight = 0; - - CClaimValue() = default; - - CClaimValue(const COutPoint& outPoint, const uint160& claimId, CAmount nAmount, int nHeight, int nValidAtHeight) - : outPoint(outPoint), claimId(claimId), nAmount(nAmount), nEffectiveAmount(nAmount), nHeight(nHeight), nValidAtHeight(nValidAtHeight) - { - } - - CClaimValue(CClaimValue&&) = default; - CClaimValue(const CClaimValue&) = default; - CClaimValue& operator=(CClaimValue&&) = default; - CClaimValue& operator=(const CClaimValue&) = default; - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) - { - READWRITE(outPoint); - READWRITE(claimId); - READWRITE(nAmount); - READWRITE(nHeight); - READWRITE(nValidAtHeight); - } - - bool operator<(const CClaimValue& other) const - { - if (nEffectiveAmount < other.nEffectiveAmount) - return true; - if (nEffectiveAmount != other.nEffectiveAmount) - return false; - if (nHeight > other.nHeight) - return true; - if (nHeight != other.nHeight) - return false; - return outPoint != other.outPoint && !(outPoint < other.outPoint); - } - - bool operator==(const CClaimValue& other) const - { - return outPoint == other.outPoint && claimId == other.claimId && nAmount == other.nAmount && nHeight == other.nHeight && nValidAtHeight == other.nValidAtHeight; - } - - bool operator!=(const CClaimValue& other) const - { - return !(*this == other); - } -}; - -struct CSupportValue -{ - COutPoint outPoint; - uint160 supportedClaimId; - CAmount nAmount = 0; - int nHeight = 0; - int nValidAtHeight = 0; - - CSupportValue() = default; - - CSupportValue(const COutPoint& outPoint, const uint160& supportedClaimId, CAmount nAmount, int nHeight, int nValidAtHeight) - : outPoint(outPoint), supportedClaimId(supportedClaimId), nAmount(nAmount), nHeight(nHeight), nValidAtHeight(nValidAtHeight) - { - } - - CSupportValue(CSupportValue&&) = default; - CSupportValue(const CSupportValue&) = default; - CSupportValue& operator=(CSupportValue&&) = default; - CSupportValue& operator=(const CSupportValue&) = default; - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) - { - READWRITE(outPoint); - READWRITE(supportedClaimId); - READWRITE(nAmount); - READWRITE(nHeight); - READWRITE(nValidAtHeight); - } - - bool operator==(const CSupportValue& other) const - { - return outPoint == other.outPoint && supportedClaimId == other.supportedClaimId && nAmount == other.nAmount && nHeight == other.nHeight && nValidAtHeight == other.nValidAtHeight; - } - - bool operator!=(const CSupportValue& other) const - { - return !(*this == other); - } -}; - -typedef std::vector claimEntryType; -typedef std::vector supportEntryType; - -struct CNameOutPointHeightType -{ - std::string name; - COutPoint outPoint; - int nValidHeight = 0; - - CNameOutPointHeightType() = default; - - CNameOutPointHeightType(std::string name, const COutPoint& outPoint, int nValidHeight) - : name(std::move(name)), outPoint(outPoint), nValidHeight(nValidHeight) - { - } - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) - { - READWRITE(name); - READWRITE(outPoint); - READWRITE(nValidHeight); - } -}; - -struct CClaimNsupports -{ - CClaimNsupports() = default; - CClaimNsupports(CClaimNsupports&&) = default; - CClaimNsupports(const CClaimNsupports&) = default; - - CClaimNsupports& operator=(CClaimNsupports&&) = default; - CClaimNsupports& operator=(const CClaimNsupports&) = default; - - CClaimNsupports(const CClaimValue& claim, CAmount effectiveAmount, const std::vector& supports = {}) - : claim(claim), effectiveAmount(effectiveAmount), supports(supports) - { - } - - bool IsNull() const - { - return claim.claimId.IsNull(); - } - - bool operator<(const CClaimNsupports& other) const { - return claim < other.claim; - } - - CClaimValue claim; - CAmount effectiveAmount = 0; - std::vector supports; -}; - -static const CClaimNsupports invalid; - -struct CClaimSupportToName -{ - CClaimSupportToName(const std::string& name, int nLastTakeoverHeight, std::vector claimsNsupports, std::vector unmatchedSupports) - : name(name), nLastTakeoverHeight(nLastTakeoverHeight), claimsNsupports(std::move(claimsNsupports)), unmatchedSupports(std::move(unmatchedSupports)) - { - } - - const CClaimNsupports& find(const uint160& claimId) const - { - auto it = std::find_if(claimsNsupports.begin(), claimsNsupports.end(), [&claimId](const CClaimNsupports& value) { - return claimId == value.claim.claimId; - }); - return it != claimsNsupports.end() ? *it : invalid; - } - - const CClaimNsupports& find(const std::string& partialId) const - { - std::string lowered(partialId); - for (auto& c: lowered) - c = std::tolower(c); - - auto it = std::find_if(claimsNsupports.begin(), claimsNsupports.end(), [&lowered](const CClaimNsupports& value) { - return value.claim.claimId.GetHex().find(lowered) == 0; - }); - return it != claimsNsupports.end() ? *it : invalid; - } - - const std::string name; - const int nLastTakeoverHeight; - const std::vector claimsNsupports; - const std::vector unmatchedSupports; -}; - -class CClaimTrieCacheBase; -class CClaimTrie -{ - friend CClaimTrieCacheBase; - std::string dbPath; - int nNextHeight; - sqlite::database db; // keep below dbPath - -public: - const int nProportionalDelayFactor; - - CClaimTrie() = delete; - CClaimTrie(CClaimTrie&&) = delete; - CClaimTrie(const CClaimTrie&) = delete; - CClaimTrie(bool fWipe, int height, int proportionalDelayFactor = 32); - - CClaimTrie& operator=(CClaimTrie&&) = delete; - CClaimTrie& operator=(const CClaimTrie&) = delete; - - bool SyncToDisk(); - bool empty(); // for tests -}; - -struct CClaimTrieProofNode -{ - CClaimTrieProofNode(std::vector> children, bool hasValue, const uint256& valHash) - : children(std::move(children)), hasValue(hasValue), valHash(valHash) - { - } - - CClaimTrieProofNode(CClaimTrieProofNode&&) = default; - CClaimTrieProofNode(const CClaimTrieProofNode&) = default; - CClaimTrieProofNode& operator=(CClaimTrieProofNode&&) = default; - CClaimTrieProofNode& operator=(const CClaimTrieProofNode&) = default; - - std::vector> children; - bool hasValue; - uint256 valHash; -}; - -struct CClaimTrieProof -{ - CClaimTrieProof() = default; - CClaimTrieProof(CClaimTrieProof&&) = default; - CClaimTrieProof(const CClaimTrieProof&) = default; - CClaimTrieProof& operator=(CClaimTrieProof&&) = default; - CClaimTrieProof& operator=(const CClaimTrieProof&) = default; - - std::vector> pairs; - std::vector nodes; - int nHeightOfLastTakeover = 0; - bool hasValue = false; - COutPoint outPoint; -}; - -template -using queueEntryType = std::pair; - -typedef std::vector> claimUndoType; -typedef std::vector> supportUndoType; -typedef std::vector insertUndoType; -typedef std::vector>> takeoverUndoType; - -class CClaimTrieCacheBase -{ -public: - explicit CClaimTrieCacheBase(CClaimTrie* base); - virtual ~CClaimTrieCacheBase(); - - uint256 getMerkleHash(); - - bool flush(); - bool checkConsistency(); - bool ValidateTipMatches(const CBlockIndex* tip); - - bool haveClaim(const std::string& name, const COutPoint& outPoint) const; - bool haveClaimInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const; - - bool haveSupport(const std::string& name, const COutPoint& outPoint) const; - bool haveSupportInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const; - - bool addClaim(const std::string& name, const COutPoint& outPoint, const uint160& claimId, CAmount nAmount, - int nHeight, int nValidHeight = -1, const std::vector& metadata = {}); - bool addSupport(const std::string& name, const COutPoint& outPoint, CAmount nAmount, - const uint160& supportedClaimId, int nHeight, int nValidHeight = -1, const std::vector& metadata = {}); - - bool removeSupport(const COutPoint& outPoint, std::string& nodeName, int& validHeight); - bool removeClaim(const uint160& claimId, const COutPoint& outPoint, std::string& nodeName, int& validHeight); - - virtual bool incrementBlock(insertUndoType& insertUndo, - claimUndoType& expireUndo, - insertUndoType& insertSupportUndo, - supportUndoType& expireSupportUndo, - takeoverUndoType& takeovers); - - virtual bool decrementBlock(insertUndoType& insertUndo, - claimUndoType& expireUndo, - insertUndoType& insertSupportUndo, - supportUndoType& expireSupportUndo); - - virtual bool getInfoForName(const std::string& name, CClaimValue& claim, int heightOffset = 0) const; - virtual bool getProofForName(const std::string& name, const uint160& finalClaim, CClaimTrieProof& proof); - - virtual int expirationTime() const; - - virtual bool finalizeDecrement(takeoverUndoType& takeovers); - - virtual CClaimSupportToName getClaimsForName(const std::string& name) const; - virtual std::string adjustNameForValidHeight(const std::string& name, int validHeight) const; - - std::size_t getTotalNamesInTrie() const; - std::size_t getTotalClaimsInTrie() const; - CAmount getTotalValueOfClaimsInTrie(bool fControllingOnly) const; - - bool findNameForClaim(std::vector claim, CClaimValue& value, std::string& name); - void getNamesInTrie(std::function callback); - bool getLastTakeoverForName(const std::string& name, uint160& claimId, int& takeoverHeight) const; - -protected: - CClaimTrie* base; - mutable sqlite::database db; - int nNextHeight; // Height of the block that is being worked on, which is - bool transacting; - mutable std::unordered_set removalWorkaround; - - // one greater than the height of the chain's tip - - mutable sqlite::database_binder claimHashQuery, childHashQuery; - - virtual uint256 recursiveComputeMerkleHash(const std::string& name, int takeoverHeight, bool checkOnly); - supportEntryType getSupportsForName(const std::string& name) const; - - virtual int getDelayForName(const std::string& name, const uint160& claimId) const; - - bool deleteNodeIfPossible(const std::string& name, std::string& parent, int64_t& claims); - void ensureTreeStructureIsUpToDate(); - -private: - // for unit test - friend struct ClaimTrieChainFixture; - friend class CClaimTrieCacheTest; - - bool activateAllFor(insertUndoType& insertUndo, insertUndoType& insertSupportUndo, - const std::string& takeover); -}; - -class CClaimTrieCacheExpirationFork : public CClaimTrieCacheBase -{ -public: - explicit CClaimTrieCacheExpirationFork(CClaimTrie* base); - - void setExpirationTime(int time); - int expirationTime() const override; - - virtual void initializeIncrement(); - bool finalizeDecrement(takeoverUndoType& takeovers) override; - - bool incrementBlock(insertUndoType& insertUndo, - claimUndoType& expireUndo, - insertUndoType& insertSupportUndo, - supportUndoType& expireSupportUndo, - takeoverUndoType& takeovers) override; - - bool decrementBlock(insertUndoType& insertUndo, - claimUndoType& expireUndo, - insertUndoType& insertSupportUndo, - supportUndoType& expireSupportUndo) override; - -private: - int nExpirationTime; - bool forkForExpirationChange(bool increment); -}; - -class CClaimTrieCacheNormalizationFork : public CClaimTrieCacheExpirationFork -{ -public: - explicit CClaimTrieCacheNormalizationFork(CClaimTrie* base) - : CClaimTrieCacheExpirationFork(base) - { - } - - bool shouldNormalize() const; - - // lower-case and normalize any input string name - // see: https://unicode.org/reports/tr15/#Norm_Forms - std::string normalizeClaimName(const std::string& name, bool force = false) const; // public only for validating name field on update op - - bool incrementBlock(insertUndoType& insertUndo, - claimUndoType& expireUndo, - insertUndoType& insertSupportUndo, - supportUndoType& expireSupportUndo, - takeoverUndoType& takeovers) override; - - bool decrementBlock(insertUndoType& insertUndo, - claimUndoType& expireUndo, - insertUndoType& insertSupportUndo, - supportUndoType& expireSupportUndo) override; - - bool getProofForName(const std::string& name, const uint160& finalClaim, CClaimTrieProof& proof) override; - bool getInfoForName(const std::string& name, CClaimValue& claim, int heightOffset = 0) const override; - CClaimSupportToName getClaimsForName(const std::string& name) const override; - std::string adjustNameForValidHeight(const std::string& name, int validHeight) const override; - -protected: - int getDelayForName(const std::string& name, const uint160& claimId) const override; - -private: - bool normalizeAllNamesInTrieIfNecessary(takeoverUndoType& takeovers); - bool unnormalizeAllNamesInTrieIfNecessary(); -}; - -class CClaimTrieCacheHashFork : public CClaimTrieCacheNormalizationFork -{ -public: - explicit CClaimTrieCacheHashFork(CClaimTrie* base); - - bool getProofForName(const std::string& name, const uint160& finalClaim, CClaimTrieProof& proof) override; - void initializeIncrement() override; - bool finalizeDecrement(takeoverUndoType& takeovers) override; - - bool allowSupportMetadata() const; - -protected: - uint256 recursiveComputeMerkleHash(const std::string& name, int takeoverHeight, bool checkOnly) override; -}; - -typedef CClaimTrieCacheHashFork CClaimTrieCache; - -#endif // BITCOIN_CLAIMTRIE_H diff --git a/src/claimtrie/data.cpp b/src/claimtrie/data.cpp new file mode 100644 index 000000000..bf0de4fc8 --- /dev/null +++ b/src/claimtrie/data.cpp @@ -0,0 +1,84 @@ + +#include +#include + +#include +#include + +#define logPrint CLogPrint::global() + +CClaimValue::CClaimValue(CTxOutPoint outPoint, CUint160 claimId, int64_t nAmount, int nHeight, int nValidAtHeight) + : outPoint(std::move(outPoint)), claimId(std::move(claimId)), nAmount(nAmount), nEffectiveAmount(nAmount), nHeight(nHeight), nValidAtHeight(nValidAtHeight) +{ +} + +bool CClaimValue::operator<(const CClaimValue& other) const +{ + if (nEffectiveAmount < other.nEffectiveAmount) + return true; + if (nEffectiveAmount != other.nEffectiveAmount) + return false; + if (nHeight > other.nHeight) + return true; + if (nHeight != other.nHeight) + return false; + return outPoint != other.outPoint && !(outPoint < other.outPoint); +} + +bool CClaimValue::operator==(const CClaimValue& other) const +{ + return outPoint == other.outPoint && claimId == other.claimId && nAmount == other.nAmount && nHeight == other.nHeight && nValidAtHeight == other.nValidAtHeight; +} + +bool CClaimValue::operator!=(const CClaimValue& other) const +{ + return !(*this == other); +} + +std::string CClaimValue::ToString() const +{ + std::stringstream ss; + ss << "CClaimValue(" << outPoint.ToString() + << ", " << claimId.ToString() + << ", " << nAmount + << ", " << nEffectiveAmount + << ", " << nHeight + << ", " << nValidAtHeight << ')'; + return ss.str(); +} + +CSupportValue::CSupportValue(CTxOutPoint outPoint, CUint160 supportedClaimId, int64_t nAmount, int nHeight, int nValidAtHeight) + : outPoint(std::move(outPoint)), supportedClaimId(std::move(supportedClaimId)), nAmount(nAmount), nHeight(nHeight), nValidAtHeight(nValidAtHeight) +{ +} + +bool CSupportValue::operator==(const CSupportValue& other) const +{ + return outPoint == other.outPoint && supportedClaimId == other.supportedClaimId && nAmount == other.nAmount && nHeight == other.nHeight && nValidAtHeight == other.nValidAtHeight; +} + +bool CSupportValue::operator!=(const CSupportValue& other) const +{ + return !(*this == other); +} + +std::string CSupportValue::ToString() const +{ + std::stringstream ss; + ss << "CSupportValue(" << outPoint.ToString() + << ", " << supportedClaimId.ToString() + << ", " << nAmount + << ", " << nHeight + << ", " << nValidAtHeight << ')'; + return ss.str(); +} + +CNameOutPointHeightType::CNameOutPointHeightType(std::string name, CTxOutPoint outPoint, int nValidHeight) + : name(std::move(name)), outPoint(std::move(outPoint)), nValidHeight(nValidHeight) +{ +} + +CClaimIndexElement::CClaimIndexElement(std::string name, CClaimValue claim) + : name(std::move(name)), claim(std::move(claim)) +{ +} diff --git a/src/claimtrie/data.h b/src/claimtrie/data.h new file mode 100644 index 000000000..aa1bb2e88 --- /dev/null +++ b/src/claimtrie/data.h @@ -0,0 +1,131 @@ + +#ifndef CLAIMTRIE_DATA_H +#define CLAIMTRIE_DATA_H + +#include +#include +#include + +#include +#include +#include + +namespace sqlite +{ + inline int bind_col_in_db(sqlite3_stmt* stmt, int inx, const CUint160& val) { + return sqlite3_bind_blob(stmt, inx, val.begin(), int(val.size()), SQLITE_STATIC); + } + + inline int bind_col_in_db(sqlite3_stmt* stmt, int inx, const CUint256& val) { + return sqlite3_bind_blob(stmt, inx, val.begin(), int(val.size()), SQLITE_STATIC); + } + + inline void store_result_in_db(sqlite3_context* db, const CUint160& val) { + sqlite3_result_blob(db, val.begin(), int(val.size()), SQLITE_TRANSIENT); + } + + inline void store_result_in_db(sqlite3_context* db, const CUint256& val) { + sqlite3_result_blob(db, val.begin(), int(val.size()), SQLITE_TRANSIENT); + } +} + +#include + +namespace sqlite +{ + template<> + struct has_sqlite_type : std::true_type {}; + + template<> + struct has_sqlite_type : std::true_type {}; + + inline CUint160 get_col_from_db(sqlite3_stmt* stmt, int inx, result_type) { + CUint160 ret; + auto ptr = sqlite3_column_blob(stmt, inx); + if (!ptr) return ret; + int bytes = sqlite3_column_bytes(stmt, inx); + assert(bytes == ret.size()); + std::memcpy(ret.begin(), ptr, bytes); + return ret; + } + + inline CUint256 get_col_from_db(sqlite3_stmt* stmt, int inx, result_type) { + CUint256 ret; + auto ptr = sqlite3_column_blob(stmt, inx); + if (!ptr) return ret; + int bytes = sqlite3_column_bytes(stmt, inx); + assert(bytes == ret.size()); + std::memcpy(ret.begin(), ptr, bytes); + return ret; + } +} + +struct CClaimValue +{ + CTxOutPoint outPoint; + CUint160 claimId; + int64_t nAmount = 0; + int64_t nEffectiveAmount = 0; + int nHeight = 0; + int nValidAtHeight = 0; + + CClaimValue() = default; + CClaimValue(CTxOutPoint outPoint, CUint160 claimId, int64_t nAmount, int nHeight, int nValidAtHeight); + + CClaimValue(CClaimValue&&) = default; + CClaimValue(const CClaimValue&) = default; + CClaimValue& operator=(CClaimValue&&) = default; + CClaimValue& operator=(const CClaimValue&) = default; + + bool operator<(const CClaimValue& other) const; + bool operator==(const CClaimValue& other) const; + bool operator!=(const CClaimValue& other) const; + + std::string ToString() const; +}; + +struct CSupportValue +{ + CTxOutPoint outPoint; + CUint160 supportedClaimId; + int64_t nAmount = 0; + int nHeight = 0; + int nValidAtHeight = 0; + + CSupportValue() = default; + CSupportValue(CTxOutPoint outPoint, CUint160 supportedClaimId, int64_t nAmount, int nHeight, int nValidAtHeight); + + CSupportValue(CSupportValue&&) = default; + CSupportValue(const CSupportValue&) = default; + CSupportValue& operator=(CSupportValue&&) = default; + CSupportValue& operator=(const CSupportValue&) = default; + + bool operator==(const CSupportValue& other) const; + bool operator!=(const CSupportValue& other) const; + + std::string ToString() const; +}; + +typedef std::vector claimEntryType; +typedef std::vector supportEntryType; + +struct CNameOutPointHeightType +{ + std::string name; + CTxOutPoint outPoint; + int nValidHeight = 0; + + CNameOutPointHeightType() = default; + CNameOutPointHeightType(std::string name, CTxOutPoint outPoint, int nValidHeight); +}; + +struct CClaimIndexElement +{ + std::string name; + CClaimValue claim; + + CClaimIndexElement() = default; + CClaimIndexElement(std::string name, CClaimValue claim); +}; + +#endif // CLAIMTRIE_DATA_H diff --git a/src/claimtrieforks.cpp b/src/claimtrie/forks.cpp similarity index 73% rename from src/claimtrieforks.cpp rename to src/claimtrie/forks.cpp index 621351d6c..19b0fc94a 100644 --- a/src/claimtrieforks.cpp +++ b/src/claimtrie/forks.cpp @@ -1,35 +1,33 @@ -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include #include -CClaimTrieCacheExpirationFork::CClaimTrieCacheExpirationFork(CClaimTrie* base) - : CClaimTrieCacheBase(base) -{ - setExpirationTime(Params().GetConsensus().GetExpirationTime(nNextHeight)); -} +#define logPrint CLogPrint::global() -void CClaimTrieCacheExpirationFork::setExpirationTime(int time) +CClaimTrieCacheExpirationFork::CClaimTrieCacheExpirationFork(CClaimTrie* base) : CClaimTrieCacheBase(base) { - nExpirationTime = time; + expirationHeight = nNextHeight; } int CClaimTrieCacheExpirationFork::expirationTime() const { - return nExpirationTime; + if (expirationHeight < base->nExtendedClaimExpirationForkHeight) + return CClaimTrieCacheBase::expirationTime(); + return base->nExtendedClaimExpirationTime; } bool CClaimTrieCacheExpirationFork::incrementBlock(insertUndoType& insertUndo, claimUndoType& expireUndo, insertUndoType& insertSupportUndo, supportUndoType& expireSupportUndo, takeoverUndoType& takeoverUndo) { if (CClaimTrieCacheBase::incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverUndo)) { - setExpirationTime(Params().GetConsensus().GetExpirationTime(nNextHeight)); + expirationHeight = nNextHeight; return true; } return false; @@ -38,7 +36,7 @@ bool CClaimTrieCacheExpirationFork::incrementBlock(insertUndoType& insertUndo, c bool CClaimTrieCacheExpirationFork::decrementBlock(insertUndoType& insertUndo, claimUndoType& expireUndo, insertUndoType& insertSupportUndo, supportUndoType& expireSupportUndo) { if (CClaimTrieCacheBase::decrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo)) { - setExpirationTime(Params().GetConsensus().GetExpirationTime(nNextHeight)); + expirationHeight = nNextHeight; return true; } return false; @@ -47,7 +45,7 @@ bool CClaimTrieCacheExpirationFork::decrementBlock(insertUndoType& insertUndo, c void CClaimTrieCacheExpirationFork::initializeIncrement() { // we could do this in the constructor, but that would not allow for multiple increments in a row (as done in unit tests) - if (nNextHeight != Params().GetConsensus().nExtendedClaimExpirationForkHeight) + if (nNextHeight != base->nExtendedClaimExpirationForkHeight) return; forkForExpirationChange(true); @@ -56,7 +54,7 @@ void CClaimTrieCacheExpirationFork::initializeIncrement() bool CClaimTrieCacheExpirationFork::finalizeDecrement(takeoverUndoType& takeoverUndo) { auto ret = CClaimTrieCacheBase::finalizeDecrement(takeoverUndo); - if (ret && nNextHeight == Params().GetConsensus().nExtendedClaimExpirationForkHeight) + if (ret && nNextHeight == base->nExtendedClaimExpirationForkHeight) forkForExpirationChange(false); return ret; } @@ -73,7 +71,7 @@ bool CClaimTrieCacheExpirationFork::forkForExpirationChange(bool increment) will have their expiration extension removed. */ - auto extension = Params().GetConsensus().nExtendedClaimExpirationTime - Params().GetConsensus().nOriginalClaimExpirationTime; + auto extension = base->nExtendedClaimExpirationTime - base->nOriginalClaimExpirationTime; if (increment) { db << "UPDATE claims SET expirationHeight = expirationHeight + ? WHERE expirationHeight >= ?" << extension << nNextHeight; @@ -89,9 +87,13 @@ bool CClaimTrieCacheExpirationFork::forkForExpirationChange(bool increment) return true; } +CClaimTrieCacheNormalizationFork::CClaimTrieCacheNormalizationFork(CClaimTrie* base) : CClaimTrieCacheExpirationFork(base) +{ +} + bool CClaimTrieCacheNormalizationFork::shouldNormalize() const { - return nNextHeight > Params().GetConsensus().nNormalizedNameForkHeight; + return nNextHeight > base->nNormalizedNameForkHeight; } std::string CClaimTrieCacheNormalizationFork::normalizeClaimName(const std::string& name, bool force) const @@ -125,10 +127,10 @@ std::string CClaimTrieCacheNormalizationFork::normalizeClaimName(const std::stri } catch (const boost::locale::conv::conversion_error& e) { return name; } catch (const std::bad_cast& e) { - LogPrintf("%s() is invalid or dependencies are missing: %s\n", __func__, e.what()); + logPrint << "CClaimTrieCacheNormalizationFork::" << __func__ << "() is invalid or dependencies are missing: " << e.what() << Clog::endl; throw; } catch (const std::exception& e) { // TODO: change to use ... with current_exception() in c++11 - LogPrintf("%s() had an unexpected exception: %s\n", __func__, e.what()); + logPrint << "CClaimTrieCacheNormalizationFork::" << __func__ << "() had an unexpected exception: " << e.what() << Clog::endl; return name; } @@ -159,11 +161,11 @@ bool CClaimTrieCacheNormalizationFork::normalizeAllNamesInTrieIfNecessary(takeov for (auto&& row: query) { std::string name; int takeoverHeight; - std::unique_ptr takeoverID; + std::unique_ptr takeoverID; row >> name >> takeoverHeight >> takeoverID; if (name.empty()) continue; // preserve our root node if (takeoverHeight > 0) - takeoverUndo.emplace_back(name, std::make_pair(takeoverHeight, takeoverID ? *takeoverID : uint160())); + takeoverUndo.emplace_back(name, std::make_pair(takeoverHeight, takeoverID ? *takeoverID : CUint160())); // we need to let the tree structure method do the actual node delete: db << "UPDATE nodes SET hash = NULL WHERE name = ?" << name; } @@ -202,57 +204,22 @@ bool CClaimTrieCacheNormalizationFork::unnormalizeAllNamesInTrieIfNecessary() bool CClaimTrieCacheNormalizationFork::incrementBlock(insertUndoType& insertUndo, claimUndoType& expireUndo, insertUndoType& insertSupportUndo, supportUndoType& expireSupportUndo, takeoverUndoType& takeoverUndo) { - if (nNextHeight == Params().GetConsensus().nNormalizedNameForkHeight) + if (nNextHeight == base->nNormalizedNameForkHeight) normalizeAllNamesInTrieIfNecessary(takeoverUndo); - auto ret = CClaimTrieCacheExpirationFork::incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverUndo); -// if (nNextHeight == 588319) { -// getMerkleHash(); -// auto q2 = db << "SELECT name, nodeName FROM claims WHERE nodeName NOT IN (SELECT name FROM nodes) " -// "AND validHeight < ?1 AND expirationHeight >= ?1" << nNextHeight; -// for (auto&& row: q2) { -// std::string name, nn; -// row >> name >> nn; -// LogPrintf("BAD NAME 2: %s, %s\n", name, nn); -// } -// std::ifstream input("dump588318.txt"); -// std::string line; -// std::vector lines; -// while (std::getline(input, line)) { -// lines.push_back(line); -// } -// std::sort(lines.begin(), lines.end()); -// auto q3 = db << "SELECT n.name, n.hash, IFNULL(n.takeoverHeight, 0), " -// "(SELECT COUNT(*) FROM claims c WHERE c.nodeName = n.name " -// "AND validHeight < ?1 AND expirationHeight >= ?1) as cc FROM nodes n ORDER BY n.name" << nNextHeight; -// for (auto&& row: q3) { -// std::string name; int takeover, childs; uint256 hash; -// row >> name >> hash >> takeover >> childs; -// std::string m = name + ", " + std::to_string(name.size()) + ", " + hash.GetHex() + ", " + std::to_string(takeover) + ", " + std::to_string(childs); -// if (!std::binary_search(lines.begin(), lines.end(), m)) { -// LogPrintf("BAD BAD: %s\n", m); -// } -// } -// auto q4 = db << "SELECT n.name, n.parent FROM nodes n LEFT JOIN claims c ON n.name = c.nodeName LEFT JOIN nodes n2 ON n.name = n2.parent WHERE c.nodeName IS NULL AND n2.parent IS NULL"; -// for (auto&& row: q4) { -// std::string name, nn; -// row >> name >> nn; -// LogPrintf("BAD NAME 3: %s, %s\n", name, nn); -// } -// } - return ret; + return CClaimTrieCacheExpirationFork::incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverUndo); } bool CClaimTrieCacheNormalizationFork::decrementBlock(insertUndoType& insertUndo, claimUndoType& expireUndo, insertUndoType& insertSupportUndo, supportUndoType& expireSupportUndo) { auto ret = CClaimTrieCacheExpirationFork::decrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo); - if (ret && nNextHeight == Params().GetConsensus().nNormalizedNameForkHeight) + if (ret && nNextHeight == base->nNormalizedNameForkHeight) unnormalizeAllNamesInTrieIfNecessary(); return ret; } -bool CClaimTrieCacheNormalizationFork::getProofForName(const std::string& name, const uint160& finalClaim, CClaimTrieProof& proof) +bool CClaimTrieCacheNormalizationFork::getProofForName(const std::string& name, const CUint160& claim, CClaimTrieProof& proof) { - return CClaimTrieCacheExpirationFork::getProofForName(normalizeClaimName(name), finalClaim, proof); + return CClaimTrieCacheExpirationFork::getProofForName(normalizeClaimName(name), claim, proof); } bool CClaimTrieCacheNormalizationFork::getInfoForName(const std::string& name, CClaimValue& claim, int offsetHeight) const @@ -265,30 +232,45 @@ CClaimSupportToName CClaimTrieCacheNormalizationFork::getClaimsForName(const std return CClaimTrieCacheExpirationFork::getClaimsForName(normalizeClaimName(name)); } -int CClaimTrieCacheNormalizationFork::getDelayForName(const std::string& name, const uint160& claimId) const +int CClaimTrieCacheNormalizationFork::getDelayForName(const std::string& name, const CUint160& claimId) const { return CClaimTrieCacheExpirationFork::getDelayForName(normalizeClaimName(name), claimId); } std::string CClaimTrieCacheNormalizationFork::adjustNameForValidHeight(const std::string& name, int validHeight) const { - return normalizeClaimName(name, validHeight > Params().GetConsensus().nNormalizedNameForkHeight); + return normalizeClaimName(name, validHeight > base->nNormalizedNameForkHeight); } CClaimTrieCacheHashFork::CClaimTrieCacheHashFork(CClaimTrie* base) : CClaimTrieCacheNormalizationFork(base) { } -static const uint256 leafHash = uint256S("0000000000000000000000000000000000000000000000000000000000000002"); -static const uint256 emptyHash = uint256S("0000000000000000000000000000000000000000000000000000000000000003"); +static const auto leafHash = CUint256S("0000000000000000000000000000000000000000000000000000000000000002"); +static const auto emptyHash = CUint256S("0000000000000000000000000000000000000000000000000000000000000003"); -uint256 CClaimTrieCacheHashFork::recursiveComputeMerkleHash(const std::string& name, int takeoverHeight, bool checkOnly) +CUint256 ComputeMerkleRoot(std::vector hashes) { - if (nNextHeight < Params().GetConsensus().nAllClaimsInMerkleForkHeight) + while (hashes.size() > 1) { + if (hashes.size() & 1) + hashes.push_back(hashes.back()); + + for (std::size_t i = 0, j = 0; i < hashes.size(); i += 2) + hashes[j++] = Hash(hashes[i].begin(), hashes[i].end(), + hashes[i+1].begin(), hashes[i+1].end()); + + hashes.resize(hashes.size() / 2); + } + return hashes.empty() ? CUint256{} : hashes[0]; +} + +CUint256 CClaimTrieCacheHashFork::recursiveComputeMerkleHash(const std::string& name, int takeoverHeight, bool checkOnly) +{ + if (nNextHeight < base->nAllClaimsInMerkleForkHeight) return CClaimTrieCacheNormalizationFork::recursiveComputeMerkleHash(name, takeoverHeight, checkOnly); // it may be that using RAM for this is more expensive than preparing a new query statement in each recursive call - struct Triple { std::string name; std::unique_ptr hash; int takeoverHeight; }; + struct Triple { std::string name; std::unique_ptr hash; int takeoverHeight; }; std::vector children; for (auto&& row : childHashQuery << name) { children.emplace_back(); @@ -297,19 +279,19 @@ uint256 CClaimTrieCacheHashFork::recursiveComputeMerkleHash(const std::string& n } childHashQuery++; - std::vector childHashes; + std::vector childHashes; for (auto& child: children) { - if (child.hash == nullptr) child.hash = std::make_unique(); + if (child.hash == nullptr) child.hash = std::make_unique(); if (child.hash->IsNull()) { *child.hash = recursiveComputeMerkleHash(child.name, child.takeoverHeight, checkOnly); } childHashes.push_back(*child.hash); } - std::vector claimHashes; + std::vector claimHashes; //if (takeoverHeight > 0) { for (auto &&row: claimHashQuery << nNextHeight << name) { - COutPoint p; + CTxOutPoint p; row >> p.hash >> p.n; auto claimHash = getValueHash(p, takeoverHeight); claimHashes.push_back(claimHash); @@ -326,14 +308,14 @@ uint256 CClaimTrieCacheHashFork::recursiveComputeMerkleHash(const std::string& n return computedHash; } -std::vector ComputeMerklePath(const std::vector& hashes, uint32_t idx) +std::vector ComputeMerklePath(const std::vector& hashes, uint32_t idx) { uint32_t count = 0; int matchlevel = -1; bool matchh = false; - uint256 inner[32], h; + CUint256 inner[32], h; const uint32_t one = 1; - std::vector res; + std::vector res; const auto iterateInner = [&](int& level) { for (; !(count & (one << level)); level++) { @@ -381,12 +363,12 @@ std::vector ComputeMerklePath(const std::vector& hashes, uint3 return res; } -bool CClaimTrieCacheHashFork::getProofForName(const std::string& name, const uint160& finalClaim, CClaimTrieProof& proof) +bool CClaimTrieCacheHashFork::getProofForName(const std::string& name, const CUint160& claim, CClaimTrieProof& proof) { - if (nNextHeight < Params().GetConsensus().nAllClaimsInMerkleForkHeight) - return CClaimTrieCacheNormalizationFork::getProofForName(name, finalClaim, proof); + if (nNextHeight < base->nAllClaimsInMerkleForkHeight) + return CClaimTrieCacheNormalizationFork::getProofForName(name, claim, proof); - auto fillPairs = [&proof](const std::vector& hashes, uint32_t idx) { + auto fillPairs = [&proof](const std::vector& hashes, uint32_t idx) { auto partials = ComputeMerklePath(hashes, idx); for (int i = partials.size() - 1; i >= 0; --i) proof.pairs.emplace_back((idx >> i) & 1, partials[i]); @@ -400,14 +382,14 @@ bool CClaimTrieCacheHashFork::getProofForName(const std::string& name, const uin "SELECT POPS(p) FROM prefix WHERE p != '') SELECT p FROM prefix) " "ORDER BY name" << name; for (auto&& row: nodeQuery) { - std::string key;; + std::string key; int takeoverHeight; row >> key >> takeoverHeight; - std::vector childHashes; uint32_t nextCurrentIdx = 0; + std::vector childHashes; for (auto&& child : childHashQuery << key) { std::string childKey; - uint256 childHash; + CUint256 childHash; child >> childKey >> childHash; if (name.find(childKey) == 0) nextCurrentIdx = uint32_t(childHashes.size()); @@ -415,14 +397,14 @@ bool CClaimTrieCacheHashFork::getProofForName(const std::string& name, const uin } childHashQuery++; - std::vector claimHashes; - uint32_t finalClaimIdx = 0; + std::vector claimHashes; + uint32_t claimIdx = 0; for (auto&& child: claimHashQuery << nNextHeight << key) { - COutPoint childOutPoint; - uint160 childClaimID; + CTxOutPoint childOutPoint; + CUint160 childClaimID; child >> childOutPoint.hash >> childOutPoint.n >> childClaimID; - if (childClaimID == finalClaim && key == name) { - finalClaimIdx = uint32_t(claimHashes.size()); + if (childClaimID == claim && key == name) { + claimIdx = uint32_t(claimHashes.size()); proof.outPoint = childOutPoint; proof.hasValue = true; } @@ -438,7 +420,7 @@ bool CClaimTrieCacheHashFork::getProofForName(const std::string& name, const uin auto hash = childHashes.empty() ? leafHash : ComputeMerkleRoot(childHashes); proof.pairs.emplace_back(true, hash); if (!claimHashes.empty()) - fillPairs(claimHashes, finalClaimIdx); + fillPairs(claimHashes, claimIdx); } else { auto hash = claimHashes.empty() ? emptyHash : ComputeMerkleRoot(claimHashes); proof.pairs.emplace_back(false, hash); @@ -454,7 +436,7 @@ void CClaimTrieCacheHashFork::initializeIncrement() { CClaimTrieCacheNormalizationFork::initializeIncrement(); // we could do this in the constructor, but that would not allow for multiple increments in a row (as done in unit tests) - if (nNextHeight == Params().GetConsensus().nAllClaimsInMerkleForkHeight - 1) { + if (nNextHeight == base->nAllClaimsInMerkleForkHeight - 1) { if (!transacting) { transacting = true; db << "begin"; } db << "UPDATE nodes SET hash = NULL"; } @@ -463,7 +445,7 @@ void CClaimTrieCacheHashFork::initializeIncrement() bool CClaimTrieCacheHashFork::finalizeDecrement(takeoverUndoType& takeoverUndo) { auto ret = CClaimTrieCacheNormalizationFork::finalizeDecrement(takeoverUndo); - if (ret && nNextHeight == Params().GetConsensus().nAllClaimsInMerkleForkHeight - 1) { + if (ret && nNextHeight == base->nAllClaimsInMerkleForkHeight - 1) { if (!transacting) { transacting = true; db << "begin"; } db << "UPDATE nodes SET hash = NULL"; } @@ -472,5 +454,5 @@ bool CClaimTrieCacheHashFork::finalizeDecrement(takeoverUndoType& takeoverUndo) bool CClaimTrieCacheHashFork::allowSupportMetadata() const { - return nNextHeight >= Params().GetConsensus().nAllClaimsInMerkleForkHeight; + return nNextHeight >= base->nAllClaimsInMerkleForkHeight; } diff --git a/src/claimtrie/forks.h b/src/claimtrie/forks.h new file mode 100644 index 000000000..46573e219 --- /dev/null +++ b/src/claimtrie/forks.h @@ -0,0 +1,87 @@ + +#ifndef CLAIMTRIE_FORKS_H +#define CLAIMTRIE_FORKS_H + +#include + +class CClaimTrieCacheExpirationFork : public CClaimTrieCacheBase +{ +public: + explicit CClaimTrieCacheExpirationFork(CClaimTrie* base); + + int expirationTime() const override; + + virtual void initializeIncrement(); + bool finalizeDecrement(takeoverUndoType& takeoverHeightUndo) override; + + bool incrementBlock(insertUndoType& insertUndo, + claimUndoType& expireUndo, + insertUndoType& insertSupportUndo, + supportUndoType& expireSupportUndo, + takeoverUndoType& takeoverHeightUndo) override; + + bool decrementBlock(insertUndoType& insertUndo, + claimUndoType& expireUndo, + insertUndoType& insertSupportUndo, + supportUndoType& expireSupportUndo) override; + +protected: + int expirationHeight; + +private: + bool forkForExpirationChange(bool increment); +}; + +class CClaimTrieCacheNormalizationFork : public CClaimTrieCacheExpirationFork +{ +public: + explicit CClaimTrieCacheNormalizationFork(CClaimTrie* base); + + bool shouldNormalize() const; + + // lower-case and normalize any input string name + // see: https://unicode.org/reports/tr15/#Norm_Forms + std::string normalizeClaimName(const std::string& name, bool force = false) const; // public only for validating name field on update op + + bool incrementBlock(insertUndoType& insertUndo, + claimUndoType& expireUndo, + insertUndoType& insertSupportUndo, + supportUndoType& expireSupportUndo, + takeoverUndoType& takeoverHeightUndo) override; + + bool decrementBlock(insertUndoType& insertUndo, + claimUndoType& expireUndo, + insertUndoType& insertSupportUndo, + supportUndoType& expireSupportUndo) override; + + bool getProofForName(const std::string& name, const CUint160& claim, CClaimTrieProof& proof) override; + bool getInfoForName(const std::string& name, CClaimValue& claim, int heightOffset = 0) const override; + CClaimSupportToName getClaimsForName(const std::string& name) const override; + std::string adjustNameForValidHeight(const std::string& name, int validHeight) const override; + +protected: + int getDelayForName(const std::string& name, const CUint160& claimId) const override; + +private: + bool normalizeAllNamesInTrieIfNecessary(takeoverUndoType& takeovers); + bool unnormalizeAllNamesInTrieIfNecessary(); +}; + +class CClaimTrieCacheHashFork : public CClaimTrieCacheNormalizationFork +{ +public: + explicit CClaimTrieCacheHashFork(CClaimTrie* base); + + bool getProofForName(const std::string& name, const CUint160& claim, CClaimTrieProof& proof) override; + void initializeIncrement() override; + bool finalizeDecrement(takeoverUndoType& takeoverHeightUndo) override; + + bool allowSupportMetadata() const; + +protected: + CUint256 recursiveComputeMerkleHash(const std::string& name, int takeoverHeight, bool checkOnly) override; +}; + +typedef CClaimTrieCacheHashFork CClaimTrieCache; + +#endif // CLAIMTRIE_FORKS_H diff --git a/src/claimtrie/hash.cpp b/src/claimtrie/hash.cpp new file mode 100644 index 000000000..8d18ecbb1 --- /dev/null +++ b/src/claimtrie/hash.cpp @@ -0,0 +1,12 @@ + +#include + +CUint256 CalcHash(SHA256_CTX* sha) +{ + CUint256 result; + SHA256_Final(result.begin(), sha); + SHA256_Init(sha); + SHA256_Update(sha, result.begin(), result.size()); + SHA256_Final(result.begin(), sha); + return result; +} diff --git a/src/claimtrie/hash.h b/src/claimtrie/hash.h new file mode 100644 index 000000000..88127c4c3 --- /dev/null +++ b/src/claimtrie/hash.h @@ -0,0 +1,29 @@ + +#ifndef CLAIMTRIE_HASH_H +#define CLAIMTRIE_HASH_H + +#include + +#include + +// Bitcoin doubles hashes +CUint256 CalcHash(SHA256_CTX* sha); + +template +CUint256 CalcHash(SHA256_CTX* sha, TIterator begin, TIterator end, Args... args) +{ + static uint8_t blank; + SHA256_Update(sha, begin == end ? &blank : (uint8_t*)&begin[0], std::distance(begin, end) * sizeof(begin[0])); + return CalcHash(sha, args...); +} + +template +CUint256 Hash(TIterator begin, TIterator end, Args... args) +{ + static_assert((sizeof...(args) & 1) != 1, "Parameters should be even number"); + SHA256_CTX sha; + SHA256_Init(&sha); + return CalcHash(&sha, begin, end, args...); +} + +#endif // CLAIMTRIE_HASH_H diff --git a/src/claimtrie/log.cpp b/src/claimtrie/log.cpp new file mode 100644 index 000000000..364cde754 --- /dev/null +++ b/src/claimtrie/log.cpp @@ -0,0 +1,23 @@ + +#include + +void CLogPrint::setLogger(ClogBase* log) +{ + logger = log; +} + +CLogPrint& CLogPrint::global() +{ + static CLogPrint logger; + return logger; +} + +CLogPrint& CLogPrint::operator<<(const Clog& cl) +{ + if (logger && cl == Clog::endl) { + ss << '\n'; + logger->LogPrintStr(ss.str()); + ss.str({}); + } + return *this; +} diff --git a/src/claimtrie/log.h b/src/claimtrie/log.h new file mode 100644 index 000000000..ac3f49f0e --- /dev/null +++ b/src/claimtrie/log.h @@ -0,0 +1,41 @@ + +#ifndef CLAIMTRIE_LOG_H +#define CLAIMTRIE_LOG_H + +#include +#include + +struct ClogBase +{ + ClogBase() = default; + virtual ~ClogBase() = default; + virtual void LogPrintStr(const std::string&) = 0; +}; + +enum struct Clog +{ + endl = 0, +}; + +struct CLogPrint +{ + template + CLogPrint& operator<<(const T& a) + { + if (logger) + ss << a; + return *this; + } + + CLogPrint& operator<<(const Clog& cl); + + void setLogger(ClogBase* log); + static CLogPrint& global(); + +private: + CLogPrint() = default; + std::stringstream ss; + ClogBase* logger = nullptr; +}; + +#endif // CLAIMTRIE_LOG_H diff --git a/src/sqlite/hdr/sqlite_modern_cpp.h b/src/claimtrie/sqlite/hdr/sqlite_modern_cpp.h similarity index 99% rename from src/sqlite/hdr/sqlite_modern_cpp.h rename to src/claimtrie/sqlite/hdr/sqlite_modern_cpp.h index 080bf3719..6a6a01270 100644 --- a/src/sqlite/hdr/sqlite_modern_cpp.h +++ b/src/claimtrie/sqlite/hdr/sqlite_modern_cpp.h @@ -9,7 +9,7 @@ #define MODERN_SQLITE_VERSION 3002008 -#include +#include "../sqlite3.h" #include "sqlite_modern_cpp/type_wrapper.h" #include "sqlite_modern_cpp/errors.h" diff --git a/src/sqlite/hdr/sqlite_modern_cpp/errors.h b/src/claimtrie/sqlite/hdr/sqlite_modern_cpp/errors.h similarity index 99% rename from src/sqlite/hdr/sqlite_modern_cpp/errors.h rename to src/claimtrie/sqlite/hdr/sqlite_modern_cpp/errors.h index aba4feb28..07e1b1fa8 100644 --- a/src/sqlite/hdr/sqlite_modern_cpp/errors.h +++ b/src/claimtrie/sqlite/hdr/sqlite_modern_cpp/errors.h @@ -3,7 +3,7 @@ #include #include -#include +#include "../../sqlite3.h" namespace sqlite { @@ -67,4 +67,4 @@ namespace sqlite { } } namespace exceptions = errors; -} \ No newline at end of file +} diff --git a/src/sqlite/hdr/sqlite_modern_cpp/lists/error_codes.h b/src/claimtrie/sqlite/hdr/sqlite_modern_cpp/lists/error_codes.h similarity index 100% rename from src/sqlite/hdr/sqlite_modern_cpp/lists/error_codes.h rename to src/claimtrie/sqlite/hdr/sqlite_modern_cpp/lists/error_codes.h diff --git a/src/sqlite/hdr/sqlite_modern_cpp/log.h b/src/claimtrie/sqlite/hdr/sqlite_modern_cpp/log.h similarity index 100% rename from src/sqlite/hdr/sqlite_modern_cpp/log.h rename to src/claimtrie/sqlite/hdr/sqlite_modern_cpp/log.h diff --git a/src/sqlite/hdr/sqlite_modern_cpp/sqlcipher.h b/src/claimtrie/sqlite/hdr/sqlite_modern_cpp/sqlcipher.h similarity index 100% rename from src/sqlite/hdr/sqlite_modern_cpp/sqlcipher.h rename to src/claimtrie/sqlite/hdr/sqlite_modern_cpp/sqlcipher.h diff --git a/src/sqlite/hdr/sqlite_modern_cpp/type_wrapper.h b/src/claimtrie/sqlite/hdr/sqlite_modern_cpp/type_wrapper.h similarity index 99% rename from src/sqlite/hdr/sqlite_modern_cpp/type_wrapper.h rename to src/claimtrie/sqlite/hdr/sqlite_modern_cpp/type_wrapper.h index 9a8710dc2..ddfd011a7 100644 --- a/src/sqlite/hdr/sqlite_modern_cpp/type_wrapper.h +++ b/src/claimtrie/sqlite/hdr/sqlite_modern_cpp/type_wrapper.h @@ -49,7 +49,7 @@ namespace sqlite typedef const std::u16string& u16str_ref; } #endif -#include +#include "../../sqlite3.h" #include "errors.h" namespace sqlite { @@ -415,4 +415,4 @@ namespace sqlite { }); } #endif -} \ No newline at end of file +} diff --git a/src/sqlite/hdr/sqlite_modern_cpp/utility/function_traits.h b/src/claimtrie/sqlite/hdr/sqlite_modern_cpp/utility/function_traits.h similarity index 98% rename from src/sqlite/hdr/sqlite_modern_cpp/utility/function_traits.h rename to src/claimtrie/sqlite/hdr/sqlite_modern_cpp/utility/function_traits.h index f629aa09e..1e972daa2 100644 --- a/src/sqlite/hdr/sqlite_modern_cpp/utility/function_traits.h +++ b/src/claimtrie/sqlite/hdr/sqlite_modern_cpp/utility/function_traits.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include namespace sqlite { namespace utility { diff --git a/src/sqlite/hdr/sqlite_modern_cpp/utility/uncaught_exceptions.h b/src/claimtrie/sqlite/hdr/sqlite_modern_cpp/utility/uncaught_exceptions.h similarity index 100% rename from src/sqlite/hdr/sqlite_modern_cpp/utility/uncaught_exceptions.h rename to src/claimtrie/sqlite/hdr/sqlite_modern_cpp/utility/uncaught_exceptions.h diff --git a/src/sqlite/hdr/sqlite_modern_cpp/utility/utf16_utf8.h b/src/claimtrie/sqlite/hdr/sqlite_modern_cpp/utility/utf16_utf8.h similarity index 100% rename from src/sqlite/hdr/sqlite_modern_cpp/utility/utf16_utf8.h rename to src/claimtrie/sqlite/hdr/sqlite_modern_cpp/utility/utf16_utf8.h diff --git a/src/sqlite/shell.c b/src/claimtrie/sqlite/shell.c similarity index 100% rename from src/sqlite/shell.c rename to src/claimtrie/sqlite/shell.c diff --git a/src/sqlite/sqlite3.c b/src/claimtrie/sqlite/sqlite3.c similarity index 100% rename from src/sqlite/sqlite3.c rename to src/claimtrie/sqlite/sqlite3.c diff --git a/src/sqlite/sqlite3.h b/src/claimtrie/sqlite/sqlite3.h similarity index 100% rename from src/sqlite/sqlite3.h rename to src/claimtrie/sqlite/sqlite3.h diff --git a/src/sqlite/sqlite3ext.h b/src/claimtrie/sqlite/sqlite3ext.h similarity index 100% rename from src/sqlite/sqlite3ext.h rename to src/claimtrie/sqlite/sqlite3ext.h diff --git a/src/claimtrie.cpp b/src/claimtrie/trie.cpp similarity index 89% rename from src/claimtrie.cpp rename to src/claimtrie/trie.cpp index 46405cd10..452f266cd 100644 --- a/src/claimtrie.cpp +++ b/src/claimtrie/trie.cpp @@ -1,21 +1,22 @@ -#include -#include -#include -#include -#include + +#include +#include +#include #include #include -#include +#include #include #include -extern const uint256 one = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); +#define logPrint CLogPrint::global() + +static const auto one = CUint256S("0000000000000000000000000000000000000000000000000000000000000001"); std::vector heightToVch(int n) { - std::vector vchHeight(8, 0); + std::vector vchHeight(8, 0); vchHeight[4] = n >> 24; vchHeight[5] = n >> 16; vchHeight[6] = n >> 8; @@ -23,40 +24,84 @@ std::vector heightToVch(int n) return vchHeight; } -uint256 getValueHash(const COutPoint& outPoint, int nHeightOfLastTakeover) +CUint256 getValueHash(const CTxOutPoint& outPoint, int nHeightOfLastTakeover) { - CHash256 hasher; - auto hash = Hash(outPoint.hash.begin(), outPoint.hash.end()); - hasher.Write(hash.begin(), hash.size()); - + auto hash1 = Hash(outPoint.hash.begin(), outPoint.hash.end()); auto snOut = std::to_string(outPoint.n); - hash = Hash(snOut.begin(), snOut.end()); - hasher.Write(hash.begin(), hash.size()); - + auto hash2 = Hash(snOut.begin(), snOut.end()); auto vchHash = heightToVch(nHeightOfLastTakeover); - hash = Hash(vchHash.begin(), vchHash.end()); - hasher.Write(hash.begin(), hash.size()); - - uint256 result; - hasher.Finalize(result.begin()); - return result; + auto hash3 = Hash(vchHash.begin(), vchHash.end()); + return Hash(hash1.begin(), hash1.end(), hash2.begin(), hash2.end(), hash3.begin(), hash3.end()); } -static const sqlite::sqlite_config sharedConfig{ +CClaimNsupports::CClaimNsupports(CClaimValue claim, int64_t effectiveAmount, std::vector supports) + : claim(std::move(claim)), effectiveAmount(effectiveAmount), supports(std::move(supports)) +{ +} + +bool CClaimNsupports::IsNull() const +{ + return claim.claimId.IsNull(); +} + +CClaimSupportToName::CClaimSupportToName(std::string name, int nLastTakeoverHeight, std::vector claimsNsupports, std::vector unmatchedSupports) + : name(std::move(name)), nLastTakeoverHeight(nLastTakeoverHeight), claimsNsupports(std::move(claimsNsupports)), unmatchedSupports(std::move(unmatchedSupports)) +{ +} + +static const CClaimNsupports invalid; + +const CClaimNsupports& CClaimSupportToName::find(const CUint160& claimId) const +{ + auto it = std::find_if(claimsNsupports.begin(), claimsNsupports.end(), [&claimId](const CClaimNsupports& value) { + return claimId == value.claim.claimId; + }); + return it != claimsNsupports.end() ? *it : invalid; +} + +const CClaimNsupports& CClaimSupportToName::find(const std::string& partialId) const +{ + std::string lowered(partialId); + for (auto& c: lowered) + c = std::tolower(c); + + auto it = std::find_if(claimsNsupports.begin(), claimsNsupports.end(), [&lowered](const CClaimNsupports& value) { + return value.claim.claimId.GetHex().find(lowered) == 0; + }); + return it != claimsNsupports.end() ? *it : invalid; +} + +bool CClaimNsupports::operator<(const CClaimNsupports& other) const +{ + return claim < other.claim; +} + +CClaimTrieProofNode::CClaimTrieProofNode(std::vector> children, bool hasValue, CUint256 valHash) + : children(std::move(children)), hasValue(hasValue), valHash(std::move(valHash)) +{ +} + +static const sqlite::sqlite_config sharedConfig { sqlite::OpenFlags::READWRITE | sqlite::OpenFlags::CREATE, // TODO: test with this: | sqlite::OpenFlags::SHAREDCACHE, nullptr, sqlite::Encoding::UTF8 }; -CClaimTrie::CClaimTrie(bool fWipe, int height, int proportionalDelayFactor) - : dbPath((GetDataDir() / "claims.sqlite").string()), db(dbPath, sharedConfig), - nNextHeight(height), nProportionalDelayFactor(proportionalDelayFactor) +CClaimTrie::CClaimTrie(bool fWipe, int height, + int nNormalizedNameForkHeight, + int64_t nOriginalClaimExpirationTime, + int64_t nExtendedClaimExpirationTime, + int64_t nExtendedClaimExpirationForkHeight, + int64_t nAllClaimsInMerkleForkHeight, + int proportionalDelayFactor) : + nNextHeight(height), + db("claims.sqlite", sharedConfig), + nProportionalDelayFactor(proportionalDelayFactor), + nNormalizedNameForkHeight(nNormalizedNameForkHeight), + nOriginalClaimExpirationTime(nOriginalClaimExpirationTime), + nExtendedClaimExpirationTime(nExtendedClaimExpirationTime), + nExtendedClaimExpirationForkHeight(nExtendedClaimExpirationForkHeight), + nAllClaimsInMerkleForkHeight(nAllClaimsInMerkleForkHeight) { -// db.define("MERKLE_ROOT", [](std::vector& hashes, const std::vector& blob) { hashes.emplace_back(uint256(blob)); }, -// [](const std::vector& hashes) { return ComputeMerkleRoot(hashes); }); -// -// db.define("MERKLE_PAIR", [](const std::vector& blob1, const std::vector& blob2) { return Hash(blob1.begin(), blob1.end(), blob2.begin(), blob2.end()); }); -// db.define("MERKLE", [](const std::vector& blob1) { return Hash(blob1.begin(), blob1.end()); }); - db << "CREATE TABLE IF NOT EXISTS nodes (name TEXT NOT NULL PRIMARY KEY, parent TEXT REFERENCES nodes(name) DEFERRABLE INITIALLY DEFERRED, " "hash BLOB COLLATE BINARY, takeoverHeight INTEGER, takeoverID BLOB COLLATE BINARY)"; db << "CREATE INDEX IF NOT EXISTS nodes_hash ON nodes (hash)"; @@ -95,7 +140,8 @@ CClaimTrie::CClaimTrie(bool fWipe, int height, int proportionalDelayFactor) db << "INSERT OR IGNORE INTO nodes(name, hash) VALUES('', ?)" << one; // ensure that we always have our root node } -CClaimTrieCacheBase::~CClaimTrieCacheBase() { +CClaimTrieCacheBase::~CClaimTrieCacheBase() +{ if (transacting) { db << "rollback"; transacting = false; @@ -111,13 +157,14 @@ bool CClaimTrie::SyncToDisk() return rc == SQLITE_OK; } -bool CClaimTrie::empty() { +bool CClaimTrie::empty() +{ int64_t count; db << "SELECT COUNT(*) FROM claims WHERE validHeight < ?1 AND expirationHeight >= ?1" << nNextHeight >> count; return count == 0; } -bool CClaimTrieCacheBase::haveClaim(const std::string& name, const COutPoint& outPoint) const +bool CClaimTrieCacheBase::haveClaim(const std::string& name, const CTxOutPoint& outPoint) const { auto query = db << "SELECT 1 FROM claims WHERE nodeName = ?1 AND txID = ?2 AND txN = ?3 " "AND validHeight < ?4 AND expirationHeight >= ?4 LIMIT 1" @@ -125,7 +172,7 @@ bool CClaimTrieCacheBase::haveClaim(const std::string& name, const COutPoint& ou return query.begin() != query.end(); } -bool CClaimTrieCacheBase::haveSupport(const std::string& name, const COutPoint& outPoint) const +bool CClaimTrieCacheBase::haveSupport(const std::string& name, const CTxOutPoint& outPoint) const { auto query = db << "SELECT 1 FROM supports WHERE nodeName = ?1 AND txID = ?2 AND txN = ?3 " "AND validHeight < ?4 AND expirationHeight >= ?4 LIMIT 1" @@ -148,7 +195,7 @@ supportEntryType CClaimTrieCacheBase::getSupportsForName(const std::string& name return ret; } -bool CClaimTrieCacheBase::haveClaimInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const +bool CClaimTrieCacheBase::haveClaimInQueue(const std::string& name, const CTxOutPoint& outPoint, int& nValidAtHeight) const { auto query = db << "SELECT validHeight FROM claims WHERE nodeName = ? AND txID = ? AND txN = ? " "AND validHeight >= ? AND expirationHeight > validHeight LIMIT 1" @@ -160,7 +207,7 @@ bool CClaimTrieCacheBase::haveClaimInQueue(const std::string& name, const COutPo return false; } -bool CClaimTrieCacheBase::haveSupportInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const +bool CClaimTrieCacheBase::haveSupportInQueue(const std::string& name, const CTxOutPoint& outPoint, int& nValidAtHeight) const { auto query = db << "SELECT validHeight FROM supports WHERE nodeName = ? AND txID = ? AND txN = ? " "AND validHeight >= ? AND expirationHeight > validHeight LIMIT 1" @@ -172,7 +219,8 @@ bool CClaimTrieCacheBase::haveSupportInQueue(const std::string& name, const COut return false; } -bool CClaimTrieCacheBase::deleteNodeIfPossible(const std::string& name, std::string& parent, int64_t& claims) { +bool CClaimTrieCacheBase::deleteNodeIfPossible(const std::string& name, std::string& parent, int64_t& claims) +{ if (name.empty()) return false; // to remove a node it must have one or less children and no claims db << "SELECT COUNT(*) FROM claims WHERE nodeName = ?1 AND validHeight < ?2 AND expirationHeight >= ?2 " @@ -186,7 +234,7 @@ bool CClaimTrieCacheBase::deleteNodeIfPossible(const std::string& name, std::str // alternately: SELECT COUNT(DISTINCT nodeName) FROM claims WHERE SUBSTR(nodeName, 1, len(?)) == ? AND LENGTH(nodeName) > len(?) db << "SELECT COUNT(*),MAX(name) FROM nodes WHERE parent = ?" << name >> std::tie(count, childName); if (count > 1) return false; // still has multiple children - LogPrint(BCLog::CLAIMS, "Removing node %s with %d children\n", name, count); + logPrint << "Removing node " << name << " with " << count << " children" << Clog::endl; // okay. it's going away auto query = db << "SELECT parent FROM nodes WHERE name = ?" << name; auto it = query.begin(); @@ -202,7 +250,8 @@ bool CClaimTrieCacheBase::deleteNodeIfPossible(const std::string& name, std::str return ret; } -void CClaimTrieCacheBase::ensureTreeStructureIsUpToDate() { +void CClaimTrieCacheBase::ensureTreeStructureIsUpToDate() +{ if (!transacting) return; // your children are your nodes that match your key but go at least one longer, @@ -272,7 +321,7 @@ void CClaimTrieCacheBase::ensureTreeStructureIsUpToDate() { break; } // insert the split node: - LogPrint(BCLog::CLAIMS, "Inserting split node %s near %s, parent %s\n", newNodeName, sibling, parent); + logPrint << "Inserting split node " << newNodeName << " near " << sibling << ", parent " << parent << Clog::endl; insertQuery << newNodeName << parent; insertQuery++; @@ -281,7 +330,7 @@ void CClaimTrieCacheBase::ensureTreeStructureIsUpToDate() { } } - LogPrint(BCLog::CLAIMS, "Inserting or updating node %s (%s), parent %s\n", name, HexStr(name), parent); + logPrint << "Inserting or updating node " << name << ", parent " << parent << Clog::endl; insertQuery << name << parent; insertQuery++; } @@ -313,9 +362,9 @@ std::size_t CClaimTrieCacheBase::getTotalClaimsInTrie() const return ret; } -CAmount CClaimTrieCacheBase::getTotalValueOfClaimsInTrie(bool fControllingOnly) const +int64_t CClaimTrieCacheBase::getTotalValueOfClaimsInTrie(bool fControllingOnly) const { - CAmount ret = 0; + int64_t ret = 0; std::string query("SELECT SUM(SELECT IFNULL(SUM(s.amount),0)+c.amount FROM supports s " "WHERE s.supportedClaimID = c.claimID AND s.validHeight < ?1 AND s.expirationHeight >= ?1) " "FROM claims c WHERE c.validHeight < ?1 AND s.expirationHeight >= ?1"); @@ -348,9 +397,9 @@ CClaimSupportToName CClaimTrieCacheBase::getClaimsForName(const std::string& nam if (it != query.end()) *it >> nLastTakeoverHeight; } - auto supports = getSupportsForName(name); claimEntryType claims; + auto supports = getSupportsForName(name); { auto query = db << "SELECT claimID, txID, txN, blockHeight, validHeight, amount " "FROM claims WHERE nodeName = ? AND expirationHeight >= ?" @@ -362,6 +411,7 @@ CClaimSupportToName CClaimTrieCacheBase::getClaimsForName(const std::string& nam claims.push_back(claim); } } + auto find = [&supports](decltype(supports)::iterator& it, const CClaimValue& claim) { it = std::find_if(it, supports.end(), [&claim](const CSupportValue& support) { return claim.claimId == support.supportedClaimId; @@ -372,7 +422,7 @@ CClaimSupportToName CClaimTrieCacheBase::getClaimsForName(const std::string& nam // match support to claim std::vector claimsNsupports; for (const auto& claim : claims) { - CAmount nAmount = claim.nValidAtHeight < nNextHeight ? claim.nAmount : 0; + int64_t nAmount = claim.nValidAtHeight < nNextHeight ? claim.nAmount : 0; auto ic = claimsNsupports.emplace(claimsNsupports.end(), claim, nAmount); for (auto it = supports.begin(); find(it, claim); it = supports.erase(it)) { if (it->nValidAtHeight < nNextHeight) @@ -385,22 +435,18 @@ CClaimSupportToName CClaimTrieCacheBase::getClaimsForName(const std::string& nam return {name, nLastTakeoverHeight, std::move(claimsNsupports), std::move(supports)}; } -void completeHash(uint256& partialHash, const std::string& key, std::size_t to) +void completeHash(CUint256& partialHash, const std::string& key, int to) { - CHash256 hasher; - for (auto i = key.size(); i > to + 1; --i, hasher.Reset()) - hasher - .Write((uint8_t*)&key[i - 1], 1) - .Write(partialHash.begin(), partialHash.size()) - .Finalize(partialHash.begin()); + for (auto it = key.rbegin(); std::distance(it, key.rend()) > to + 1; ++it) + partialHash = Hash(it, it + 1, partialHash.begin(), partialHash.end()); } -uint256 CClaimTrieCacheBase::recursiveComputeMerkleHash(const std::string& name, int takeoverHeight, bool checkOnly) +CUint256 CClaimTrieCacheBase::recursiveComputeMerkleHash(const std::string& name, int takeoverHeight, bool checkOnly) { std::vector vchToHash; const auto pos = name.size(); // we have to free up the hash query so it can be reused by a child - struct Triple { std::string name; std::unique_ptr hash; int takeoverHeight; }; + struct Triple { std::string name; std::unique_ptr hash; int takeoverHeight; }; std::vector children; for (auto&& row : childHashQuery << name) { children.emplace_back(); @@ -410,12 +456,10 @@ uint256 CClaimTrieCacheBase::recursiveComputeMerkleHash(const std::string& name, childHashQuery++; for (auto& child: children) { - if (child.hash == nullptr) child.hash = std::make_unique(); + if (child.hash == nullptr) child.hash = std::make_unique(); if (child.hash->IsNull()) { *child.hash = recursiveComputeMerkleHash(child.name, child.takeoverHeight, checkOnly); } - if (!checkOnly) - LogPrint(BCLog::CLAIMS, "Using hash of %s (%s): %s, takeover: %d\n", child.name, HexStr(child.name), (*child.hash).GetHex(), child.takeoverHeight); completeHash(*child.hash, child.name, pos); vchToHash.push_back(child.name[pos]); vchToHash.insert(vchToHash.end(), child.hash->begin(), child.hash->end()); @@ -423,7 +467,7 @@ uint256 CClaimTrieCacheBase::recursiveComputeMerkleHash(const std::string& name, CClaimValue claim; if (getInfoForName(name, claim)) { - uint256 valueHash = getValueHash(claim.outPoint, takeoverHeight); + CUint256 valueHash = getValueHash(claim.outPoint, takeoverHeight); vchToHash.insert(vchToHash.end(), valueHash.begin(), valueHash.end()); } @@ -440,7 +484,7 @@ bool CClaimTrieCacheBase::checkConsistency() auto query = db << "SELECT name, hash, IFNULL(takeoverHeight, 0) FROM nodes"; for (auto&& row: query) { std::string name; - uint256 hash; + CUint256 hash; int takeoverHeight; row >> name >> hash >> takeoverHeight; auto computedHash = recursiveComputeMerkleHash(name, takeoverHeight, true); @@ -459,7 +503,7 @@ bool CClaimTrieCacheBase::flush() db << "commit"; } catch (const sqlite::sqlite_exception& e) { - LogPrintf("ERROR in ClaimTrieCache flush: %s\n", e.what()); + logPrint << "ERROR in ClaimTrieCache flush: " << e.what() << Clog::endl; auto code = e.get_code(); if (code == SQLITE_LOCKED || code == SQLITE_BUSY) { LogPrintf("Retrying the commit in one second.\n", e.what()); @@ -475,36 +519,25 @@ bool CClaimTrieCacheBase::flush() return true; } -bool CClaimTrieCacheBase::ValidateTipMatches(const CBlockIndex* tip) +bool CClaimTrieCacheBase::ReadFromDisk(int nHeight, const CUint256& rootHash) { - base->nNextHeight = nNextHeight = tip ? tip->nHeight + 1 : 0; + base->nNextHeight = nNextHeight = nHeight + 1; - LogPrintf("Checking claim trie consistency... "); + logPrint << "Checking claim trie consistency... " << Clog::endl; if (checkConsistency()) { - LogPrintf("consistent\n"); - if (tip && tip->hashClaimTrie != getMerkleHash()) { - // suppose we leave the old LevelDB data there: any harm done? It's ~10GB - // eh, we better blow it away; it's their job to back up the folder first - // well, only do it if we're empty on the sqlite side -- aka, we haven't trie to sync first - std::size_t count; - db << "SELECT COUNT(*) FROM nodes" >> count; - if (count <= 1) { - auto oldDataPath = GetDataDir() / "claimtrie"; - boost::system::error_code ec; - boost::filesystem::remove_all(oldDataPath, ec); - } - - return error("%s(): the block's root claim hash doesn't match the persisted claim root hash.", __func__); + logPrint << "consistent" << Clog::endl; + if (rootHash != getMerkleHash()) { + logPrint << "Merkle hash does not match root hash" << Clog::endl; + return false; } return true; } - LogPrintf("inconsistent!\n"); - + logPrint << "inconsistent!" << Clog::endl; return false; } CClaimTrieCacheBase::CClaimTrieCacheBase(CClaimTrie* base) - : base(base), db(base->dbPath, sharedConfig), transacting(false), + : base(base), db(base->db), transacting(false), childHashQuery(db << "SELECT name, hash, IFNULL(takeoverHeight, 0) FROM nodes WHERE parent = ? ORDER BY name"), claimHashQuery(db << "SELECT c.txID, c.txN, c.claimID, c.blockHeight, c.validHeight, c.amount, " "(SELECT IFNULL(SUM(s.amount),0)+c.amount FROM supports s WHERE s.supportedClaimID = c.claimID " @@ -526,13 +559,13 @@ CClaimTrieCacheBase::CClaimTrieCacheBase(CClaimTrie* base) int CClaimTrieCacheBase::expirationTime() const { - return Params().GetConsensus().nOriginalClaimExpirationTime; + return base->nOriginalClaimExpirationTime; } -uint256 CClaimTrieCacheBase::getMerkleHash() +CUint256 CClaimTrieCacheBase::getMerkleHash() { ensureTreeStructureIsUpToDate(); - std::unique_ptr hash; + std::unique_ptr hash; int takeoverHeight; // can't use childHashQuery here because "IS NULL" must be used instead of parent = NULL db << "SELECT hash, IFNULL(takeoverHeight, 0) FROM nodes WHERE name = ''" >> std::tie(hash, takeoverHeight); @@ -543,7 +576,7 @@ uint256 CClaimTrieCacheBase::getMerkleHash() return *hash; } -bool CClaimTrieCacheBase::getLastTakeoverForName(const std::string& name, uint160& claimId, int& takeoverHeight) const +bool CClaimTrieCacheBase::getLastTakeoverForName(const std::string& name, CUint160& claimId, int& takeoverHeight) const { auto query = db << "SELECT takeoverHeight, takeoverID FROM nodes WHERE name = ? AND takeoverID IS NOT NULL" << name; auto it = query.begin(); @@ -553,8 +586,8 @@ bool CClaimTrieCacheBase::getLastTakeoverForName(const std::string& name, uint16 return !claimId.IsNull(); } -bool CClaimTrieCacheBase::addClaim(const std::string& name, const COutPoint& outPoint, const uint160& claimId, - CAmount nAmount, int nHeight, int nValidHeight, const std::vector& metadata) +bool CClaimTrieCacheBase::addClaim(const std::string& name, const CTxOutPoint& outPoint, const CUint160& claimId, + int64_t nAmount, int nHeight, int nValidHeight, const std::vector& metadata) { if (!transacting) { transacting = true; db << "begin"; } @@ -584,8 +617,8 @@ bool CClaimTrieCacheBase::addClaim(const std::string& name, const COutPoint& out return true; } -bool CClaimTrieCacheBase::addSupport(const std::string& name, const COutPoint& outPoint, CAmount nAmount, - const uint160& supportedClaimId, int nHeight, int nValidHeight, const std::vector& metadata) +bool CClaimTrieCacheBase::addSupport(const std::string& name, const CTxOutPoint& outPoint, const CUint160& supportedClaimId, + int64_t nAmount, int nHeight, int nValidHeight, const std::vector& metadata) { if (!transacting) { transacting = true; db << "begin"; } @@ -603,7 +636,7 @@ bool CClaimTrieCacheBase::addSupport(const std::string& name, const COutPoint& o return true; } -bool CClaimTrieCacheBase::removeClaim(const uint160& claimId, const COutPoint& outPoint, std::string& nodeName, int& validHeight) +bool CClaimTrieCacheBase::removeClaim(const CUint160& claimId, const CTxOutPoint& outPoint, std::string& nodeName, int& validHeight) { if (!transacting) { transacting = true; db << "begin"; } @@ -640,11 +673,10 @@ bool CClaimTrieCacheBase::removeClaim(const uint160& claimId, const COutPoint& o } } } - return true; } -bool CClaimTrieCacheBase::removeSupport(const COutPoint& outPoint, std::string& nodeName, int& validHeight) +bool CClaimTrieCacheBase::removeSupport(const CTxOutPoint& outPoint, std::string& nodeName, int& validHeight) { if (!transacting) { transacting = true; db << "begin"; } @@ -1147,6 +1179,7 @@ bool CClaimTrieCacheBase::incrementBlock(insertUndoType& insertUndo, claimUndoTy expireSupportUndo.emplace_back(name, value); } } + db << "UPDATE nodes SET hash = NULL WHERE name IN (SELECT nodeName FROM supports WHERE expirationHeight = ?)" << nNextHeight; @@ -1156,10 +1189,10 @@ bool CClaimTrieCacheBase::incrementBlock(insertUndoType& insertUndo, claimUndoTy >> [&takeovers](std::string name) { takeovers.push_back(std::move(name)); }; + auto getTakeoverQuery = db << "SELECT IFNULL(takeoverHeight, 0), takeoverID FROM nodes WHERE name = ?"; auto hasCandidateQuery = db << "UPDATE nodes SET takeoverHeight = ?, takeoverID = ? WHERE name = ?"; auto noCandidateQuery = db << "UPDATE nodes SET takeoverHeight = NULL, takeoverID = NULL WHERE name = ?"; - auto maxWorkaround = Params().GetConsensus().nMaxTakeoverWorkaroundHeight; for (const auto& nameWithTakeover : takeovers) { // if somebody activates on this block and they are the new best, then everybody activates on this block @@ -1167,7 +1200,7 @@ bool CClaimTrieCacheBase::incrementBlock(insertUndoType& insertUndo, claimUndoTy auto hasCandidate = getInfoForName(nameWithTakeover, candidateValue, 1); // now that they're all in get the winner: int existingHeight; - std::unique_ptr existingID; + std::unique_ptr existingID; getTakeoverQuery << nameWithTakeover >> std::tie(existingHeight, existingID); getTakeoverQuery++; // reset it @@ -1179,15 +1212,15 @@ bool CClaimTrieCacheBase::incrementBlock(insertUndoType& insertUndo, claimUndoTy // This is a super ugly hack to work around bug in old code. // The bug: un/support a name then update it. This will cause its takeover height to be reset to current. // This is because the old code with add to the cache without setting block originals when dealing in supports. - if (nNextHeight < maxWorkaround) { + if (nNextHeight < 658300) { auto wit = takeoverWorkarounds.find(std::make_pair(nNextHeight, nameWithTakeover)); takeoverHappening |= wit != takeoverWorkarounds.end(); } - LogPrint(BCLog::CLAIMS, "Takeover on %s (%s) at %d, happening: %d, set before: %d\n", nameWithTakeover, HexStr(nameWithTakeover), nNextHeight, takeoverHappening, hasBeenSetBefore); + logPrint << "Takeover on " << nameWithTakeover << " at " << nNextHeight << ", happening: " << takeoverHappening << ", set before: " << hasBeenSetBefore << Clog::endl; if (takeoverHappening || !hasBeenSetBefore) { - takeoverUndo.emplace_back(nameWithTakeover, std::make_pair(existingHeight, hasBeenSetBefore ? *existingID : uint160())); + takeoverUndo.emplace_back(nameWithTakeover, std::make_pair(existingHeight, hasBeenSetBefore ? *existingID : CUint160())); if (hasCandidate) { hasCandidateQuery << nNextHeight << candidateValue.claimId << nameWithTakeover; hasCandidateQuery++; @@ -1203,25 +1236,24 @@ bool CClaimTrieCacheBase::incrementBlock(insertUndoType& insertUndo, claimUndoTy getTakeoverQuery.used(true); hasCandidateQuery.used(true); noCandidateQuery.used(true); - nNextHeight++; return true; } -bool CClaimTrieCacheBase::activateAllFor(insertUndoType& insertUndo, insertUndoType& insertSupportUndo, - const std::string& name) { +bool CClaimTrieCacheBase::activateAllFor(insertUndoType& insertUndo, insertUndoType& insertSupportUndo, const std::string& name) +{ // now that we know a takeover is happening, we bring everybody in: auto ret = false; { auto query = db << "SELECT txID, txN, validHeight FROM claims WHERE nodeName = ?1 AND validHeight > ?2 AND expirationHeight > ?2" << name << nNextHeight; for (auto &&row: query) { - uint256 hash; + CUint256 hash; uint32_t n; int oldValidHeight; row >> hash >> n >> oldValidHeight; - insertUndo.emplace_back(name, COutPoint(hash, n), oldValidHeight); - LogPrint(BCLog::CLAIMS, "Early activation of claim %s, t: %s:%d at %d\n", name, hash.GetHex().substr(0, 6), n, nNextHeight); + insertUndo.emplace_back(name, CTxOutPoint(hash, n), oldValidHeight); + logPrint << "Early activation of claim " << name << ", " << CTxOutPoint(hash, n).ToString() << " at " << nNextHeight << Clog::endl; } } // and then update them all to activate now: @@ -1234,12 +1266,12 @@ bool CClaimTrieCacheBase::activateAllFor(insertUndoType& insertUndo, insertUndoT auto query = db << "SELECT txID, txN, validHeight FROM supports WHERE nodeName = ?1 AND validHeight > ?2 AND expirationHeight > ?2" << name << nNextHeight; for (auto &&row: query) { - uint256 hash; + CUint256 hash; uint32_t n; int oldValidHeight; row >> hash >> n >> oldValidHeight; - insertSupportUndo.emplace_back(name, COutPoint(hash, n), oldValidHeight); - LogPrint(BCLog::CLAIMS, "Early activation of support %s, t: %s:%d at %d\n", name, hash.GetHex().substr(0, 6), n, nNextHeight); + insertSupportUndo.emplace_back(name, CTxOutPoint(hash, n), oldValidHeight); + logPrint << "Early activation of support " << name << ", " << CTxOutPoint(hash, n).ToString() << " at " << nNextHeight << Clog::endl; } } // and then update them all to activate now: @@ -1267,14 +1299,14 @@ bool CClaimTrieCacheBase::decrementBlock(insertUndoType& insertUndo, claimUndoTy } for (auto it = insertSupportUndo.crbegin(); it != insertSupportUndo.crend(); ++it) { - LogPrint(BCLog::CLAIMS, "Resetting support valid height to %d for %s\n", it->nValidHeight, it->name); + logPrint << "Resetting support valid height to " << it->nValidHeight << " for " << it->name << Clog::endl; db << "UPDATE supports SET validHeight = ? WHERE txID = ? AND txN = ?" << it->nValidHeight << it->outPoint.hash << it->outPoint.n; db << "INSERT INTO nodes(name) VALUES(?) ON CONFLICT(name) DO UPDATE SET hash = NULL" << it->name; } for (auto it = insertUndo.crbegin(); it != insertUndo.crend(); ++it) { - LogPrint(BCLog::CLAIMS, "Resetting valid height to %d for %s\n", it->nValidHeight, it->name); + logPrint << "Resetting valid height to " << it->nValidHeight << " for " << it->name << Clog::endl; db << "UPDATE claims SET validHeight = ? WHERE nodeName = ? AND txID = ? AND txN = ?" << it->nValidHeight << it->name << it->outPoint.hash << it->outPoint.n; db << "INSERT INTO nodes(name) VALUES(?) ON CONFLICT(name) DO UPDATE SET hash = NULL" << it->name; @@ -1300,9 +1332,9 @@ bool CClaimTrieCacheBase::finalizeDecrement(takeoverUndoType& takeoverUndo) return true; } -int CClaimTrieCacheBase::getDelayForName(const std::string& name, const uint160& claimId) const +int CClaimTrieCacheBase::getDelayForName(const std::string& name, const CUint160& claimId) const { - uint160 winningClaimId; + CUint160 winningClaimId; int winningTakeoverHeight; auto found = getLastTakeoverForName(name, winningClaimId, winningTakeoverHeight); if (found && winningClaimId == claimId) { @@ -1326,7 +1358,7 @@ std::string CClaimTrieCacheBase::adjustNameForValidHeight(const std::string& nam return name; } -bool CClaimTrieCacheBase::getProofForName(const std::string& name, const uint160& finalClaim, CClaimTrieProof& proof) +bool CClaimTrieCacheBase::getProofForName(const std::string& name, const CUint160& finalClaim, CClaimTrieProof& proof) { // cache the parent nodes getMerkleHash(); @@ -1341,25 +1373,25 @@ bool CClaimTrieCacheBase::getProofForName(const std::string& name, const uint160 int takeoverHeight; row >> key >> takeoverHeight; bool fNodeHasValue = getInfoForName(key, claim); - uint256 valueHash; + CUint256 valueHash; if (fNodeHasValue) valueHash = getValueHash(claim.outPoint, takeoverHeight); const auto pos = key.size(); - std::vector> children; + std::vector> children; for (auto&& child : childHashQuery << key) { std::string childKey; - uint256 hash; + CUint256 hash; child >> childKey >> hash; if (name.find(childKey) == 0) { for (auto i = pos; i + 1 < childKey.size(); ++i) { - children.emplace_back(childKey[i], uint256{}); + children.emplace_back(childKey[i], CUint256{}); proof.nodes.emplace_back(children, fNodeHasValue, valueHash); children.clear(); valueHash.SetNull(); fNodeHasValue = false; } - children.emplace_back(childKey.back(), uint256{}); + children.emplace_back(childKey.back(), CUint256{}); continue; } completeHash(hash, childKey, pos); @@ -1379,7 +1411,8 @@ bool CClaimTrieCacheBase::getProofForName(const std::string& name, const uint160 return true; } -bool CClaimTrieCacheBase::findNameForClaim(std::vector claim, CClaimValue& value, std::string& name) { +bool CClaimTrieCacheBase::findNameForClaim(std::vector claim, CClaimValue& value, std::string& name) +{ std::reverse(claim.begin(), claim.end()); auto query = db << "SELECT nodeName, claimId, txID, txN, amount, validHeight, blockHeight " "FROM claims WHERE SUBSTR(claimID, ?) = ? AND validHeight < ? AND expirationHeight >= ?" diff --git a/src/claimtrie/trie.h b/src/claimtrie/trie.h new file mode 100644 index 000000000..31e4c73c6 --- /dev/null +++ b/src/claimtrie/trie.h @@ -0,0 +1,207 @@ +#ifndef CLAIMTRIE_TRIE_H +#define CLAIMTRIE_TRIE_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +CUint256 getValueHash(const CTxOutPoint& outPoint, int nHeightOfLastTakeover); + +struct CClaimNsupports +{ + CClaimNsupports() = default; + CClaimNsupports(CClaimNsupports&&) = default; + CClaimNsupports(const CClaimNsupports&) = default; + + bool operator<(const CClaimNsupports& other) const; + CClaimNsupports& operator=(CClaimNsupports&&) = default; + CClaimNsupports& operator=(const CClaimNsupports&) = default; + + CClaimNsupports(CClaimValue claim, int64_t effectiveAmount, std::vector supports = {}); + + bool IsNull() const; + + CClaimValue claim; + int64_t effectiveAmount = 0; + std::vector supports; +}; + +struct CClaimSupportToName +{ + CClaimSupportToName(std::string name, int nLastTakeoverHeight, std::vector claimsNsupports, std::vector unmatchedSupports); + + const CClaimNsupports& find(const CUint160& claimId) const; + const CClaimNsupports& find(const std::string& partialId) const; + + const std::string name; + const int nLastTakeoverHeight; + const std::vector claimsNsupports; + const std::vector unmatchedSupports; +}; + +class CClaimTrie +{ + friend class CClaimTrieCacheBase; + friend class ClaimTrieChainFixture; + friend class CClaimTrieCacheHashFork; + friend class CClaimTrieCacheExpirationFork; + friend class CClaimTrieCacheNormalizationFork; +public: + CClaimTrie() = default; + CClaimTrie(CClaimTrie&&) = delete; + CClaimTrie(const CClaimTrie&) = delete; + CClaimTrie(bool fWipe, int height, + int nNormalizedNameForkHeight, + int64_t nOriginalClaimExpirationTime, + int64_t nExtendedClaimExpirationTime, + int64_t nExtendedClaimExpirationForkHeight, + int64_t nAllClaimsInMerkleForkHeight, + int proportionalDelayFactor = 32); + + CClaimTrie& operator=(CClaimTrie&&) = delete; + CClaimTrie& operator=(const CClaimTrie&) = delete; + + bool empty(); + bool SyncToDisk(); + +protected: + int nNextHeight = 0; + sqlite::database db; + const int nProportionalDelayFactor = 0; + + const int nNormalizedNameForkHeight = -1; + const int64_t nOriginalClaimExpirationTime = -1; + const int64_t nExtendedClaimExpirationTime = -1; + const int64_t nExtendedClaimExpirationForkHeight = -1; + const int64_t nAllClaimsInMerkleForkHeight = -1; +}; + +struct CClaimTrieProofNode +{ + CClaimTrieProofNode(std::vector> children, bool hasValue, CUint256 valHash); + + CClaimTrieProofNode(CClaimTrieProofNode&&) = default; + CClaimTrieProofNode(const CClaimTrieProofNode&) = default; + CClaimTrieProofNode& operator=(CClaimTrieProofNode&&) = default; + CClaimTrieProofNode& operator=(const CClaimTrieProofNode&) = default; + + std::vector> children; + bool hasValue; + CUint256 valHash; +}; + +struct CClaimTrieProof +{ + CClaimTrieProof() = default; + CClaimTrieProof(CClaimTrieProof&&) = default; + CClaimTrieProof(const CClaimTrieProof&) = default; + CClaimTrieProof& operator=(CClaimTrieProof&&) = default; + CClaimTrieProof& operator=(const CClaimTrieProof&) = default; + + std::vector> pairs; + std::vector nodes; + int nHeightOfLastTakeover = 0; + bool hasValue = false; + CTxOutPoint outPoint; +}; + +template +using queueEntryType = std::pair; + +typedef std::vector> claimUndoType; +typedef std::vector> supportUndoType; +typedef std::vector insertUndoType; +typedef std::vector>> takeoverUndoType; + +class CClaimTrieCacheBase +{ +public: + explicit CClaimTrieCacheBase(CClaimTrie* base); + virtual ~CClaimTrieCacheBase(); + + CUint256 getMerkleHash(); + + bool flush(); + bool empty() const; + bool checkConsistency(); + bool ReadFromDisk(int nHeight, const CUint256& rootHash); + + std::size_t getTotalNamesInTrie() const; + std::size_t getTotalClaimsInTrie() const; + int64_t getTotalValueOfClaimsInTrie(bool fControllingOnly) const; + + bool haveClaim(const std::string& name, const CTxOutPoint& outPoint) const; + bool haveClaimInQueue(const std::string& name, const CTxOutPoint& outPoint, int& nValidAtHeight) const; + + bool haveSupport(const std::string& name, const CTxOutPoint& outPoint) const; + bool haveSupportInQueue(const std::string& name, const CTxOutPoint& outPoint, int& nValidAtHeight) const; + + bool addClaim(const std::string& name, const CTxOutPoint& outPoint, const CUint160& claimId, int64_t nAmount, + int nHeight, int nValidHeight = -1, const std::vector& metadata = {}); + + bool addSupport(const std::string& name, const CTxOutPoint& outPoint, const CUint160& supportedClaimId, int64_t nAmount, + int nHeight, int nValidHeight = -1, const std::vector& metadata = {}); + + bool removeClaim(const CUint160& claimId, const CTxOutPoint& outPoint, std::string& nodeName, int& validHeight); + bool removeSupport(const CTxOutPoint& outPoint, std::string& nodeName, int& validHeight); + + virtual bool incrementBlock(insertUndoType& insertUndo, + claimUndoType& expireUndo, + insertUndoType& insertSupportUndo, + supportUndoType& expireSupportUndo, + takeoverUndoType& takeoverHeightUndo); + + virtual bool decrementBlock(insertUndoType& insertUndo, + claimUndoType& expireUndo, + insertUndoType& insertSupportUndo, + supportUndoType& expireSupportUndo); + + virtual bool getProofForName(const std::string& name, const CUint160& claim, CClaimTrieProof& proof); + virtual bool getInfoForName(const std::string& name, CClaimValue& claim, int heightOffset = 0) const; + + virtual int expirationTime() const; + + virtual bool finalizeDecrement(takeoverUndoType& takeoverHeightUndo); + + virtual CClaimSupportToName getClaimsForName(const std::string& name) const; + virtual std::string adjustNameForValidHeight(const std::string& name, int validHeight) const; + + bool findNameForClaim(std::vector claim, CClaimValue& value, std::string& name); + void getNamesInTrie(std::function callback); + bool getLastTakeoverForName(const std::string& name, CUint160& claimId, int& takeoverHeight) const; + +protected: + CClaimTrie* base; + mutable sqlite::database db; + int nNextHeight; // Height of the block that is being worked on, which is + bool transacting; + mutable std::unordered_set removalWorkaround; + + mutable sqlite::database_binder claimHashQuery, childHashQuery; + + virtual CUint256 recursiveComputeMerkleHash(const std::string& name, int takeoverHeight, bool checkOnly); + supportEntryType getSupportsForName(const std::string& name) const; + + virtual int getDelayForName(const std::string& name, const CUint160& claimId) const; + + bool deleteNodeIfPossible(const std::string& name, std::string& parent, int64_t& claims); + void ensureTreeStructureIsUpToDate(); + +private: + // for unit test + friend struct ClaimTrieChainFixture; + friend class CClaimTrieCacheTest; + + bool activateAllFor(insertUndoType& insertUndo, insertUndoType& insertSupportUndo, const std::string& takeover); +}; + +#endif // CLAIMTRIE_TRIE_H diff --git a/src/claimtrie/txoutpoint.cpp b/src/claimtrie/txoutpoint.cpp new file mode 100644 index 000000000..20c4c550d --- /dev/null +++ b/src/claimtrie/txoutpoint.cpp @@ -0,0 +1,42 @@ + +#include + +#include + +CTxOutPoint::CTxOutPoint(CUint256 hashIn, uint32_t nIn) : hash(std::move(hashIn)), n(nIn) +{ +} + +void CTxOutPoint::SetNull() +{ + hash.SetNull(); + n = uint32_t(-1); +} + +bool CTxOutPoint::IsNull() const +{ + return hash.IsNull() && n == uint32_t(-1); +} + +std::string CTxOutPoint::ToString() const +{ + std::stringstream ss; + ss << "CTxOutPoint(" << hash.ToString().substr(0, 10) << ", " << n << ')'; + return ss.str(); +} + +bool operator<(const CTxOutPoint& a, const CTxOutPoint& b) +{ + int cmp = a.hash.Compare(b.hash); + return cmp < 0 || (cmp == 0 && a.n < b.n); +} + +bool operator==(const CTxOutPoint& a, const CTxOutPoint& b) +{ + return (a.hash == b.hash && a.n == b.n); +} + +bool operator!=(const CTxOutPoint& a, const CTxOutPoint& b) +{ + return !(a == b); +} diff --git a/src/claimtrie/txoutpoint.h b/src/claimtrie/txoutpoint.h new file mode 100644 index 000000000..d057e69bf --- /dev/null +++ b/src/claimtrie/txoutpoint.h @@ -0,0 +1,37 @@ + +#ifndef CLAIMTRIE_TXOUTPUT_H +#define CLAIMTRIE_TXOUTPUT_H + +#include + +#include +#include +#include +#include + +/** An outpoint - a combination of a transaction hash and an index n into its vout */ +class CTxOutPoint +{ +public: + CUint256 hash; + uint32_t n = uint32_t(-1); + + CTxOutPoint() = default; + CTxOutPoint(CTxOutPoint&&) = default; + CTxOutPoint(const CTxOutPoint&) = default; + CTxOutPoint(CUint256 hashIn, uint32_t nIn); + + CTxOutPoint& operator=(CTxOutPoint&&) = default; + CTxOutPoint& operator=(const CTxOutPoint&) = default; + + void SetNull(); + bool IsNull() const; + + friend bool operator<(const CTxOutPoint& a, const CTxOutPoint& b); + friend bool operator==(const CTxOutPoint& a, const CTxOutPoint& b); + friend bool operator!=(const CTxOutPoint& a, const CTxOutPoint& b); + + std::string ToString() const; +}; + +#endif // CLAIMTRIE_TXOUTPUT_H diff --git a/src/claimtrie/uints.cpp b/src/claimtrie/uints.cpp new file mode 100644 index 000000000..b0e4cc8e7 --- /dev/null +++ b/src/claimtrie/uints.cpp @@ -0,0 +1,155 @@ + +#include + +#include +#include +#include +#include +#include + +/** Template base class for fixed-sized opaque blobs. */ +template +CBaseBlob::CBaseBlob() : data(std::make_unique(WIDTH)) +{ + SetNull(); +} + +template +CBaseBlob::CBaseBlob(const std::vector& vec) : data(std::make_unique(WIDTH)) +{ + assert(vec.size() == size()); + std::copy(vec.begin(), vec.end(), begin()); +} + +template +CBaseBlob::CBaseBlob(const CBaseBlob& o) : data(std::make_unique(WIDTH)) +{ + *this = o; +} + +template +CBaseBlob& CBaseBlob::operator=(const CBaseBlob& o) +{ + if (this != &o) + std::copy(o.begin(), o.end(), begin()); + return *this; +} + +template +bool CBaseBlob::IsNull() const +{ + return std::all_of(begin(), end(), [](uint8_t e) { return e == 0; }); +} + +template +void CBaseBlob::SetNull() +{ + std::memset(begin(), 0, size()); +} + +template +int CBaseBlob::Compare(const CBaseBlob& other) const +{ + return std::memcmp(begin(), other.begin(), size()); +} + +template +std::string CBaseBlob::GetHex() const +{ + std::stringstream ss; + ss << std::hex; + for (int i = WIDTH - 1; i >= 0; --i) + ss << std::setw(2) << std::setfill('0') << uint32_t(data[i]); + return ss.str(); +} + +template +void CBaseBlob::SetHex(const char* psz) +{ + SetNull(); + + // skip leading spaces + while (isspace(*psz)) + psz++; + + // skip 0x + if (psz[0] == '0' && tolower(psz[1]) == 'x') + psz += 2; + + auto b = psz; + // advance to end + while (isxdigit(*psz)) + psz++; + + --psz; + char buf[3] = {}; + auto it = begin(); + while (psz >= b && it != end()) { + buf[1] = *psz--; + buf[0] = psz >= b ? *psz-- : '0'; + *it++ = std::strtoul(buf, nullptr, 16); + } +} + +template +void CBaseBlob::SetHex(const std::string& str) +{ + SetHex(str.c_str()); +} + +template +std::string CBaseBlob::ToString() const +{ + return GetHex(); +} + +template +uint8_t* CBaseBlob::begin() +{ + return data.get(); +} + +template +uint8_t* CBaseBlob::end() +{ + return begin() + WIDTH; +} + +template +const uint8_t* CBaseBlob::begin() const +{ + return data.get(); +} + +template +const uint8_t* CBaseBlob::end() const +{ + return begin() + WIDTH; +} + +CUint160 CUint160S(const char* str) +{ + CUint160 s; + s.SetHex(str); + return s; +} + +CUint160 CUint160S(const std::string& s) +{ + return CUint160S(s.c_str()); +} + +CUint256 CUint256S(const char* str) +{ + CUint256 s; + s.SetHex(str); + return s; +} + +CUint256 CUint256S(const std::string& s) +{ + return CUint256S(s.c_str()); +} + +template class CBaseBlob<160>; +template class CBaseBlob<256>; diff --git a/src/claimtrie/uints.h b/src/claimtrie/uints.h new file mode 100644 index 000000000..fbc3e8fc5 --- /dev/null +++ b/src/claimtrie/uints.h @@ -0,0 +1,59 @@ + +#ifndef CLAIMTRIE_UINTS_H +#define CLAIMTRIE_UINTS_H + +#include +#include + +/** Template base class for fixed-sized opaque blobs. */ +template +class CBaseBlob +{ +protected: + static constexpr int WIDTH = BITS / 8; + std::unique_ptr data; +public: + CBaseBlob(); + + explicit CBaseBlob(const std::vector& vec); + + CBaseBlob(CBaseBlob&&) = default; + CBaseBlob& operator=(CBaseBlob&&) = default; + + CBaseBlob(const CBaseBlob& o); + CBaseBlob& operator=(const CBaseBlob& o); + + bool IsNull() const; + void SetNull(); + + int Compare(const CBaseBlob& other) const; + + friend inline bool operator==(const CBaseBlob& a, const CBaseBlob& b) { return a.Compare(b) == 0; } + friend inline bool operator!=(const CBaseBlob& a, const CBaseBlob& b) { return a.Compare(b) != 0; } + friend inline bool operator<(const CBaseBlob& a, const CBaseBlob& b) { return a.Compare(b) < 0; } + + std::string GetHex() const; + void SetHex(const char* psz); + void SetHex(const std::string& str); + + std::string ToString() const; + + uint8_t* begin(); + uint8_t* end(); + + const uint8_t* begin() const; + const uint8_t* end() const; + + constexpr uint32_t size() const { return WIDTH; } +}; + +typedef CBaseBlob<160> CUint160; +typedef CBaseBlob<256> CUint256; + +CUint160 CUint160S(const char* str); +CUint160 CUint160S(const std::string& s); + +CUint256 CUint256S(const char* str); +CUint256 CUint256S(const std::string& s); + +#endif // CLAIMTRIE_UINTS_H diff --git a/src/claimtrie_serial.h b/src/claimtrie_serial.h new file mode 100644 index 000000000..e78db0244 --- /dev/null +++ b/src/claimtrie_serial.h @@ -0,0 +1,105 @@ + +#ifndef CLAIMTRIE_SERIAL_H +#define CLAIMTRIE_SERIAL_H + +#include +#include +#include + +template +void Serialize(Stream& s, const CBaseBlob& u) +{ + s.write((const char*)u.begin(), u.size()); +} + +template +void Unserialize(Stream& s, CBaseBlob& u) +{ + s.read((char*)u.begin(), u.size()); +} + +template +void Serialize(Stream& s, const CTxOutPoint& u) +{ + Serialize(s, u.hash); + Serialize(s, u.n); +} + +template +void Unserialize(Stream& s, CTxOutPoint& u) +{ + Unserialize(s, u.hash); + Unserialize(s, u.n); +} + +template +void Serialize(Stream& s, const CClaimValue& u) +{ + Serialize(s, u.outPoint); + Serialize(s, u.claimId); + Serialize(s, u.nAmount); + Serialize(s, u.nHeight); + Serialize(s, u.nValidAtHeight); +} + +template +void Unserialize(Stream& s, CClaimValue& u) +{ + Unserialize(s, u.outPoint); + Unserialize(s, u.claimId); + Unserialize(s, u.nAmount); + Unserialize(s, u.nHeight); + Unserialize(s, u.nValidAtHeight); +} + +template +void Serialize(Stream& s, const CSupportValue& u) +{ + Serialize(s, u.outPoint); + Serialize(s, u.supportedClaimId); + Serialize(s, u.nAmount); + Serialize(s, u.nHeight); + Serialize(s, u.nValidAtHeight); +} + +template +void Unserialize(Stream& s, CSupportValue& u) +{ + Unserialize(s, u.outPoint); + Unserialize(s, u.supportedClaimId); + Unserialize(s, u.nAmount); + Unserialize(s, u.nHeight); + Unserialize(s, u.nValidAtHeight); +} + +template +void Serialize(Stream& s, const CNameOutPointHeightType& u) +{ + Serialize(s, u.name); + Serialize(s, u.outPoint); + Serialize(s, u.nValidHeight); +} + +template +void Unserialize(Stream& s, CNameOutPointHeightType& u) +{ + Unserialize(s, u.name); + Unserialize(s, u.outPoint); + Unserialize(s, u.nValidHeight); +} + +template +void Serialize(Stream& s, const CClaimIndexElement& u) +{ + Serialize(s, u.name); + Serialize(s, u.claim); +} + +template +void Unserialize(Stream& s, CClaimIndexElement& u) +{ + Unserialize(s, u.name); + Unserialize(s, u.claim); +} + +#endif // CLAIMTRIE_SERIAL_H diff --git a/src/consensus/params.h b/src/consensus/params.h index 9534d8834..4ca74edbd 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -78,9 +78,6 @@ struct Params { int nAllowMinDiffMaxHeight; int nNormalizedNameForkHeight; - int nMinTakeoverWorkaroundHeight; - int nMaxTakeoverWorkaroundHeight; - int nWitnessForkHeight; int64_t nPowTargetSpacing; diff --git a/src/init.cpp b/src/init.cpp index be92cb3db..d3082efce 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -1455,7 +1455,16 @@ bool AppInitMain() pblocktree.reset(); pblocktree.reset(new CBlockTreeDB(nBlockTreeDBCache, false, fReset)); delete pclaimTrie; - pclaimTrie = new CClaimTrie(fReindex || fReindexChainState, 0); + auto& consensus = chainparams.GetConsensus(); + if (g_logger->Enabled() && LogAcceptCategory(BCLog::CLAIMS)) + CLogPrint::global().setLogger(g_logger); + pclaimTrie = new CClaimTrie(fReindex || fReindexChainState, 0, + consensus.nNormalizedNameForkHeight, + consensus.nOriginalClaimExpirationTime, + consensus.nExtendedClaimExpirationTime, + consensus.nExtendedClaimExpirationForkHeight, + consensus.nAllClaimsInMerkleForkHeight, + 32); if (fReset) { pblocktree->WriteReindexing(true); @@ -1528,12 +1537,12 @@ bool AppInitMain() } assert(chainActive.Tip() != nullptr); } - { - CClaimTrieCache trieCache(pclaimTrie); - if (!trieCache.ValidateTipMatches(chainActive.Tip())) { - strLoadError = _("Error loading the claim trie from disk"); - break; - } + auto tip = chainActive.Tip(); + assert(tip); + CClaimTrieCache trieCache(pclaimTrie); + if (!trieCache.ReadFromDisk(tip->nHeight, tip->hashClaimTrie)) { + strLoadError = _("Error loading the claim trie from disk"); + break; } if (!fReset) { // Note that RewindBlockIndex MUST run even if we're about to -reindex-chainstate. diff --git a/src/lbry.cpp b/src/lbry.cpp index 921db7ade..6aa94d644 100644 --- a/src/lbry.cpp +++ b/src/lbry.cpp @@ -3,8 +3,6 @@ #include -uint32_t g_memfileSize = 0; - unsigned int CalculateLbryNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params) { if (params.fPowNoRetargeting) diff --git a/src/lbry.h b/src/lbry.h index aa7fc331b..601ccc4a3 100644 --- a/src/lbry.h +++ b/src/lbry.h @@ -4,7 +4,6 @@ #include #include -extern uint32_t g_memfileSize; unsigned int CalculateLbryNextWorkRequired(const CBlockIndex* pindexLast, int64_t nLastRetargetTime, const Consensus::Params& params); #endif diff --git a/src/logging.h b/src/logging.h index 9cbac42f7..ebeee1eec 100644 --- a/src/logging.h +++ b/src/logging.h @@ -6,6 +6,7 @@ #ifndef BITCOIN_LOGGING_H #define BITCOIN_LOGGING_H +#include #include #include @@ -57,7 +58,7 @@ namespace BCLog { ALL = ~(uint32_t)0, }; - class Logger + class Logger : public ClogBase { private: FILE* m_fileout = nullptr; @@ -87,7 +88,7 @@ namespace BCLog { std::atomic m_reopen_file{false}; /** Send a string to the log output */ - void LogPrintStr(const std::string &str); + void LogPrintStr(const std::string &str) override; /** Returns whether logs will be written to any output */ bool Enabled() const { return m_print_to_console || m_print_to_file; } diff --git a/src/miner.cpp b/src/miner.cpp index 26da8835c..5c45492af 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -204,7 +205,7 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc { CClaimTrieCache trieCache(pclaimTrie); blockToCache(pblock, trieCache, nHeight); - pblock->hashClaimTrie = trieCache.getMerkleHash(); + pblock->hashClaimTrie = uint256(trieCache.getMerkleHash()); } CValidationState state; if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) { diff --git a/src/nameclaim.cpp b/src/nameclaim.cpp index 5decd4f75..17c448325 100644 --- a/src/nameclaim.cpp +++ b/src/nameclaim.cpp @@ -68,14 +68,10 @@ bool DecodeClaimScript(const CScript& scriptIn, int& op, std::vector OP_PUSHDATA4) - { return false; - } + if (!scriptIn.GetOp(pc, opcode, vchParam2) || opcode < 0 || opcode > OP_PUSHDATA4) - { return false; - } + if (op == OP_UPDATE_CLAIM || op == OP_SUPPORT_CLAIM) - { - static const size_t claimIdHashSize = sizeof(uint160); - if (vchParam2.size() != claimIdHashSize) { + if (vchParam2.size() != sizeof(uint160)) return false; - } - } if (!scriptIn.GetOp(pc, opcode, vchParam3)) - { return false; - } + auto last_drop = OP_DROP; - if (opcode >= 0 && opcode <= OP_PUSHDATA4 && op != OP_CLAIM_NAME) - { + if (opcode >= 0 && opcode <= OP_PUSHDATA4 && op != OP_CLAIM_NAME) { if (!scriptIn.GetOp(pc, opcode)) - { return false; - } last_drop = OP_2DROP; - } - else if (op == OP_UPDATE_CLAIM) - { + } else if (op == OP_UPDATE_CLAIM) return false; - } + if (opcode != OP_2DROP) - { return false; - } + if (!scriptIn.GetOp(pc, opcode) || opcode != last_drop) - { return false; - } + if (op == OP_SUPPORT_CLAIM && last_drop == OP_2DROP && !allowSupportMetadata) - { return false; - } vvchParams.push_back(std::move(vchParam1)); vvchParams.push_back(std::move(vchParam2)); if (last_drop == OP_2DROP) - { vvchParams.push_back(std::move(vchParam3)); - } + return true; } @@ -164,9 +143,7 @@ CScript StripClaimScriptPrefix(const CScript& scriptIn, int& op) CScript::const_iterator pc = scriptIn.begin(); if (!DecodeClaimScript(scriptIn, op, vvchParams, pc)) - { return scriptIn; - } return CScript(pc, scriptIn.end()); } @@ -183,31 +160,21 @@ size_t ClaimNameSize(const CScript& scriptIn) CScript::const_iterator pc = scriptIn.begin(); int op; if (!DecodeClaimScript(scriptIn, op, vvchParams, pc)) - { return 0; - } - else - { - return vvchParams[0].size(); - } + return vvchParams[0].size(); } CAmount CalcMinClaimTrieFee(const CTransaction& tx, const CAmount &minFeePerNameClaimChar) { if (minFeePerNameClaimChar == 0) - { return 0; - } CAmount min_fee = 0; - for (const CTxOut& txout: tx.vout) - { + for (const CTxOut& txout: tx.vout) { int op; std::vector > vvchParams; - if (DecodeClaimScript(txout.scriptPubKey, op, vvchParams)) - { - if (op == OP_CLAIM_NAME) - { + if (DecodeClaimScript(txout.scriptPubKey, op, vvchParams)) { + if (op == OP_CLAIM_NAME) { int claim_name_size = vvchParams[0].size(); min_fee += claim_name_size*minFeePerNameClaimChar; } diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index fb9db508d..90b868161 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -8,6 +8,7 @@ #include #include +#include #include