Introduce libclaimtrie

Signed-off-by: Anthony Fieroni <bvbfan@abv.bg>
This commit is contained in:
Anthony Fieroni 2019-10-09 18:09:30 +03:00 committed by Brannon King
parent 61625c0eef
commit 53a61258e1
61 changed files with 1461 additions and 905 deletions

View file

@ -29,6 +29,7 @@ LIBBITCOIN_COMMON=libbitcoin_common.a
LIBBITCOIN_CONSENSUS=libbitcoin_consensus.a LIBBITCOIN_CONSENSUS=libbitcoin_consensus.a
LIBBITCOIN_CLI=libbitcoin_cli.a LIBBITCOIN_CLI=libbitcoin_cli.a
LIBBITCOIN_UTIL=libbitcoin_util.a LIBBITCOIN_UTIL=libbitcoin_util.a
LIBCLAIMTRIE=claimtrie/libclaimtrie.a
LIBBITCOIN_CRYPTO_BASE=crypto/libbitcoin_crypto_base.a LIBBITCOIN_CRYPTO_BASE=crypto/libbitcoin_crypto_base.a
LIBBITCOINQT=qt/libbitcoinqt.a LIBBITCOINQT=qt/libbitcoinqt.a
LIBSECP256K1=secp256k1/libsecp256k1.la 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 # 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: # But to build the less dependent modules first, we manually select their order here:
EXTRA_LIBRARIES += \ EXTRA_LIBRARIES += \
$(LIBCLAIMTRIE) \
$(LIBBITCOIN_CRYPTO) \ $(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_COMMON) \
@ -103,7 +105,7 @@ BITCOIN_CORE_H = \
checkpoints.h \ checkpoints.h \
checkqueue.h \ checkqueue.h \
claimscriptop.h \ claimscriptop.h \
claimtrie.h \ claimtrie_serial.h \
clientversion.h \ clientversion.h \
coins.h \ coins.h \
compat.h \ compat.h \
@ -170,8 +172,6 @@ BITCOIN_CORE_H = \
script/standard.h \ script/standard.h \
shutdown.h \ shutdown.h \
streams.h \ streams.h \
sqlite/sqlite3.h \
sqlite/hdr/sqlite_modern_cpp.h \
support/allocators/secure.h \ support/allocators/secure.h \
support/allocators/zeroafterfree.h \ support/allocators/zeroafterfree.h \
support/cleanse.h \ support/cleanse.h \
@ -223,7 +223,6 @@ libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h
# server: shared between lbrycrdd and lbrycrd-qt # 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_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS)
libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_server_a_CFLAGS = $(PIE_FLAGS)
libbitcoin_server_a_SOURCES = \ libbitcoin_server_a_SOURCES = \
addrdb.cpp \ addrdb.cpp \
addrman.cpp \ addrman.cpp \
@ -232,8 +231,6 @@ libbitcoin_server_a_SOURCES = \
chain.cpp \ chain.cpp \
checkpoints.cpp \ checkpoints.cpp \
claimscriptop.cpp \ claimscriptop.cpp \
claimtrie.cpp \
claimtrieforks.cpp \
consensus/tx_verify.cpp \ consensus/tx_verify.cpp \
httprpc.cpp \ httprpc.cpp \
httpserver.cpp \ httpserver.cpp \
@ -263,7 +260,6 @@ libbitcoin_server_a_SOURCES = \
rpc/server.cpp \ rpc/server.cpp \
rpc/util.cpp \ rpc/util.cpp \
script/sigcache.cpp \ script/sigcache.cpp \
sqlite/sqlite3.c \
shutdown.cpp \ shutdown.cpp \
timedata.cpp \ timedata.cpp \
torcontrol.cpp \ torcontrol.cpp \
@ -415,6 +411,20 @@ libbitcoin_common_a_SOURCES = \
warnings.cpp \ warnings.cpp \
$(BITCOIN_CORE_H) $(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. # util: shared between all executables.
# This library *must* be included to make sure that the glibc # This library *must* be included to make sure that the glibc
# backward-compatibility objects and their sanity checks are linked. # backward-compatibility objects and their sanity checks are linked.
@ -482,7 +492,7 @@ lbrycrdd_LDADD = \
$(LIBMEMENV) \ $(LIBMEMENV) \
$(LIBSECP256K1) $(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 binary #
lbrycrd_cli_SOURCES = bitcoin-cli.cpp lbrycrd_cli_SOURCES = bitcoin-cli.cpp
@ -500,7 +510,7 @@ lbrycrd_cli_LDADD = \
$(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CRYPTO) $(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 # # bitcoin-tx binary #
@ -521,7 +531,7 @@ lbrycrd_tx_LDADD = \
$(LIBBITCOIN_CRYPTO) \ $(LIBBITCOIN_CRYPTO) \
$(LIBSECP256K1) $(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 # # bitcoinconsensus library #

View file

@ -55,7 +55,7 @@ if ENABLE_WALLET
bench_bench_bitcoin_SOURCES += bench/coin_selection.cpp bench_bench_bitcoin_SOURCES += bench/coin_selection.cpp
endif 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) bench_bench_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
CLEAN_BITCOIN_BENCH = bench/*.gcda bench/*.gcno $(GENERATED_BENCH_FILES) CLEAN_BITCOIN_BENCH = bench/*.gcda bench/*.gcno $(GENERATED_BENCH_FILES)

View file

@ -409,7 +409,7 @@ if ENABLE_ZMQ
qt_lbrycrd_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) qt_lbrycrd_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
endif endif
qt_lbrycrd_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \ 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) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
qt_lbrycrd_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) qt_lbrycrd_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
qt_lbrycrd_qt_LIBTOOLFLAGS = $(AM_LIBTOOLFLAGS) --tag CXX qt_lbrycrd_qt_LIBTOOLFLAGS = $(AM_LIBTOOLFLAGS) --tag CXX

View file

@ -63,7 +63,7 @@ if ENABLE_ZMQ
qt_test_test_lbrycrd_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) qt_test_test_lbrycrd_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
endif endif
qt_test_test_lbrycrd_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) \ 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) \ $(QR_LIBS) $(PROTOBUF_LIBS) $(ICU_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
qt_test_test_lbrycrd_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) qt_test_test_lbrycrd_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)

View file

@ -126,7 +126,7 @@ test_test_lbrycrd_LDADD += $(LIBBITCOIN_WALLET)
endif endif
test_test_lbrycrd_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) \ 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_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_test_lbrycrd_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(CRYPTO_LIBS) $(ICU_LIBS) $(MINIUPNPC_LIBS) 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) \ $(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1) $(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) nodist_test_test_lbrycrd_SOURCES = $(GENERATED_TEST_FILES)

View file

@ -143,8 +143,6 @@ public:
consensus.nAllowMinDiffMinHeight = -1; consensus.nAllowMinDiffMinHeight = -1;
consensus.nAllowMinDiffMaxHeight = -1; consensus.nAllowMinDiffMaxHeight = -1;
consensus.nNormalizedNameForkHeight = 539940; // targeting 21 March 2019 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.nWitnessForkHeight = 680770; // targeting 11 Dec 2019
consensus.nAllClaimsInMerkleForkHeight = 658310; // targeting 30 Oct 2019 consensus.nAllClaimsInMerkleForkHeight = 658310; // targeting 30 Oct 2019
consensus.fPowAllowMinDifficultyBlocks = false; consensus.fPowAllowMinDifficultyBlocks = false;
@ -261,8 +259,6 @@ public:
consensus.nAllowMinDiffMinHeight = 277299; consensus.nAllowMinDiffMinHeight = 277299;
consensus.nAllowMinDiffMaxHeight = 1100000; consensus.nAllowMinDiffMaxHeight = 1100000;
consensus.nNormalizedNameForkHeight = 993380; // targeting, 21 Feb 2019 consensus.nNormalizedNameForkHeight = 993380; // targeting, 21 Feb 2019
consensus.nMinTakeoverWorkaroundHeight = 99;
consensus.nMaxTakeoverWorkaroundHeight = 1198550; // targeting 30 Sep 2019
consensus.nWitnessForkHeight = 1198600; consensus.nWitnessForkHeight = 1198600;
consensus.nAllClaimsInMerkleForkHeight = 1198560; // targeting 30 Sep 2019 consensus.nAllClaimsInMerkleForkHeight = 1198560; // targeting 30 Sep 2019
consensus.fPowAllowMinDifficultyBlocks = true; consensus.fPowAllowMinDifficultyBlocks = true;
@ -368,8 +364,6 @@ public:
consensus.nAllowMinDiffMinHeight = -1; consensus.nAllowMinDiffMinHeight = -1;
consensus.nAllowMinDiffMaxHeight = -1; consensus.nAllowMinDiffMaxHeight = -1;
consensus.nNormalizedNameForkHeight = 250; // SDK depends upon this number consensus.nNormalizedNameForkHeight = 250; // SDK depends upon this number
consensus.nMinTakeoverWorkaroundHeight = -1;
consensus.nMaxTakeoverWorkaroundHeight = -1;
consensus.nWitnessForkHeight = 150; consensus.nWitnessForkHeight = 150;
consensus.nAllClaimsInMerkleForkHeight = 350; consensus.nAllClaimsInMerkleForkHeight = 350;
consensus.fPowAllowMinDifficultyBlocks = false; consensus.fPowAllowMinDifficultyBlocks = false;

View file

@ -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", 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); 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) 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", 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); 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<unsigned char>& name) static std::string vchToString(const std::vector<unsigned char>& name)

View file

@ -6,7 +6,7 @@
#define CLAIMSCRIPTOP_H #define CLAIMSCRIPTOP_H
#include "amount.h" #include "amount.h"
#include "claimtrie.h" #include "claimtrie/forks.h"
#include "hash.h" #include "hash.h"
#include "primitives/transaction.h" #include "primitives/transaction.h"
#include "script/script.h" #include "script/script.h"

View file

@ -1,491 +0,0 @@
#ifndef BITCOIN_CLAIMTRIE_H
#define BITCOIN_CLAIMTRIE_H
#include <amount.h>
#include <chain.h>
#include <chainparams.h>
#include <primitives/transaction.h>
#include <serialize.h>
#include <uint256.h>
#include <util.h>
#include <map>
#include <string>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <sqlite/sqlite3.h>
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 <sqlite/hdr/sqlite_modern_cpp.h>
namespace sqlite {
template<>
struct has_sqlite_type<uint256, SQLITE_BLOB, void> : std::true_type {};
template<>
struct has_sqlite_type<uint160, SQLITE_BLOB, void> : std::true_type {};
inline uint160 get_col_from_db(sqlite3_stmt* stmt, int inx, result_type<uint160>) {
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>) {
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 <typename Stream, typename Operation>
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 <typename Stream, typename Operation>
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<CClaimValue> claimEntryType;
typedef std::vector<CSupportValue> 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 <typename Stream, typename Operation>
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<CSupportValue>& 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<CSupportValue> supports;
};
static const CClaimNsupports invalid;
struct CClaimSupportToName
{
CClaimSupportToName(const std::string& name, int nLastTakeoverHeight, std::vector<CClaimNsupports> claimsNsupports, std::vector<CSupportValue> 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<CClaimNsupports> claimsNsupports;
const std::vector<CSupportValue> 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<std::pair<unsigned char, uint256>> 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<std::pair<unsigned char, uint256>> 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<std::pair<bool, uint256>> pairs;
std::vector<CClaimTrieProofNode> nodes;
int nHeightOfLastTakeover = 0;
bool hasValue = false;
COutPoint outPoint;
};
template <typename T>
using queueEntryType = std::pair<std::string, T>;
typedef std::vector<queueEntryType<CClaimValue>> claimUndoType;
typedef std::vector<queueEntryType<CSupportValue>> supportUndoType;
typedef std::vector<CNameOutPointHeightType> insertUndoType;
typedef std::vector<queueEntryType<std::pair<int, uint160>>> 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<unsigned char>& metadata = {});
bool addSupport(const std::string& name, const COutPoint& outPoint, CAmount nAmount,
const uint160& supportedClaimId, int nHeight, int nValidHeight = -1, const std::vector<unsigned char>& 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<unsigned char> claim, CClaimValue& value, std::string& name);
void getNamesInTrie(std::function<void(const std::string&)> 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<std::string> 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

84
src/claimtrie/data.cpp Normal file
View file

@ -0,0 +1,84 @@
#include <claimtrie/data.h>
#include <claimtrie/log.h>
#include <algorithm>
#include <sstream>
#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))
{
}

131
src/claimtrie/data.h Normal file
View file

@ -0,0 +1,131 @@
#ifndef CLAIMTRIE_DATA_H
#define CLAIMTRIE_DATA_H
#include <claimtrie/sqlite/sqlite3.h>
#include <claimtrie/txoutpoint.h>
#include <claimtrie/uints.h>
#include <cstring>
#include <string>
#include <vector>
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 <claimtrie/sqlite/hdr/sqlite_modern_cpp.h>
namespace sqlite
{
template<>
struct has_sqlite_type<CUint256, SQLITE_BLOB, void> : std::true_type {};
template<>
struct has_sqlite_type<CUint160, SQLITE_BLOB, void> : std::true_type {};
inline CUint160 get_col_from_db(sqlite3_stmt* stmt, int inx, result_type<CUint160>) {
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>) {
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<CClaimValue> claimEntryType;
typedef std::vector<CSupportValue> 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

View file

@ -1,35 +1,33 @@
#include <consensus/merkle.h> #include <claimtrie/forks.h>
#include <chainparams.h> #include <claimtrie/hash.h>
#include <claimtrie.h> #include <claimtrie/log.h>
#include <hash.h> #include <claimtrie/trie.h>
#include <boost/locale.hpp> #include <boost/locale.hpp>
#include <boost/locale/conversion.hpp> #include <boost/locale/conversion.hpp>
#include <boost/locale/localization_backend.hpp> #include <boost/locale/localization_backend.hpp>
#include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp>
CClaimTrieCacheExpirationFork::CClaimTrieCacheExpirationFork(CClaimTrie* base) #define logPrint CLogPrint::global()
: CClaimTrieCacheBase(base)
{
setExpirationTime(Params().GetConsensus().GetExpirationTime(nNextHeight));
}
void CClaimTrieCacheExpirationFork::setExpirationTime(int time) CClaimTrieCacheExpirationFork::CClaimTrieCacheExpirationFork(CClaimTrie* base) : CClaimTrieCacheBase(base)
{ {
nExpirationTime = time; expirationHeight = nNextHeight;
} }
int CClaimTrieCacheExpirationFork::expirationTime() const int CClaimTrieCacheExpirationFork::expirationTime() const
{ {
return nExpirationTime; if (expirationHeight < base->nExtendedClaimExpirationForkHeight)
return CClaimTrieCacheBase::expirationTime();
return base->nExtendedClaimExpirationTime;
} }
bool CClaimTrieCacheExpirationFork::incrementBlock(insertUndoType& insertUndo, claimUndoType& expireUndo, bool CClaimTrieCacheExpirationFork::incrementBlock(insertUndoType& insertUndo, claimUndoType& expireUndo,
insertUndoType& insertSupportUndo, supportUndoType& expireSupportUndo, takeoverUndoType& takeoverUndo) insertUndoType& insertSupportUndo, supportUndoType& expireSupportUndo, takeoverUndoType& takeoverUndo)
{ {
if (CClaimTrieCacheBase::incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverUndo)) { if (CClaimTrieCacheBase::incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverUndo)) {
setExpirationTime(Params().GetConsensus().GetExpirationTime(nNextHeight)); expirationHeight = nNextHeight;
return true; return true;
} }
return false; return false;
@ -38,7 +36,7 @@ bool CClaimTrieCacheExpirationFork::incrementBlock(insertUndoType& insertUndo, c
bool CClaimTrieCacheExpirationFork::decrementBlock(insertUndoType& insertUndo, claimUndoType& expireUndo, insertUndoType& insertSupportUndo, supportUndoType& expireSupportUndo) bool CClaimTrieCacheExpirationFork::decrementBlock(insertUndoType& insertUndo, claimUndoType& expireUndo, insertUndoType& insertSupportUndo, supportUndoType& expireSupportUndo)
{ {
if (CClaimTrieCacheBase::decrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo)) { if (CClaimTrieCacheBase::decrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo)) {
setExpirationTime(Params().GetConsensus().GetExpirationTime(nNextHeight)); expirationHeight = nNextHeight;
return true; return true;
} }
return false; return false;
@ -47,7 +45,7 @@ bool CClaimTrieCacheExpirationFork::decrementBlock(insertUndoType& insertUndo, c
void CClaimTrieCacheExpirationFork::initializeIncrement() 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) // 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; return;
forkForExpirationChange(true); forkForExpirationChange(true);
@ -56,7 +54,7 @@ void CClaimTrieCacheExpirationFork::initializeIncrement()
bool CClaimTrieCacheExpirationFork::finalizeDecrement(takeoverUndoType& takeoverUndo) bool CClaimTrieCacheExpirationFork::finalizeDecrement(takeoverUndoType& takeoverUndo)
{ {
auto ret = CClaimTrieCacheBase::finalizeDecrement(takeoverUndo); auto ret = CClaimTrieCacheBase::finalizeDecrement(takeoverUndo);
if (ret && nNextHeight == Params().GetConsensus().nExtendedClaimExpirationForkHeight) if (ret && nNextHeight == base->nExtendedClaimExpirationForkHeight)
forkForExpirationChange(false); forkForExpirationChange(false);
return ret; return ret;
} }
@ -73,7 +71,7 @@ bool CClaimTrieCacheExpirationFork::forkForExpirationChange(bool increment)
will have their expiration extension removed. will have their expiration extension removed.
*/ */
auto extension = Params().GetConsensus().nExtendedClaimExpirationTime - Params().GetConsensus().nOriginalClaimExpirationTime; auto extension = base->nExtendedClaimExpirationTime - base->nOriginalClaimExpirationTime;
if (increment) { if (increment) {
db << "UPDATE claims SET expirationHeight = expirationHeight + ? WHERE expirationHeight >= ?" db << "UPDATE claims SET expirationHeight = expirationHeight + ? WHERE expirationHeight >= ?"
<< extension << nNextHeight; << extension << nNextHeight;
@ -89,9 +87,13 @@ bool CClaimTrieCacheExpirationFork::forkForExpirationChange(bool increment)
return true; return true;
} }
CClaimTrieCacheNormalizationFork::CClaimTrieCacheNormalizationFork(CClaimTrie* base) : CClaimTrieCacheExpirationFork(base)
{
}
bool CClaimTrieCacheNormalizationFork::shouldNormalize() const bool CClaimTrieCacheNormalizationFork::shouldNormalize() const
{ {
return nNextHeight > Params().GetConsensus().nNormalizedNameForkHeight; return nNextHeight > base->nNormalizedNameForkHeight;
} }
std::string CClaimTrieCacheNormalizationFork::normalizeClaimName(const std::string& name, bool force) const 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) { } catch (const boost::locale::conv::conversion_error& e) {
return name; return name;
} catch (const std::bad_cast& e) { } 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; throw;
} catch (const std::exception& e) { // TODO: change to use ... with current_exception() in c++11 } 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; return name;
} }
@ -159,11 +161,11 @@ bool CClaimTrieCacheNormalizationFork::normalizeAllNamesInTrieIfNecessary(takeov
for (auto&& row: query) { for (auto&& row: query) {
std::string name; std::string name;
int takeoverHeight; int takeoverHeight;
std::unique_ptr<uint160> takeoverID; std::unique_ptr<CUint160> takeoverID;
row >> name >> takeoverHeight >> takeoverID; row >> name >> takeoverHeight >> takeoverID;
if (name.empty()) continue; // preserve our root node if (name.empty()) continue; // preserve our root node
if (takeoverHeight > 0) 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: // we need to let the tree structure method do the actual node delete:
db << "UPDATE nodes SET hash = NULL WHERE name = ?" << name; db << "UPDATE nodes SET hash = NULL WHERE name = ?" << name;
} }
@ -202,57 +204,22 @@ bool CClaimTrieCacheNormalizationFork::unnormalizeAllNamesInTrieIfNecessary()
bool CClaimTrieCacheNormalizationFork::incrementBlock(insertUndoType& insertUndo, claimUndoType& expireUndo, bool CClaimTrieCacheNormalizationFork::incrementBlock(insertUndoType& insertUndo, claimUndoType& expireUndo,
insertUndoType& insertSupportUndo, supportUndoType& expireSupportUndo, takeoverUndoType& takeoverUndo) insertUndoType& insertSupportUndo, supportUndoType& expireSupportUndo, takeoverUndoType& takeoverUndo)
{ {
if (nNextHeight == Params().GetConsensus().nNormalizedNameForkHeight) if (nNextHeight == base->nNormalizedNameForkHeight)
normalizeAllNamesInTrieIfNecessary(takeoverUndo); normalizeAllNamesInTrieIfNecessary(takeoverUndo);
auto ret = CClaimTrieCacheExpirationFork::incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverUndo); return 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<std::string> 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;
} }
bool CClaimTrieCacheNormalizationFork::decrementBlock(insertUndoType& insertUndo, claimUndoType& expireUndo, insertUndoType& insertSupportUndo, supportUndoType& expireSupportUndo) bool CClaimTrieCacheNormalizationFork::decrementBlock(insertUndoType& insertUndo, claimUndoType& expireUndo, insertUndoType& insertSupportUndo, supportUndoType& expireSupportUndo)
{ {
auto ret = CClaimTrieCacheExpirationFork::decrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo); auto ret = CClaimTrieCacheExpirationFork::decrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo);
if (ret && nNextHeight == Params().GetConsensus().nNormalizedNameForkHeight) if (ret && nNextHeight == base->nNormalizedNameForkHeight)
unnormalizeAllNamesInTrieIfNecessary(); unnormalizeAllNamesInTrieIfNecessary();
return ret; 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 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)); 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); return CClaimTrieCacheExpirationFork::getDelayForName(normalizeClaimName(name), claimId);
} }
std::string CClaimTrieCacheNormalizationFork::adjustNameForValidHeight(const std::string& name, int validHeight) const 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) CClaimTrieCacheHashFork::CClaimTrieCacheHashFork(CClaimTrie* base) : CClaimTrieCacheNormalizationFork(base)
{ {
} }
static const uint256 leafHash = uint256S("0000000000000000000000000000000000000000000000000000000000000002"); static const auto leafHash = CUint256S("0000000000000000000000000000000000000000000000000000000000000002");
static const uint256 emptyHash = uint256S("0000000000000000000000000000000000000000000000000000000000000003"); static const auto emptyHash = CUint256S("0000000000000000000000000000000000000000000000000000000000000003");
uint256 CClaimTrieCacheHashFork::recursiveComputeMerkleHash(const std::string& name, int takeoverHeight, bool checkOnly) CUint256 ComputeMerkleRoot(std::vector<CUint256> 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); 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 // 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<uint256> hash; int takeoverHeight; }; struct Triple { std::string name; std::unique_ptr<CUint256> hash; int takeoverHeight; };
std::vector<Triple> children; std::vector<Triple> children;
for (auto&& row : childHashQuery << name) { for (auto&& row : childHashQuery << name) {
children.emplace_back(); children.emplace_back();
@ -297,19 +279,19 @@ uint256 CClaimTrieCacheHashFork::recursiveComputeMerkleHash(const std::string& n
} }
childHashQuery++; childHashQuery++;
std::vector<uint256> childHashes; std::vector<CUint256> childHashes;
for (auto& child: children) { for (auto& child: children) {
if (child.hash == nullptr) child.hash = std::make_unique<uint256>(); if (child.hash == nullptr) child.hash = std::make_unique<CUint256>();
if (child.hash->IsNull()) { if (child.hash->IsNull()) {
*child.hash = recursiveComputeMerkleHash(child.name, child.takeoverHeight, checkOnly); *child.hash = recursiveComputeMerkleHash(child.name, child.takeoverHeight, checkOnly);
} }
childHashes.push_back(*child.hash); childHashes.push_back(*child.hash);
} }
std::vector<uint256> claimHashes; std::vector<CUint256> claimHashes;
//if (takeoverHeight > 0) { //if (takeoverHeight > 0) {
for (auto &&row: claimHashQuery << nNextHeight << name) { for (auto &&row: claimHashQuery << nNextHeight << name) {
COutPoint p; CTxOutPoint p;
row >> p.hash >> p.n; row >> p.hash >> p.n;
auto claimHash = getValueHash(p, takeoverHeight); auto claimHash = getValueHash(p, takeoverHeight);
claimHashes.push_back(claimHash); claimHashes.push_back(claimHash);
@ -326,14 +308,14 @@ uint256 CClaimTrieCacheHashFork::recursiveComputeMerkleHash(const std::string& n
return computedHash; return computedHash;
} }
std::vector<uint256> ComputeMerklePath(const std::vector<uint256>& hashes, uint32_t idx) std::vector<CUint256> ComputeMerklePath(const std::vector<CUint256>& hashes, uint32_t idx)
{ {
uint32_t count = 0; uint32_t count = 0;
int matchlevel = -1; int matchlevel = -1;
bool matchh = false; bool matchh = false;
uint256 inner[32], h; CUint256 inner[32], h;
const uint32_t one = 1; const uint32_t one = 1;
std::vector<uint256> res; std::vector<CUint256> res;
const auto iterateInner = [&](int& level) { const auto iterateInner = [&](int& level) {
for (; !(count & (one << level)); level++) { for (; !(count & (one << level)); level++) {
@ -381,12 +363,12 @@ std::vector<uint256> ComputeMerklePath(const std::vector<uint256>& hashes, uint3
return res; 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) if (nNextHeight < base->nAllClaimsInMerkleForkHeight)
return CClaimTrieCacheNormalizationFork::getProofForName(name, finalClaim, proof); return CClaimTrieCacheNormalizationFork::getProofForName(name, claim, proof);
auto fillPairs = [&proof](const std::vector<uint256>& hashes, uint32_t idx) { auto fillPairs = [&proof](const std::vector<CUint256>& hashes, uint32_t idx) {
auto partials = ComputeMerklePath(hashes, idx); auto partials = ComputeMerklePath(hashes, idx);
for (int i = partials.size() - 1; i >= 0; --i) for (int i = partials.size() - 1; i >= 0; --i)
proof.pairs.emplace_back((idx >> i) & 1, partials[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) " "SELECT POPS(p) FROM prefix WHERE p != '') SELECT p FROM prefix) "
"ORDER BY name" << name; "ORDER BY name" << name;
for (auto&& row: nodeQuery) { for (auto&& row: nodeQuery) {
std::string key;; std::string key;
int takeoverHeight; int takeoverHeight;
row >> key >> takeoverHeight; row >> key >> takeoverHeight;
std::vector<uint256> childHashes;
uint32_t nextCurrentIdx = 0; uint32_t nextCurrentIdx = 0;
std::vector<CUint256> childHashes;
for (auto&& child : childHashQuery << key) { for (auto&& child : childHashQuery << key) {
std::string childKey; std::string childKey;
uint256 childHash; CUint256 childHash;
child >> childKey >> childHash; child >> childKey >> childHash;
if (name.find(childKey) == 0) if (name.find(childKey) == 0)
nextCurrentIdx = uint32_t(childHashes.size()); nextCurrentIdx = uint32_t(childHashes.size());
@ -415,14 +397,14 @@ bool CClaimTrieCacheHashFork::getProofForName(const std::string& name, const uin
} }
childHashQuery++; childHashQuery++;
std::vector<uint256> claimHashes; std::vector<CUint256> claimHashes;
uint32_t finalClaimIdx = 0; uint32_t claimIdx = 0;
for (auto&& child: claimHashQuery << nNextHeight << key) { for (auto&& child: claimHashQuery << nNextHeight << key) {
COutPoint childOutPoint; CTxOutPoint childOutPoint;
uint160 childClaimID; CUint160 childClaimID;
child >> childOutPoint.hash >> childOutPoint.n >> childClaimID; child >> childOutPoint.hash >> childOutPoint.n >> childClaimID;
if (childClaimID == finalClaim && key == name) { if (childClaimID == claim && key == name) {
finalClaimIdx = uint32_t(claimHashes.size()); claimIdx = uint32_t(claimHashes.size());
proof.outPoint = childOutPoint; proof.outPoint = childOutPoint;
proof.hasValue = true; proof.hasValue = true;
} }
@ -438,7 +420,7 @@ bool CClaimTrieCacheHashFork::getProofForName(const std::string& name, const uin
auto hash = childHashes.empty() ? leafHash : ComputeMerkleRoot(childHashes); auto hash = childHashes.empty() ? leafHash : ComputeMerkleRoot(childHashes);
proof.pairs.emplace_back(true, hash); proof.pairs.emplace_back(true, hash);
if (!claimHashes.empty()) if (!claimHashes.empty())
fillPairs(claimHashes, finalClaimIdx); fillPairs(claimHashes, claimIdx);
} else { } else {
auto hash = claimHashes.empty() ? emptyHash : ComputeMerkleRoot(claimHashes); auto hash = claimHashes.empty() ? emptyHash : ComputeMerkleRoot(claimHashes);
proof.pairs.emplace_back(false, hash); proof.pairs.emplace_back(false, hash);
@ -454,7 +436,7 @@ void CClaimTrieCacheHashFork::initializeIncrement()
{ {
CClaimTrieCacheNormalizationFork::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) // 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"; } if (!transacting) { transacting = true; db << "begin"; }
db << "UPDATE nodes SET hash = NULL"; db << "UPDATE nodes SET hash = NULL";
} }
@ -463,7 +445,7 @@ void CClaimTrieCacheHashFork::initializeIncrement()
bool CClaimTrieCacheHashFork::finalizeDecrement(takeoverUndoType& takeoverUndo) bool CClaimTrieCacheHashFork::finalizeDecrement(takeoverUndoType& takeoverUndo)
{ {
auto ret = CClaimTrieCacheNormalizationFork::finalizeDecrement(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"; } if (!transacting) { transacting = true; db << "begin"; }
db << "UPDATE nodes SET hash = NULL"; db << "UPDATE nodes SET hash = NULL";
} }
@ -472,5 +454,5 @@ bool CClaimTrieCacheHashFork::finalizeDecrement(takeoverUndoType& takeoverUndo)
bool CClaimTrieCacheHashFork::allowSupportMetadata() const bool CClaimTrieCacheHashFork::allowSupportMetadata() const
{ {
return nNextHeight >= Params().GetConsensus().nAllClaimsInMerkleForkHeight; return nNextHeight >= base->nAllClaimsInMerkleForkHeight;
} }

87
src/claimtrie/forks.h Normal file
View file

@ -0,0 +1,87 @@
#ifndef CLAIMTRIE_FORKS_H
#define CLAIMTRIE_FORKS_H
#include <claimtrie/trie.h>
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

12
src/claimtrie/hash.cpp Normal file
View file

@ -0,0 +1,12 @@
#include <claimtrie/hash.h>
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;
}

29
src/claimtrie/hash.h Normal file
View file

@ -0,0 +1,29 @@
#ifndef CLAIMTRIE_HASH_H
#define CLAIMTRIE_HASH_H
#include <openssl/sha.h>
#include <claimtrie/uints.h>
// Bitcoin doubles hashes
CUint256 CalcHash(SHA256_CTX* sha);
template<typename TIterator, typename... Args>
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<typename TIterator, typename... Args>
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

23
src/claimtrie/log.cpp Normal file
View file

@ -0,0 +1,23 @@
#include <claimtrie/log.h>
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;
}

41
src/claimtrie/log.h Normal file
View file

@ -0,0 +1,41 @@
#ifndef CLAIMTRIE_LOG_H
#define CLAIMTRIE_LOG_H
#include <string>
#include <sstream>
struct ClogBase
{
ClogBase() = default;
virtual ~ClogBase() = default;
virtual void LogPrintStr(const std::string&) = 0;
};
enum struct Clog
{
endl = 0,
};
struct CLogPrint
{
template <typename T>
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

View file

@ -9,7 +9,7 @@
#define MODERN_SQLITE_VERSION 3002008 #define MODERN_SQLITE_VERSION 3002008
#include <sqlite/sqlite3.h> #include "../sqlite3.h"
#include "sqlite_modern_cpp/type_wrapper.h" #include "sqlite_modern_cpp/type_wrapper.h"
#include "sqlite_modern_cpp/errors.h" #include "sqlite_modern_cpp/errors.h"

View file

@ -3,7 +3,7 @@
#include <string> #include <string>
#include <stdexcept> #include <stdexcept>
#include <sqlite/sqlite3.h> #include "../../sqlite3.h"
namespace sqlite { namespace sqlite {

View file

@ -49,7 +49,7 @@ namespace sqlite
typedef const std::u16string& u16str_ref; typedef const std::u16string& u16str_ref;
} }
#endif #endif
#include <sqlite/sqlite3.h> #include "../../sqlite3.h"
#include "errors.h" #include "errors.h"
namespace sqlite { namespace sqlite {

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include <tuple> #include <tuple>
#include<type_traits> #include <type_traits>
namespace sqlite { namespace sqlite {
namespace utility { namespace utility {

View file

@ -1,21 +1,22 @@
#include <claimtrie.h>
#include <hash.h> #include <claimtrie/hash.h>
#include <logging.h> #include <claimtrie/log.h>
#include <util.h> #include <claimtrie/trie.h>
#include <utilstrencodings.h>
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
#include <consensus/merkle.h> #include <iomanip>
#include <boost/container/flat_map.hpp> #include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp> #include <boost/container/flat_set.hpp>
extern const uint256 one = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); #define logPrint CLogPrint::global()
static const auto one = CUint256S("0000000000000000000000000000000000000000000000000000000000000001");
std::vector<unsigned char> heightToVch(int n) std::vector<unsigned char> heightToVch(int n)
{ {
std::vector<unsigned char> vchHeight(8, 0); std::vector<uint8_t> vchHeight(8, 0);
vchHeight[4] = n >> 24; vchHeight[4] = n >> 24;
vchHeight[5] = n >> 16; vchHeight[5] = n >> 16;
vchHeight[6] = n >> 8; vchHeight[6] = n >> 8;
@ -23,40 +24,84 @@ std::vector<unsigned char> heightToVch(int n)
return vchHeight; return vchHeight;
} }
uint256 getValueHash(const COutPoint& outPoint, int nHeightOfLastTakeover) CUint256 getValueHash(const CTxOutPoint& outPoint, int nHeightOfLastTakeover)
{ {
CHash256 hasher; auto hash1 = Hash(outPoint.hash.begin(), outPoint.hash.end());
auto hash = Hash(outPoint.hash.begin(), outPoint.hash.end());
hasher.Write(hash.begin(), hash.size());
auto snOut = std::to_string(outPoint.n); auto snOut = std::to_string(outPoint.n);
hash = Hash(snOut.begin(), snOut.end()); auto hash2 = Hash(snOut.begin(), snOut.end());
hasher.Write(hash.begin(), hash.size());
auto vchHash = heightToVch(nHeightOfLastTakeover); auto vchHash = heightToVch(nHeightOfLastTakeover);
hash = Hash(vchHash.begin(), vchHash.end()); auto hash3 = Hash(vchHash.begin(), vchHash.end());
hasher.Write(hash.begin(), hash.size()); return Hash(hash1.begin(), hash1.end(), hash2.begin(), hash2.end(), hash3.begin(), hash3.end());
uint256 result;
hasher.Finalize(result.begin());
return result;
} }
static const sqlite::sqlite_config sharedConfig{ CClaimNsupports::CClaimNsupports(CClaimValue claim, int64_t effectiveAmount, std::vector<CSupportValue> 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<CClaimNsupports> claimsNsupports, std::vector<CSupportValue> 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<std::pair<unsigned char, CUint256>> 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, sqlite::OpenFlags::READWRITE | sqlite::OpenFlags::CREATE, // TODO: test with this: | sqlite::OpenFlags::SHAREDCACHE,
nullptr, sqlite::Encoding::UTF8 nullptr, sqlite::Encoding::UTF8
}; };
CClaimTrie::CClaimTrie(bool fWipe, int height, int proportionalDelayFactor) CClaimTrie::CClaimTrie(bool fWipe, int height,
: dbPath((GetDataDir() / "claims.sqlite").string()), db(dbPath, sharedConfig), int nNormalizedNameForkHeight,
nNextHeight(height), nProportionalDelayFactor(proportionalDelayFactor) 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<uint256>& hashes, const std::vector<unsigned char>& blob) { hashes.emplace_back(uint256(blob)); },
// [](const std::vector<uint256>& hashes) { return ComputeMerkleRoot(hashes); });
//
// db.define("MERKLE_PAIR", [](const std::vector<unsigned char>& blob1, const std::vector<unsigned char>& blob2) { return Hash(blob1.begin(), blob1.end(), blob2.begin(), blob2.end()); });
// db.define("MERKLE", [](const std::vector<unsigned char>& 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, " 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)"; "hash BLOB COLLATE BINARY, takeoverHeight INTEGER, takeoverID BLOB COLLATE BINARY)";
db << "CREATE INDEX IF NOT EXISTS nodes_hash ON nodes (hash)"; 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 db << "INSERT OR IGNORE INTO nodes(name, hash) VALUES('', ?)" << one; // ensure that we always have our root node
} }
CClaimTrieCacheBase::~CClaimTrieCacheBase() { CClaimTrieCacheBase::~CClaimTrieCacheBase()
{
if (transacting) { if (transacting) {
db << "rollback"; db << "rollback";
transacting = false; transacting = false;
@ -111,13 +157,14 @@ bool CClaimTrie::SyncToDisk()
return rc == SQLITE_OK; return rc == SQLITE_OK;
} }
bool CClaimTrie::empty() { bool CClaimTrie::empty()
{
int64_t count; int64_t count;
db << "SELECT COUNT(*) FROM claims WHERE validHeight < ?1 AND expirationHeight >= ?1" << nNextHeight >> count; db << "SELECT COUNT(*) FROM claims WHERE validHeight < ?1 AND expirationHeight >= ?1" << nNextHeight >> count;
return count == 0; 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 " auto query = db << "SELECT 1 FROM claims WHERE nodeName = ?1 AND txID = ?2 AND txN = ?3 "
"AND validHeight < ?4 AND expirationHeight >= ?4 LIMIT 1" "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(); 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 " auto query = db << "SELECT 1 FROM supports WHERE nodeName = ?1 AND txID = ?2 AND txN = ?3 "
"AND validHeight < ?4 AND expirationHeight >= ?4 LIMIT 1" "AND validHeight < ?4 AND expirationHeight >= ?4 LIMIT 1"
@ -148,7 +195,7 @@ supportEntryType CClaimTrieCacheBase::getSupportsForName(const std::string& name
return ret; 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 = ? " auto query = db << "SELECT validHeight FROM claims WHERE nodeName = ? AND txID = ? AND txN = ? "
"AND validHeight >= ? AND expirationHeight > validHeight LIMIT 1" "AND validHeight >= ? AND expirationHeight > validHeight LIMIT 1"
@ -160,7 +207,7 @@ bool CClaimTrieCacheBase::haveClaimInQueue(const std::string& name, const COutPo
return false; 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 = ? " auto query = db << "SELECT validHeight FROM supports WHERE nodeName = ? AND txID = ? AND txN = ? "
"AND validHeight >= ? AND expirationHeight > validHeight LIMIT 1" "AND validHeight >= ? AND expirationHeight > validHeight LIMIT 1"
@ -172,7 +219,8 @@ bool CClaimTrieCacheBase::haveSupportInQueue(const std::string& name, const COut
return false; 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; if (name.empty()) return false;
// to remove a node it must have one or less children and no claims // 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 " 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(?) // 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); db << "SELECT COUNT(*),MAX(name) FROM nodes WHERE parent = ?" << name >> std::tie(count, childName);
if (count > 1) return false; // still has multiple children 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 // okay. it's going away
auto query = db << "SELECT parent FROM nodes WHERE name = ?" << name; auto query = db << "SELECT parent FROM nodes WHERE name = ?" << name;
auto it = query.begin(); auto it = query.begin();
@ -202,7 +250,8 @@ bool CClaimTrieCacheBase::deleteNodeIfPossible(const std::string& name, std::str
return ret; return ret;
} }
void CClaimTrieCacheBase::ensureTreeStructureIsUpToDate() { void CClaimTrieCacheBase::ensureTreeStructureIsUpToDate()
{
if (!transacting) return; if (!transacting) return;
// your children are your nodes that match your key but go at least one longer, // your children are your nodes that match your key but go at least one longer,
@ -272,7 +321,7 @@ void CClaimTrieCacheBase::ensureTreeStructureIsUpToDate() {
break; break;
} }
// insert the split node: // 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 << newNodeName << parent;
insertQuery++; 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 << name << parent;
insertQuery++; insertQuery++;
} }
@ -313,9 +362,9 @@ std::size_t CClaimTrieCacheBase::getTotalClaimsInTrie() const
return ret; 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 " 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) " "WHERE s.supportedClaimID = c.claimID AND s.validHeight < ?1 AND s.expirationHeight >= ?1) "
"FROM claims c WHERE c.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()) if (it != query.end())
*it >> nLastTakeoverHeight; *it >> nLastTakeoverHeight;
} }
auto supports = getSupportsForName(name);
claimEntryType claims; claimEntryType claims;
auto supports = getSupportsForName(name);
{ {
auto query = db << "SELECT claimID, txID, txN, blockHeight, validHeight, amount " auto query = db << "SELECT claimID, txID, txN, blockHeight, validHeight, amount "
"FROM claims WHERE nodeName = ? AND expirationHeight >= ?" "FROM claims WHERE nodeName = ? AND expirationHeight >= ?"
@ -362,6 +411,7 @@ CClaimSupportToName CClaimTrieCacheBase::getClaimsForName(const std::string& nam
claims.push_back(claim); claims.push_back(claim);
} }
} }
auto find = [&supports](decltype(supports)::iterator& it, const CClaimValue& claim) { auto find = [&supports](decltype(supports)::iterator& it, const CClaimValue& claim) {
it = std::find_if(it, supports.end(), [&claim](const CSupportValue& support) { it = std::find_if(it, supports.end(), [&claim](const CSupportValue& support) {
return claim.claimId == support.supportedClaimId; return claim.claimId == support.supportedClaimId;
@ -372,7 +422,7 @@ CClaimSupportToName CClaimTrieCacheBase::getClaimsForName(const std::string& nam
// match support to claim // match support to claim
std::vector<CClaimNsupports> claimsNsupports; std::vector<CClaimNsupports> claimsNsupports;
for (const auto& claim : claims) { 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); auto ic = claimsNsupports.emplace(claimsNsupports.end(), claim, nAmount);
for (auto it = supports.begin(); find(it, claim); it = supports.erase(it)) { for (auto it = supports.begin(); find(it, claim); it = supports.erase(it)) {
if (it->nValidAtHeight < nNextHeight) if (it->nValidAtHeight < nNextHeight)
@ -385,22 +435,18 @@ CClaimSupportToName CClaimTrieCacheBase::getClaimsForName(const std::string& nam
return {name, nLastTakeoverHeight, std::move(claimsNsupports), std::move(supports)}; 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 it = key.rbegin(); std::distance(it, key.rend()) > to + 1; ++it)
for (auto i = key.size(); i > to + 1; --i, hasher.Reset()) partialHash = Hash(it, it + 1, partialHash.begin(), partialHash.end());
hasher
.Write((uint8_t*)&key[i - 1], 1)
.Write(partialHash.begin(), partialHash.size())
.Finalize(partialHash.begin());
} }
uint256 CClaimTrieCacheBase::recursiveComputeMerkleHash(const std::string& name, int takeoverHeight, bool checkOnly) CUint256 CClaimTrieCacheBase::recursiveComputeMerkleHash(const std::string& name, int takeoverHeight, bool checkOnly)
{ {
std::vector<uint8_t> vchToHash; std::vector<uint8_t> vchToHash;
const auto pos = name.size(); const auto pos = name.size();
// we have to free up the hash query so it can be reused by a child // we have to free up the hash query so it can be reused by a child
struct Triple { std::string name; std::unique_ptr<uint256> hash; int takeoverHeight; }; struct Triple { std::string name; std::unique_ptr<CUint256> hash; int takeoverHeight; };
std::vector<Triple> children; std::vector<Triple> children;
for (auto&& row : childHashQuery << name) { for (auto&& row : childHashQuery << name) {
children.emplace_back(); children.emplace_back();
@ -410,12 +456,10 @@ uint256 CClaimTrieCacheBase::recursiveComputeMerkleHash(const std::string& name,
childHashQuery++; childHashQuery++;
for (auto& child: children) { for (auto& child: children) {
if (child.hash == nullptr) child.hash = std::make_unique<uint256>(); if (child.hash == nullptr) child.hash = std::make_unique<CUint256>();
if (child.hash->IsNull()) { if (child.hash->IsNull()) {
*child.hash = recursiveComputeMerkleHash(child.name, child.takeoverHeight, checkOnly); *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); completeHash(*child.hash, child.name, pos);
vchToHash.push_back(child.name[pos]); vchToHash.push_back(child.name[pos]);
vchToHash.insert(vchToHash.end(), child.hash->begin(), child.hash->end()); vchToHash.insert(vchToHash.end(), child.hash->begin(), child.hash->end());
@ -423,7 +467,7 @@ uint256 CClaimTrieCacheBase::recursiveComputeMerkleHash(const std::string& name,
CClaimValue claim; CClaimValue claim;
if (getInfoForName(name, 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()); 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"; auto query = db << "SELECT name, hash, IFNULL(takeoverHeight, 0) FROM nodes";
for (auto&& row: query) { for (auto&& row: query) {
std::string name; std::string name;
uint256 hash; CUint256 hash;
int takeoverHeight; int takeoverHeight;
row >> name >> hash >> takeoverHeight; row >> name >> hash >> takeoverHeight;
auto computedHash = recursiveComputeMerkleHash(name, takeoverHeight, true); auto computedHash = recursiveComputeMerkleHash(name, takeoverHeight, true);
@ -459,7 +503,7 @@ bool CClaimTrieCacheBase::flush()
db << "commit"; db << "commit";
} }
catch (const sqlite::sqlite_exception& e) { 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(); auto code = e.get_code();
if (code == SQLITE_LOCKED || code == SQLITE_BUSY) { if (code == SQLITE_LOCKED || code == SQLITE_BUSY) {
LogPrintf("Retrying the commit in one second.\n", e.what()); LogPrintf("Retrying the commit in one second.\n", e.what());
@ -475,36 +519,25 @@ bool CClaimTrieCacheBase::flush()
return true; 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()) { if (checkConsistency()) {
LogPrintf("consistent\n"); logPrint << "consistent" << Clog::endl;
if (tip && tip->hashClaimTrie != getMerkleHash()) { if (rootHash != getMerkleHash()) {
// suppose we leave the old LevelDB data there: any harm done? It's ~10GB logPrint << "Merkle hash does not match root hash" << Clog::endl;
// eh, we better blow it away; it's their job to back up the folder first return false;
// 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__);
} }
return true; return true;
} }
LogPrintf("inconsistent!\n"); logPrint << "inconsistent!" << Clog::endl;
return false; return false;
} }
CClaimTrieCacheBase::CClaimTrieCacheBase(CClaimTrie* base) 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"), 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, " 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 " "(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 int CClaimTrieCacheBase::expirationTime() const
{ {
return Params().GetConsensus().nOriginalClaimExpirationTime; return base->nOriginalClaimExpirationTime;
} }
uint256 CClaimTrieCacheBase::getMerkleHash() CUint256 CClaimTrieCacheBase::getMerkleHash()
{ {
ensureTreeStructureIsUpToDate(); ensureTreeStructureIsUpToDate();
std::unique_ptr<uint256> hash; std::unique_ptr<CUint256> hash;
int takeoverHeight; int takeoverHeight;
// can't use childHashQuery here because "IS NULL" must be used instead of parent = NULL // 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); db << "SELECT hash, IFNULL(takeoverHeight, 0) FROM nodes WHERE name = ''" >> std::tie(hash, takeoverHeight);
@ -543,7 +576,7 @@ uint256 CClaimTrieCacheBase::getMerkleHash()
return *hash; 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 query = db << "SELECT takeoverHeight, takeoverID FROM nodes WHERE name = ? AND takeoverID IS NOT NULL" << name;
auto it = query.begin(); auto it = query.begin();
@ -553,8 +586,8 @@ bool CClaimTrieCacheBase::getLastTakeoverForName(const std::string& name, uint16
return !claimId.IsNull(); return !claimId.IsNull();
} }
bool CClaimTrieCacheBase::addClaim(const std::string& name, const COutPoint& outPoint, const uint160& claimId, bool CClaimTrieCacheBase::addClaim(const std::string& name, const CTxOutPoint& outPoint, const CUint160& claimId,
CAmount nAmount, int nHeight, int nValidHeight, const std::vector<unsigned char>& metadata) int64_t nAmount, int nHeight, int nValidHeight, const std::vector<unsigned char>& metadata)
{ {
if (!transacting) { transacting = true; db << "begin"; } if (!transacting) { transacting = true; db << "begin"; }
@ -584,8 +617,8 @@ bool CClaimTrieCacheBase::addClaim(const std::string& name, const COutPoint& out
return true; return true;
} }
bool CClaimTrieCacheBase::addSupport(const std::string& name, const COutPoint& outPoint, CAmount nAmount, bool CClaimTrieCacheBase::addSupport(const std::string& name, const CTxOutPoint& outPoint, const CUint160& supportedClaimId,
const uint160& supportedClaimId, int nHeight, int nValidHeight, const std::vector<unsigned char>& metadata) int64_t nAmount, int nHeight, int nValidHeight, const std::vector<unsigned char>& metadata)
{ {
if (!transacting) { transacting = true; db << "begin"; } if (!transacting) { transacting = true; db << "begin"; }
@ -603,7 +636,7 @@ bool CClaimTrieCacheBase::addSupport(const std::string& name, const COutPoint& o
return true; 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"; } if (!transacting) { transacting = true; db << "begin"; }
@ -640,11 +673,10 @@ bool CClaimTrieCacheBase::removeClaim(const uint160& claimId, const COutPoint& o
} }
} }
} }
return true; 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"; } if (!transacting) { transacting = true; db << "begin"; }
@ -1147,6 +1179,7 @@ bool CClaimTrieCacheBase::incrementBlock(insertUndoType& insertUndo, claimUndoTy
expireSupportUndo.emplace_back(name, value); expireSupportUndo.emplace_back(name, value);
} }
} }
db << "UPDATE nodes SET hash = NULL WHERE name IN (SELECT nodeName FROM supports WHERE expirationHeight = ?)" db << "UPDATE nodes SET hash = NULL WHERE name IN (SELECT nodeName FROM supports WHERE expirationHeight = ?)"
<< nNextHeight; << nNextHeight;
@ -1156,10 +1189,10 @@ bool CClaimTrieCacheBase::incrementBlock(insertUndoType& insertUndo, claimUndoTy
>> [&takeovers](std::string name) { >> [&takeovers](std::string name) {
takeovers.push_back(std::move(name)); takeovers.push_back(std::move(name));
}; };
auto getTakeoverQuery = db << "SELECT IFNULL(takeoverHeight, 0), takeoverID FROM nodes WHERE name = ?"; auto getTakeoverQuery = db << "SELECT IFNULL(takeoverHeight, 0), takeoverID FROM nodes WHERE name = ?";
auto hasCandidateQuery = db << "UPDATE nodes SET takeoverHeight = ?, takeoverID = ? 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 noCandidateQuery = db << "UPDATE nodes SET takeoverHeight = NULL, takeoverID = NULL WHERE name = ?";
auto maxWorkaround = Params().GetConsensus().nMaxTakeoverWorkaroundHeight;
for (const auto& nameWithTakeover : takeovers) { for (const auto& nameWithTakeover : takeovers) {
// if somebody activates on this block and they are the new best, then everybody activates on this block // 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); auto hasCandidate = getInfoForName(nameWithTakeover, candidateValue, 1);
// now that they're all in get the winner: // now that they're all in get the winner:
int existingHeight; int existingHeight;
std::unique_ptr<uint160> existingID; std::unique_ptr<CUint160> existingID;
getTakeoverQuery << nameWithTakeover >> std::tie(existingHeight, existingID); getTakeoverQuery << nameWithTakeover >> std::tie(existingHeight, existingID);
getTakeoverQuery++; // reset it 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. // 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. // 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. // 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)); auto wit = takeoverWorkarounds.find(std::make_pair(nNextHeight, nameWithTakeover));
takeoverHappening |= wit != takeoverWorkarounds.end(); 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) { 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) { if (hasCandidate) {
hasCandidateQuery << nNextHeight << candidateValue.claimId << nameWithTakeover; hasCandidateQuery << nNextHeight << candidateValue.claimId << nameWithTakeover;
hasCandidateQuery++; hasCandidateQuery++;
@ -1203,25 +1236,24 @@ bool CClaimTrieCacheBase::incrementBlock(insertUndoType& insertUndo, claimUndoTy
getTakeoverQuery.used(true); getTakeoverQuery.used(true);
hasCandidateQuery.used(true); hasCandidateQuery.used(true);
noCandidateQuery.used(true); noCandidateQuery.used(true);
nNextHeight++; nNextHeight++;
return true; return true;
} }
bool CClaimTrieCacheBase::activateAllFor(insertUndoType& insertUndo, insertUndoType& insertSupportUndo, bool CClaimTrieCacheBase::activateAllFor(insertUndoType& insertUndo, insertUndoType& insertSupportUndo, const std::string& name)
const std::string& name) { {
// now that we know a takeover is happening, we bring everybody in: // now that we know a takeover is happening, we bring everybody in:
auto ret = false; auto ret = false;
{ {
auto query = db << "SELECT txID, txN, validHeight FROM claims WHERE nodeName = ?1 AND validHeight > ?2 AND expirationHeight > ?2" auto query = db << "SELECT txID, txN, validHeight FROM claims WHERE nodeName = ?1 AND validHeight > ?2 AND expirationHeight > ?2"
<< name << nNextHeight; << name << nNextHeight;
for (auto &&row: query) { for (auto &&row: query) {
uint256 hash; CUint256 hash;
uint32_t n; uint32_t n;
int oldValidHeight; int oldValidHeight;
row >> hash >> n >> oldValidHeight; row >> hash >> n >> oldValidHeight;
insertUndo.emplace_back(name, COutPoint(hash, n), oldValidHeight); insertUndo.emplace_back(name, CTxOutPoint(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); logPrint << "Early activation of claim " << name << ", " << CTxOutPoint(hash, n).ToString() << " at " << nNextHeight << Clog::endl;
} }
} }
// and then update them all to activate now: // 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" auto query = db << "SELECT txID, txN, validHeight FROM supports WHERE nodeName = ?1 AND validHeight > ?2 AND expirationHeight > ?2"
<< name << nNextHeight; << name << nNextHeight;
for (auto &&row: query) { for (auto &&row: query) {
uint256 hash; CUint256 hash;
uint32_t n; uint32_t n;
int oldValidHeight; int oldValidHeight;
row >> hash >> n >> oldValidHeight; row >> hash >> n >> oldValidHeight;
insertSupportUndo.emplace_back(name, COutPoint(hash, n), oldValidHeight); insertSupportUndo.emplace_back(name, CTxOutPoint(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); logPrint << "Early activation of support " << name << ", " << CTxOutPoint(hash, n).ToString() << " at " << nNextHeight << Clog::endl;
} }
} }
// and then update them all to activate now: // 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) { 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 = ?" db << "UPDATE supports SET validHeight = ? WHERE txID = ? AND txN = ?"
<< it->nValidHeight << it->outPoint.hash << it->outPoint.n; << it->nValidHeight << it->outPoint.hash << it->outPoint.n;
db << "INSERT INTO nodes(name) VALUES(?) ON CONFLICT(name) DO UPDATE SET hash = NULL" << it->name; 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) { 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 = ?" db << "UPDATE claims SET validHeight = ? WHERE nodeName = ? AND txID = ? AND txN = ?"
<< it->nValidHeight << it->name << it->outPoint.hash << it->outPoint.n; << 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; 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; 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; int winningTakeoverHeight;
auto found = getLastTakeoverForName(name, winningClaimId, winningTakeoverHeight); auto found = getLastTakeoverForName(name, winningClaimId, winningTakeoverHeight);
if (found && winningClaimId == claimId) { if (found && winningClaimId == claimId) {
@ -1326,7 +1358,7 @@ std::string CClaimTrieCacheBase::adjustNameForValidHeight(const std::string& nam
return name; 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 // cache the parent nodes
getMerkleHash(); getMerkleHash();
@ -1341,25 +1373,25 @@ bool CClaimTrieCacheBase::getProofForName(const std::string& name, const uint160
int takeoverHeight; int takeoverHeight;
row >> key >> takeoverHeight; row >> key >> takeoverHeight;
bool fNodeHasValue = getInfoForName(key, claim); bool fNodeHasValue = getInfoForName(key, claim);
uint256 valueHash; CUint256 valueHash;
if (fNodeHasValue) if (fNodeHasValue)
valueHash = getValueHash(claim.outPoint, takeoverHeight); valueHash = getValueHash(claim.outPoint, takeoverHeight);
const auto pos = key.size(); const auto pos = key.size();
std::vector<std::pair<unsigned char, uint256>> children; std::vector<std::pair<unsigned char, CUint256>> children;
for (auto&& child : childHashQuery << key) { for (auto&& child : childHashQuery << key) {
std::string childKey; std::string childKey;
uint256 hash; CUint256 hash;
child >> childKey >> hash; child >> childKey >> hash;
if (name.find(childKey) == 0) { if (name.find(childKey) == 0) {
for (auto i = pos; i + 1 < childKey.size(); ++i) { 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); proof.nodes.emplace_back(children, fNodeHasValue, valueHash);
children.clear(); children.clear();
valueHash.SetNull(); valueHash.SetNull();
fNodeHasValue = false; fNodeHasValue = false;
} }
children.emplace_back(childKey.back(), uint256{}); children.emplace_back(childKey.back(), CUint256{});
continue; continue;
} }
completeHash(hash, childKey, pos); completeHash(hash, childKey, pos);
@ -1379,7 +1411,8 @@ bool CClaimTrieCacheBase::getProofForName(const std::string& name, const uint160
return true; return true;
} }
bool CClaimTrieCacheBase::findNameForClaim(std::vector<unsigned char> claim, CClaimValue& value, std::string& name) { bool CClaimTrieCacheBase::findNameForClaim(std::vector<unsigned char> claim, CClaimValue& value, std::string& name)
{
std::reverse(claim.begin(), claim.end()); std::reverse(claim.begin(), claim.end());
auto query = db << "SELECT nodeName, claimId, txID, txN, amount, validHeight, blockHeight " auto query = db << "SELECT nodeName, claimId, txID, txN, amount, validHeight, blockHeight "
"FROM claims WHERE SUBSTR(claimID, ?) = ? AND validHeight < ? AND expirationHeight >= ?" "FROM claims WHERE SUBSTR(claimID, ?) = ? AND validHeight < ? AND expirationHeight >= ?"

207
src/claimtrie/trie.h Normal file
View file

@ -0,0 +1,207 @@
#ifndef CLAIMTRIE_TRIE_H
#define CLAIMTRIE_TRIE_H
#include <claimtrie/data.h>
#include <claimtrie/txoutpoint.h>
#include <claimtrie/uints.h>
#include <functional>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <utility>
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<CSupportValue> supports = {});
bool IsNull() const;
CClaimValue claim;
int64_t effectiveAmount = 0;
std::vector<CSupportValue> supports;
};
struct CClaimSupportToName
{
CClaimSupportToName(std::string name, int nLastTakeoverHeight, std::vector<CClaimNsupports> claimsNsupports, std::vector<CSupportValue> 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<CClaimNsupports> claimsNsupports;
const std::vector<CSupportValue> 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<std::pair<unsigned char, CUint256>> children, bool hasValue, CUint256 valHash);
CClaimTrieProofNode(CClaimTrieProofNode&&) = default;
CClaimTrieProofNode(const CClaimTrieProofNode&) = default;
CClaimTrieProofNode& operator=(CClaimTrieProofNode&&) = default;
CClaimTrieProofNode& operator=(const CClaimTrieProofNode&) = default;
std::vector<std::pair<unsigned char, CUint256>> 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<std::pair<bool, CUint256>> pairs;
std::vector<CClaimTrieProofNode> nodes;
int nHeightOfLastTakeover = 0;
bool hasValue = false;
CTxOutPoint outPoint;
};
template <typename T>
using queueEntryType = std::pair<std::string, T>;
typedef std::vector<queueEntryType<CClaimValue>> claimUndoType;
typedef std::vector<queueEntryType<CSupportValue>> supportUndoType;
typedef std::vector<CNameOutPointHeightType> insertUndoType;
typedef std::vector<queueEntryType<std::pair<int, CUint160>>> 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<unsigned char>& metadata = {});
bool addSupport(const std::string& name, const CTxOutPoint& outPoint, const CUint160& supportedClaimId, int64_t nAmount,
int nHeight, int nValidHeight = -1, const std::vector<unsigned char>& 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<unsigned char> claim, CClaimValue& value, std::string& name);
void getNamesInTrie(std::function<void(const std::string&)> 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<std::string> 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

View file

@ -0,0 +1,42 @@
#include <claimtrie/txoutpoint.h>
#include <sstream>
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);
}

View file

@ -0,0 +1,37 @@
#ifndef CLAIMTRIE_TXOUTPUT_H
#define CLAIMTRIE_TXOUTPUT_H
#include <claimtrie/uints.h>
#include <algorithm>
#include <type_traits>
#include <vector>
#include <utility>
/** 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

155
src/claimtrie/uints.cpp Normal file
View file

@ -0,0 +1,155 @@
#include <claimtrie/uints.h>
#include <algorithm>
#include <cassert>
#include <cstring>
#include <iomanip>
#include <sstream>
/** Template base class for fixed-sized opaque blobs. */
template<uint32_t BITS>
CBaseBlob<BITS>::CBaseBlob() : data(std::make_unique<uint8_t[]>(WIDTH))
{
SetNull();
}
template<uint32_t BITS>
CBaseBlob<BITS>::CBaseBlob(const std::vector<uint8_t>& vec) : data(std::make_unique<uint8_t[]>(WIDTH))
{
assert(vec.size() == size());
std::copy(vec.begin(), vec.end(), begin());
}
template<uint32_t BITS>
CBaseBlob<BITS>::CBaseBlob(const CBaseBlob& o) : data(std::make_unique<uint8_t[]>(WIDTH))
{
*this = o;
}
template<uint32_t BITS>
CBaseBlob<BITS>& CBaseBlob<BITS>::operator=(const CBaseBlob& o)
{
if (this != &o)
std::copy(o.begin(), o.end(), begin());
return *this;
}
template<uint32_t BITS>
bool CBaseBlob<BITS>::IsNull() const
{
return std::all_of(begin(), end(), [](uint8_t e) { return e == 0; });
}
template<uint32_t BITS>
void CBaseBlob<BITS>::SetNull()
{
std::memset(begin(), 0, size());
}
template<uint32_t BITS>
int CBaseBlob<BITS>::Compare(const CBaseBlob& other) const
{
return std::memcmp(begin(), other.begin(), size());
}
template<uint32_t BITS>
std::string CBaseBlob<BITS>::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<uint32_t BITS>
void CBaseBlob<BITS>::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<uint32_t BITS>
void CBaseBlob<BITS>::SetHex(const std::string& str)
{
SetHex(str.c_str());
}
template<uint32_t BITS>
std::string CBaseBlob<BITS>::ToString() const
{
return GetHex();
}
template<uint32_t BITS>
uint8_t* CBaseBlob<BITS>::begin()
{
return data.get();
}
template<uint32_t BITS>
uint8_t* CBaseBlob<BITS>::end()
{
return begin() + WIDTH;
}
template<uint32_t BITS>
const uint8_t* CBaseBlob<BITS>::begin() const
{
return data.get();
}
template<uint32_t BITS>
const uint8_t* CBaseBlob<BITS>::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>;

59
src/claimtrie/uints.h Normal file
View file

@ -0,0 +1,59 @@
#ifndef CLAIMTRIE_UINTS_H
#define CLAIMTRIE_UINTS_H
#include <memory>
#include <vector>
/** Template base class for fixed-sized opaque blobs. */
template<uint32_t BITS>
class CBaseBlob
{
protected:
static constexpr int WIDTH = BITS / 8;
std::unique_ptr<uint8_t[]> data;
public:
CBaseBlob();
explicit CBaseBlob(const std::vector<uint8_t>& 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

105
src/claimtrie_serial.h Normal file
View file

@ -0,0 +1,105 @@
#ifndef CLAIMTRIE_SERIAL_H
#define CLAIMTRIE_SERIAL_H
#include <claimtrie/data.h>
#include <claimtrie/txoutpoint.h>
#include <claimtrie/uints.h>
template<typename Stream, uint32_t BITS>
void Serialize(Stream& s, const CBaseBlob<BITS>& u)
{
s.write((const char*)u.begin(), u.size());
}
template<typename Stream, uint32_t BITS>
void Unserialize(Stream& s, CBaseBlob<BITS>& u)
{
s.read((char*)u.begin(), u.size());
}
template<typename Stream>
void Serialize(Stream& s, const CTxOutPoint& u)
{
Serialize(s, u.hash);
Serialize(s, u.n);
}
template<typename Stream>
void Unserialize(Stream& s, CTxOutPoint& u)
{
Unserialize(s, u.hash);
Unserialize(s, u.n);
}
template<typename Stream>
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<typename Stream>
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<typename Stream>
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<typename Stream>
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<typename Stream>
void Serialize(Stream& s, const CNameOutPointHeightType& u)
{
Serialize(s, u.name);
Serialize(s, u.outPoint);
Serialize(s, u.nValidHeight);
}
template<typename Stream>
void Unserialize(Stream& s, CNameOutPointHeightType& u)
{
Unserialize(s, u.name);
Unserialize(s, u.outPoint);
Unserialize(s, u.nValidHeight);
}
template<typename Stream>
void Serialize(Stream& s, const CClaimIndexElement& u)
{
Serialize(s, u.name);
Serialize(s, u.claim);
}
template<typename Stream>
void Unserialize(Stream& s, CClaimIndexElement& u)
{
Unserialize(s, u.name);
Unserialize(s, u.claim);
}
#endif // CLAIMTRIE_SERIAL_H

View file

@ -78,9 +78,6 @@ struct Params {
int nAllowMinDiffMaxHeight; int nAllowMinDiffMaxHeight;
int nNormalizedNameForkHeight; int nNormalizedNameForkHeight;
int nMinTakeoverWorkaroundHeight;
int nMaxTakeoverWorkaroundHeight;
int nWitnessForkHeight; int nWitnessForkHeight;
int64_t nPowTargetSpacing; int64_t nPowTargetSpacing;

View file

@ -14,7 +14,7 @@
#include <chain.h> #include <chain.h>
#include <chainparams.h> #include <chainparams.h>
#include <checkpoints.h> #include <checkpoints.h>
#include <claimtrie.h> #include <claimtrie/forks.h>
#include <compat/sanity.h> #include <compat/sanity.h>
#include <consensus/validation.h> #include <consensus/validation.h>
#include <fs.h> #include <fs.h>
@ -1455,7 +1455,16 @@ bool AppInitMain()
pblocktree.reset(); pblocktree.reset();
pblocktree.reset(new CBlockTreeDB(nBlockTreeDBCache, false, fReset)); pblocktree.reset(new CBlockTreeDB(nBlockTreeDBCache, false, fReset));
delete pclaimTrie; 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) { if (fReset) {
pblocktree->WriteReindexing(true); pblocktree->WriteReindexing(true);
@ -1528,12 +1537,12 @@ bool AppInitMain()
} }
assert(chainActive.Tip() != nullptr); assert(chainActive.Tip() != nullptr);
} }
{ auto tip = chainActive.Tip();
CClaimTrieCache trieCache(pclaimTrie); assert(tip);
if (!trieCache.ValidateTipMatches(chainActive.Tip())) { CClaimTrieCache trieCache(pclaimTrie);
strLoadError = _("Error loading the claim trie from disk"); if (!trieCache.ReadFromDisk(tip->nHeight, tip->hashClaimTrie)) {
break; strLoadError = _("Error loading the claim trie from disk");
} break;
} }
if (!fReset) { if (!fReset) {
// Note that RewindBlockIndex MUST run even if we're about to -reindex-chainstate. // Note that RewindBlockIndex MUST run even if we're about to -reindex-chainstate.

View file

@ -3,8 +3,6 @@
#include <cstdio> #include <cstdio>
uint32_t g_memfileSize = 0;
unsigned int CalculateLbryNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params) unsigned int CalculateLbryNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
{ {
if (params.fPowNoRetargeting) if (params.fPowNoRetargeting)

View file

@ -4,7 +4,6 @@
#include <chain.h> #include <chain.h>
#include <chainparams.h> #include <chainparams.h>
extern uint32_t g_memfileSize;
unsigned int CalculateLbryNextWorkRequired(const CBlockIndex* pindexLast, int64_t nLastRetargetTime, const Consensus::Params& params); unsigned int CalculateLbryNextWorkRequired(const CBlockIndex* pindexLast, int64_t nLastRetargetTime, const Consensus::Params& params);
#endif #endif

View file

@ -6,6 +6,7 @@
#ifndef BITCOIN_LOGGING_H #ifndef BITCOIN_LOGGING_H
#define BITCOIN_LOGGING_H #define BITCOIN_LOGGING_H
#include <claimtrie/log.h>
#include <fs.h> #include <fs.h>
#include <tinyformat.h> #include <tinyformat.h>
@ -57,7 +58,7 @@ namespace BCLog {
ALL = ~(uint32_t)0, ALL = ~(uint32_t)0,
}; };
class Logger class Logger : public ClogBase
{ {
private: private:
FILE* m_fileout = nullptr; FILE* m_fileout = nullptr;
@ -87,7 +88,7 @@ namespace BCLog {
std::atomic<bool> m_reopen_file{false}; std::atomic<bool> m_reopen_file{false};
/** Send a string to the log output */ /** 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 */ /** Returns whether logs will be written to any output */
bool Enabled() const { return m_print_to_console || m_print_to_file; } bool Enabled() const { return m_print_to_console || m_print_to_file; }

View file

@ -9,6 +9,7 @@
#include <chain.h> #include <chain.h>
#include <chainparams.h> #include <chainparams.h>
#include <claimscriptop.h> #include <claimscriptop.h>
#include <claimtrie/forks.h>
#include <coins.h> #include <coins.h>
#include <consensus/consensus.h> #include <consensus/consensus.h>
#include <consensus/tx_verify.h> #include <consensus/tx_verify.h>
@ -204,7 +205,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
{ {
CClaimTrieCache trieCache(pclaimTrie); CClaimTrieCache trieCache(pclaimTrie);
blockToCache(pblock, trieCache, nHeight); blockToCache(pblock, trieCache, nHeight);
pblock->hashClaimTrie = trieCache.getMerkleHash(); pblock->hashClaimTrie = uint256(trieCache.getMerkleHash());
} }
CValidationState state; CValidationState state;
if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) { if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) {

View file

@ -68,14 +68,10 @@ bool DecodeClaimScript(const CScript& scriptIn, int& op, std::vector<std::vector
op = -1; op = -1;
opcodetype opcode; opcodetype opcode;
if (!scriptIn.GetOp(pc, opcode)) if (!scriptIn.GetOp(pc, opcode))
{
return false; return false;
}
if (opcode != OP_CLAIM_NAME && opcode != OP_SUPPORT_CLAIM && opcode != OP_UPDATE_CLAIM) if (opcode != OP_CLAIM_NAME && opcode != OP_SUPPORT_CLAIM && opcode != OP_UPDATE_CLAIM)
{
return false; return false;
}
op = opcode; op = opcode;
@ -90,57 +86,40 @@ bool DecodeClaimScript(const CScript& scriptIn, int& op, std::vector<std::vector
// All others are invalid. // All others are invalid.
if (!scriptIn.GetOp(pc, opcode, vchParam1) || opcode < 0 || opcode > OP_PUSHDATA4) if (!scriptIn.GetOp(pc, opcode, vchParam1) || opcode < 0 || opcode > OP_PUSHDATA4)
{
return false; return false;
}
if (!scriptIn.GetOp(pc, opcode, vchParam2) || opcode < 0 || opcode > OP_PUSHDATA4) if (!scriptIn.GetOp(pc, opcode, vchParam2) || opcode < 0 || opcode > OP_PUSHDATA4)
{
return false; return false;
}
if (op == OP_UPDATE_CLAIM || op == OP_SUPPORT_CLAIM) if (op == OP_UPDATE_CLAIM || op == OP_SUPPORT_CLAIM)
{ if (vchParam2.size() != sizeof(uint160))
static const size_t claimIdHashSize = sizeof(uint160);
if (vchParam2.size() != claimIdHashSize) {
return false; return false;
}
}
if (!scriptIn.GetOp(pc, opcode, vchParam3)) if (!scriptIn.GetOp(pc, opcode, vchParam3))
{
return false; return false;
}
auto last_drop = OP_DROP; 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)) if (!scriptIn.GetOp(pc, opcode))
{
return false; return false;
}
last_drop = OP_2DROP; last_drop = OP_2DROP;
} } else if (op == OP_UPDATE_CLAIM)
else if (op == OP_UPDATE_CLAIM)
{
return false; return false;
}
if (opcode != OP_2DROP) if (opcode != OP_2DROP)
{
return false; return false;
}
if (!scriptIn.GetOp(pc, opcode) || opcode != last_drop) if (!scriptIn.GetOp(pc, opcode) || opcode != last_drop)
{
return false; return false;
}
if (op == OP_SUPPORT_CLAIM && last_drop == OP_2DROP && !allowSupportMetadata) if (op == OP_SUPPORT_CLAIM && last_drop == OP_2DROP && !allowSupportMetadata)
{
return false; return false;
}
vvchParams.push_back(std::move(vchParam1)); vvchParams.push_back(std::move(vchParam1));
vvchParams.push_back(std::move(vchParam2)); vvchParams.push_back(std::move(vchParam2));
if (last_drop == OP_2DROP) if (last_drop == OP_2DROP)
{
vvchParams.push_back(std::move(vchParam3)); vvchParams.push_back(std::move(vchParam3));
}
return true; return true;
} }
@ -164,9 +143,7 @@ CScript StripClaimScriptPrefix(const CScript& scriptIn, int& op)
CScript::const_iterator pc = scriptIn.begin(); CScript::const_iterator pc = scriptIn.begin();
if (!DecodeClaimScript(scriptIn, op, vvchParams, pc)) if (!DecodeClaimScript(scriptIn, op, vvchParams, pc))
{
return scriptIn; return scriptIn;
}
return CScript(pc, scriptIn.end()); return CScript(pc, scriptIn.end());
} }
@ -183,31 +160,21 @@ size_t ClaimNameSize(const CScript& scriptIn)
CScript::const_iterator pc = scriptIn.begin(); CScript::const_iterator pc = scriptIn.begin();
int op; int op;
if (!DecodeClaimScript(scriptIn, op, vvchParams, pc)) if (!DecodeClaimScript(scriptIn, op, vvchParams, pc))
{
return 0; return 0;
} return vvchParams[0].size();
else
{
return vvchParams[0].size();
}
} }
CAmount CalcMinClaimTrieFee(const CTransaction& tx, const CAmount &minFeePerNameClaimChar) CAmount CalcMinClaimTrieFee(const CTransaction& tx, const CAmount &minFeePerNameClaimChar)
{ {
if (minFeePerNameClaimChar == 0) if (minFeePerNameClaimChar == 0)
{
return 0; return 0;
}
CAmount min_fee = 0; CAmount min_fee = 0;
for (const CTxOut& txout: tx.vout) for (const CTxOut& txout: tx.vout) {
{
int op; int op;
std::vector<std::vector<unsigned char> > vvchParams; std::vector<std::vector<unsigned char> > vvchParams;
if (DecodeClaimScript(txout.scriptPubKey, op, vvchParams)) if (DecodeClaimScript(txout.scriptPubKey, op, vvchParams)) {
{ if (op == OP_CLAIM_NAME) {
if (op == OP_CLAIM_NAME)
{
int claim_name_size = vvchParams[0].size(); int claim_name_size = vvchParams[0].size();
min_fee += claim_name_size*minFeePerNameClaimChar; min_fee += claim_name_size*minFeePerNameClaimChar;
} }

View file

@ -8,6 +8,7 @@
#include <stdint.h> #include <stdint.h>
#include <amount.h> #include <amount.h>
#include <claimtrie/txoutpoint.h>
#include <script/script.h> #include <script/script.h>
#include <serialize.h> #include <serialize.h>
#include <uint256.h> #include <uint256.h>
@ -22,6 +23,7 @@ public:
uint32_t n; uint32_t n;
COutPoint(): n((uint32_t) -1) { } COutPoint(): n((uint32_t) -1) { }
explicit COutPoint(const CTxOutPoint& c) : hash(c.hash), n(c.n) { }
COutPoint(const uint256& hashIn, uint32_t nIn): hash(hashIn), n(nIn) { } COutPoint(const uint256& hashIn, uint32_t nIn): hash(hashIn), n(nIn) { }
ADD_SERIALIZE_METHODS; ADD_SERIALIZE_METHODS;
@ -52,6 +54,11 @@ public:
} }
std::string ToString() const; std::string ToString() const;
operator CTxOutPoint() const
{
return CTxOutPoint{hash, n};
}
}; };
/** An input of a transaction. It contains the location of the previous /** An input of a transaction. It contains the location of the previous

View file

@ -1,4 +1,5 @@
#include <claimtrie.h>
#include <claimtrie/forks.h>
#include <coins.h> #include <coins.h>
#include <core_io.h> #include <core_io.h>
#include <key_io.h> #include <key_io.h>
@ -20,13 +21,6 @@
static constexpr size_t claimIdHexLength = 40; static constexpr size_t claimIdHexLength = 40;
uint160 uint160S(const std::string& str)
{
uint160 s;
s.SetHex(str);
return s;
}
void ParseClaimtrieId(const UniValue& v, std::string& claimId, const std::string& strName) void ParseClaimtrieId(const UniValue& v, std::string& claimId, const std::string& strName)
{ {
// use IsHexNumber which verify odd strings size // use IsHexNumber which verify odd strings size
@ -137,7 +131,7 @@ std::vector<CClaimNsupports> seqSort(const std::vector<CClaimNsupports>& source)
return claimsNsupports; return claimsNsupports;
} }
std::size_t indexOf(const std::vector<CClaimNsupports>& source, const uint160& claimId) std::size_t indexOf(const std::vector<CClaimNsupports>& source, const CUint160& claimId)
{ {
auto it = std::find_if(source.begin(), source.end(), [&claimId](const CClaimNsupports& claimNsupports) { auto it = std::find_if(source.begin(), source.end(), [&claimId](const CClaimNsupports& claimNsupports) {
return claimNsupports.claim.claimId == claimId; return claimNsupports.claim.claimId == claimId;
@ -150,7 +144,7 @@ UniValue claimToJSON(const CCoinsViewCache& coinsCache, const CClaimValue& claim
{ {
UniValue result(UniValue::VOBJ); UniValue result(UniValue::VOBJ);
auto& coin = coinsCache.AccessCoin(claim.outPoint); auto& coin = coinsCache.AccessCoin(COutPoint(claim.outPoint));
if (!coin.IsSpent()) { if (!coin.IsSpent()) {
std::string name, value; std::string name, value;
if (extractValue(coin.out.scriptPubKey, name, value)) { if (extractValue(coin.out.scriptPubKey, name, value)) {
@ -177,7 +171,7 @@ UniValue supportToJSON(const CCoinsViewCache& coinsCache, const CSupportValue& s
{ {
UniValue ret(UniValue::VOBJ); UniValue ret(UniValue::VOBJ);
auto& coin = coinsCache.AccessCoin(support.outPoint); auto& coin = coinsCache.AccessCoin(COutPoint(support.outPoint));
if (!coin.IsSpent()) { if (!coin.IsSpent()) {
std::string name, value; std::string name, value;
if (extractValue(coin.out.scriptPubKey, name, value)) { if (extractValue(coin.out.scriptPubKey, name, value)) {
@ -296,7 +290,7 @@ static UniValue getvalueforname(const JSONRPCRequest& request)
return ret; return ret;
auto& claimNsupports = auto& claimNsupports =
claimId.length() == claimIdHexLength ? csToName.find(uint160S(claimId)) : claimId.length() == claimIdHexLength ? csToName.find(CUint160S(claimId)) :
!claimId.empty() ? csToName.find(claimId) : csToName.claimsNsupports[0]; !claimId.empty() ? csToName.find(claimId) : csToName.claimsNsupports[0];
if (claimNsupports.IsNull()) if (claimNsupports.IsNull())
@ -546,11 +540,11 @@ UniValue getclaimsfortx(const JSONRPCRequest& request)
std::string sName(vvchParams[0].begin(), vvchParams[0].end()); std::string sName(vvchParams[0].begin(), vvchParams[0].end());
o.pushKV(T_NAME, escapeNonUtf8(sName)); o.pushKV(T_NAME, escapeNonUtf8(sName));
if (op == OP_CLAIM_NAME) { if (op == OP_CLAIM_NAME) {
uint160 claimId = ClaimIdHash(hash, i); CUint160 claimId = ClaimIdHash(hash, i);
o.pushKV(T_CLAIMID, claimId.GetHex()); o.pushKV(T_CLAIMID, claimId.GetHex());
o.pushKV(T_VALUE, HexStr(vvchParams[1].begin(), vvchParams[1].end())); o.pushKV(T_VALUE, HexStr(vvchParams[1].begin(), vvchParams[1].end()));
} else if (op == OP_UPDATE_CLAIM || op == OP_SUPPORT_CLAIM) { } else if (op == OP_UPDATE_CLAIM || op == OP_SUPPORT_CLAIM) {
uint160 claimId(vvchParams[1]); CUint160 claimId(vvchParams[1]);
o.pushKV(T_CLAIMID, claimId.GetHex()); o.pushKV(T_CLAIMID, claimId.GetHex());
if (vvchParams.size() > 2) if (vvchParams.size() > 2)
o.pushKV(T_VALUE, HexStr(vvchParams[2].begin(), vvchParams[2].end())); o.pushKV(T_VALUE, HexStr(vvchParams[2].begin(), vvchParams[2].end()));
@ -755,7 +749,7 @@ UniValue removedToJSON(const std::vector<queueEntryType<T>>& undo)
{ {
UniValue ret(UniValue::VARR); UniValue ret(UniValue::VARR);
for (auto& u : undo) { for (auto& u : undo) {
auto& outPoint = u.second.outPoint; auto outPoint = COutPoint(u.second.outPoint);
ret.push_back(ClaimIdHash(outPoint.hash, outPoint.n).ToString()); ret.push_back(ClaimIdHash(outPoint.hash, outPoint.n).ToString());
} }
return ret; return ret;
@ -780,7 +774,7 @@ UniValue getchangesinblock(const JSONRPCRequest& request)
auto addedUpdated = [](const insertUndoType& insertUndo) { auto addedUpdated = [](const insertUndoType& insertUndo) {
UniValue added(UniValue::VARR); UniValue added(UniValue::VARR);
for (auto& a : insertUndo) for (auto& a : insertUndo)
added.push_back(ClaimIdHash(a.outPoint.hash, a.outPoint.n).ToString()); added.push_back(ClaimIdHash(uint256(a.outPoint.hash), a.outPoint.n).ToString());
return added; return added;
}; };

View file

@ -10,6 +10,7 @@
#include <algorithm> #include <algorithm>
#include <assert.h> #include <assert.h>
#include <claimtrie_serial.h>
#include <ios> #include <ios>
#include <limits> #include <limits>
#include <map> #include <map>

View file

@ -30,7 +30,7 @@ BOOST_AUTO_TEST_CASE(takeover_stability_test) {
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "@bass", "two", 2); CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "@bass", "two", 2);
fixture.IncrementBlocks(1); fixture.IncrementBlocks(1);
BOOST_CHECK(fixture.is_best_claim("@bass", tx2)); BOOST_CHECK(fixture.is_best_claim("@bass", tx2));
uint160 id; int takeover; CUint160 id; int takeover;
BOOST_REQUIRE(fixture.getLastTakeoverForName("@bass", id, takeover)); BOOST_REQUIRE(fixture.getLastTakeoverForName("@bass", id, takeover));
auto height = chainActive.Tip()->nHeight; auto height = chainActive.Tip()->nHeight;
BOOST_CHECK_EQUAL(takeover, height); BOOST_CHECK_EQUAL(takeover, height);
@ -426,7 +426,7 @@ BOOST_AUTO_TEST_CASE(claimtrie_update_takeover_test)
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 5); CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 5);
auto cid = ClaimIdHash(tx1.GetHash(), 0); auto cid = ClaimIdHash(tx1.GetHash(), 0);
fixture.IncrementBlocks(1); fixture.IncrementBlocks(1);
uint160 cid2; CUint160 cid2;
int takeover; int takeover;
int height = chainActive.Tip()->nHeight; int height = chainActive.Tip()->nHeight;
fixture.getLastTakeoverForName("test", cid2, takeover); fixture.getLastTakeoverForName("test", cid2, takeover);
@ -1148,7 +1148,7 @@ BOOST_AUTO_TEST_CASE(basic_merkle_test)
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue, 10); CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue, 10);
fixture.IncrementBlocks(20); fixture.IncrementBlocks(20);
uint256 tx1MerkleHash = fixture.getMerkleHash(); auto tx1MerkleHash = fixture.getMerkleHash();
fixture.DecrementBlocks(20); fixture.DecrementBlocks(20);
BOOST_CHECK(tx1MerkleHash != fixture.getMerkleHash()); BOOST_CHECK(tx1MerkleHash != fixture.getMerkleHash());
fixture.CommitTx(tx1); fixture.CommitTx(tx1);
@ -1230,7 +1230,7 @@ BOOST_AUTO_TEST_CASE(supporting_claims_test)
BOOST_CHECK(fixture.getInfoForName(sName, val)); BOOST_CHECK(fixture.getInfoForName(sName, val));
BOOST_CHECK_EQUAL(val.outPoint.hash, tx1.GetHash()); BOOST_CHECK_EQUAL(val.outPoint.hash, tx1.GetHash());
BOOST_CHECK_EQUAL(val.outPoint.n, 0); BOOST_CHECK_EQUAL(val.outPoint.n, 0);
uint256 tx1MerkleHash = fixture.getMerkleHash(); auto tx1MerkleHash = fixture.getMerkleHash();
CMutableTransaction tx4 = BuildTransaction(tx1); CMutableTransaction tx4 = BuildTransaction(tx1);
CMutableTransaction tx5 = BuildTransaction(tx2); CMutableTransaction tx5 = BuildTransaction(tx2);
@ -1553,7 +1553,7 @@ BOOST_AUTO_TEST_CASE(supporting_claims2_test)
fixture.CommitTx(tx2); fixture.CommitTx(tx2);
fixture.IncrementBlocks(1); // 7 fixture.IncrementBlocks(1); // 7
uint256 rootMerkleHash = fixture.getMerkleHash(); auto rootMerkleHash = fixture.getMerkleHash();
BOOST_CHECK(!pclaimTrie->empty()); BOOST_CHECK(!pclaimTrie->empty());
BOOST_CHECK(!fixture.queueEmpty()); BOOST_CHECK(!fixture.queueEmpty());
@ -1920,7 +1920,7 @@ BOOST_AUTO_TEST_CASE(update_on_support2_test)
CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, name, 1); CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, name, 1);
fixture.IncrementBlocks(1); fixture.IncrementBlocks(1);
uint160 claimId; CUint160 claimId;
int lastTakeover; int lastTakeover;
BOOST_CHECK(fixture.getLastTakeoverForName(name, claimId, lastTakeover)); BOOST_CHECK(fixture.getLastTakeoverForName(name, claimId, lastTakeover));
BOOST_CHECK_EQUAL(lastTakeover, height + 1); BOOST_CHECK_EQUAL(lastTakeover, height + 1);

View file

@ -1,4 +1,5 @@
#include <claimtrie.h>
#include <claimtrie/forks.h>
#include <nameclaim.h> #include <nameclaim.h>
#include <uint256.h> #include <uint256.h>
#include <validation.h> #include <validation.h>
@ -24,12 +25,12 @@ public:
p.hash = Hash(key.begin(), key.end()); p.hash = Hash(key.begin(), key.end());
auto c = value.claimId; auto c = value.claimId;
if (c.IsNull()) if (c.IsNull())
c = ClaimIdHash(p.hash, p.n); c = ClaimIdHash(uint256(p.hash), p.n);
return addClaim(key, p, c, value.nAmount, value.nHeight); return addClaim(key, p, c, value.nAmount, value.nHeight);
} }
bool removeClaimFromTrie(const std::string& key, const COutPoint& outPoint) { bool removeClaimFromTrie(const std::string& key, const CTxOutPoint& outPoint) {
int validHeight; int validHeight;
std::string nodeName; std::string nodeName;
@ -37,7 +38,7 @@ public:
if (p.hash.IsNull()) if (p.hash.IsNull())
p.hash = Hash(key.begin(), key.end()); p.hash = Hash(key.begin(), key.end());
auto ret = removeClaim(ClaimIdHash(p.hash, p.n), p, nodeName, validHeight); auto ret = removeClaim(ClaimIdHash(uint256(p.hash), p.n), p, nodeName, validHeight);
assert(!ret || nodeName == key); assert(!ret || nodeName == key);
return ret; return ret;
} }
@ -47,10 +48,10 @@ public:
if (p.hash.IsNull()) if (p.hash.IsNull())
p.hash = Hash(key.begin(), key.end()); p.hash = Hash(key.begin(), key.end());
return addSupport(key, p, value.nAmount, value.supportedClaimId, value.nHeight); return addSupport(key, p, value.supportedClaimId, value.nAmount, value.nHeight);
} }
bool removeSupportFromMap(const std::string& key, const COutPoint& outPoint) { bool removeSupportFromMap(const std::string& key, const CTxOutPoint& outPoint) {
int validHeight; int validHeight;
std::string nodeName; std::string nodeName;
@ -69,7 +70,7 @@ BOOST_FIXTURE_TEST_SUITE(claimtriecache_tests, RegTestingSetup)
BOOST_AUTO_TEST_CASE(merkle_hash_single_test) BOOST_AUTO_TEST_CASE(merkle_hash_single_test)
{ {
// check empty trie // check empty trie
uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); auto one = uint256S("0000000000000000000000000000000000000000000000000000000000000001");
CClaimTrieCacheTest cc(pclaimTrie); CClaimTrieCacheTest cc(pclaimTrie);
BOOST_CHECK_EQUAL(one, cc.getMerkleHash()); BOOST_CHECK_EQUAL(one, cc.getMerkleHash());
@ -80,30 +81,31 @@ BOOST_AUTO_TEST_CASE(merkle_hash_single_test)
BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test) BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
{ {
uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); auto hash0 = uint256S("0000000000000000000000000000000000000000000000000000000000000001");
CUint160 hash160;
CMutableTransaction tx1 = BuildTransaction(hash0); CMutableTransaction tx1 = BuildTransaction(hash0);
COutPoint tx1OutPoint(tx1.GetHash(), 0); CTxOutPoint tx1OutPoint(tx1.GetHash(), 0);
CMutableTransaction tx2 = BuildTransaction(tx1.GetHash()); CMutableTransaction tx2 = BuildTransaction(tx1.GetHash());
COutPoint tx2OutPoint(tx2.GetHash(), 0); CTxOutPoint tx2OutPoint(tx2.GetHash(), 0);
CMutableTransaction tx3 = BuildTransaction(tx2.GetHash()); CMutableTransaction tx3 = BuildTransaction(tx2.GetHash());
COutPoint tx3OutPoint(tx3.GetHash(), 0); CTxOutPoint tx3OutPoint(tx3.GetHash(), 0);
CMutableTransaction tx4 = BuildTransaction(tx3.GetHash()); CMutableTransaction tx4 = BuildTransaction(tx3.GetHash());
COutPoint tx4OutPoint(tx4.GetHash(), 0); CTxOutPoint tx4OutPoint(tx4.GetHash(), 0);
CMutableTransaction tx5 = BuildTransaction(tx4.GetHash()); CMutableTransaction tx5 = BuildTransaction(tx4.GetHash());
COutPoint tx5OutPoint(tx5.GetHash(), 0); CTxOutPoint tx5OutPoint(tx5.GetHash(), 0);
CMutableTransaction tx6 = BuildTransaction(tx5.GetHash()); CMutableTransaction tx6 = BuildTransaction(tx5.GetHash());
COutPoint tx6OutPoint(tx6.GetHash(), 0); CTxOutPoint tx6OutPoint(tx6.GetHash(), 0);
uint256 hash1; CUint256 hash1;
hash1.SetHex("71c7b8d35b9a3d7ad9a1272b68972979bbd18589f1efe6f27b0bf260a6ba78fa"); hash1.SetHex("71c7b8d35b9a3d7ad9a1272b68972979bbd18589f1efe6f27b0bf260a6ba78fa");
uint256 hash2; CUint256 hash2;
hash2.SetHex("c4fc0e2ad56562a636a0a237a96a5f250ef53495c2cb5edd531f087a8de83722"); hash2.SetHex("c4fc0e2ad56562a636a0a237a96a5f250ef53495c2cb5edd531f087a8de83722");
uint256 hash3; CUint256 hash3;
hash3.SetHex("baf52472bd7da19fe1e35116cfb3bd180d8770ffbe3ae9243df1fb58a14b0975"); hash3.SetHex("baf52472bd7da19fe1e35116cfb3bd180d8770ffbe3ae9243df1fb58a14b0975");
uint256 hash4; CUint256 hash4;
hash4.SetHex("c73232a755bf015f22eaa611b283ff38100f2a23fb6222e86eca363452ba0c51"); hash4.SetHex("c73232a755bf015f22eaa611b283ff38100f2a23fb6222e86eca363452ba0c51");
CClaimTrie master(false, 2, 1); CClaimTrie master(false, 2, 1);
@ -212,10 +214,10 @@ BOOST_AUTO_TEST_CASE(basic_insertion_info_test)
CClaimTrieCacheTest ctc(pclaimTrie); CClaimTrieCacheTest ctc(pclaimTrie);
// create and insert claim // create and insert claim
uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); auto hash0 = uint256S("0000000000000000000000000000000000000000000000000000000000000001");
CMutableTransaction tx1 = BuildTransaction(hash0); CMutableTransaction tx1 = BuildTransaction(hash0);
uint160 claimId = ClaimIdHash(tx1.GetHash(), 0); CUint160 claimId = ClaimIdHash(tx1.GetHash(), 0);
COutPoint claimOutPoint(tx1.GetHash(), 0); CTxOutPoint claimOutPoint(tx1.GetHash(), 0);
CAmount amount(10); CAmount amount(10);
int height = 0; int height = 0;
int validHeight = 0; int validHeight = 0;
@ -236,9 +238,9 @@ BOOST_AUTO_TEST_CASE(basic_insertion_info_test)
// insert a support // insert a support
CAmount supportAmount(10); CAmount supportAmount(10);
uint256 hash1(uint256S("0000000000000000000000000000000000000000000000000000000000000002")); auto hash1 = uint256S("0000000000000000000000000000000000000000000000000000000000000002");
CMutableTransaction tx2 = BuildTransaction(hash1); CMutableTransaction tx2 = BuildTransaction(hash1);
COutPoint supportOutPoint(tx2.GetHash(), 0); CTxOutPoint supportOutPoint(tx2.GetHash(), 0);
CSupportValue support(supportOutPoint, claimId, supportAmount, height, validHeight); CSupportValue support(supportOutPoint, claimId, supportAmount, height, validHeight);
ctc.insertSupportIntoMap("test", support); ctc.insertSupportIntoMap("test", support);
@ -256,7 +258,7 @@ BOOST_AUTO_TEST_CASE(basic_insertion_info_test)
// CClaimTrieCacheTest cc(pclaimTrie); // CClaimTrieCacheTest cc(pclaimTrie);
// BOOST_CHECK_EQUAL(0, cc.getTotalClaimsInTrie()); // BOOST_CHECK_EQUAL(0, cc.getTotalClaimsInTrie());
// //
// COutPoint outpoint; // CTxOutPoint outpoint;
// uint160 claimId; // uint160 claimId;
// CAmount amount(20); // CAmount amount(20);
// int height = 0; // int height = 0;
@ -302,14 +304,13 @@ BOOST_AUTO_TEST_CASE(trie_stays_consistent_test)
"goodness", "goodnight", "goodnatured", "goods", "go", "goody", "goo" "goodness", "goodnight", "goodnatured", "goods", "go", "goody", "goo"
}; };
CClaimTrie trie(false, 0, 1); CClaimTrieCacheTest cache(pclaimTrie);
CClaimTrieCacheTest cache(&trie);
CClaimValue value; CClaimValue value;
for (auto& name: names) { for (auto& name: names) {
value.outPoint.hash = Hash(name.begin(), name.end()); value.outPoint.hash = Hash(name.begin(), name.end());
value.outPoint.n = 0; value.outPoint.n = 0;
value.claimId = ClaimIdHash(value.outPoint.hash, 0); value.claimId = ClaimIdHash(uint256(value.outPoint.hash), 0);
BOOST_CHECK(cache.insertClaimIntoTrie(name, value)); BOOST_CHECK(cache.insertClaimIntoTrie(name, value));
} }
@ -318,17 +319,17 @@ BOOST_AUTO_TEST_CASE(trie_stays_consistent_test)
for (auto& name: names) { for (auto& name: names) {
auto hash = Hash(name.begin(), name.end()); auto hash = Hash(name.begin(), name.end());
BOOST_CHECK(cache.removeClaimFromTrie(name, COutPoint(hash, 0))); BOOST_CHECK(cache.removeClaimFromTrie(name, CTxOutPoint(hash, 0)));
cache.flush(); cache.flush();
BOOST_CHECK(cache.checkConsistency()); BOOST_CHECK(cache.checkConsistency());
} }
BOOST_CHECK(trie.empty()); BOOST_CHECK(pclaimTrie->empty());
} }
BOOST_AUTO_TEST_CASE(verify_basic_serialization) BOOST_AUTO_TEST_CASE(verify_basic_serialization)
{ {
CClaimValue cv; CClaimValue cv;
cv.outPoint = COutPoint(uint256S("123"), 2); cv.outPoint = CTxOutPoint(CUint256S("123"), 2);
cv.nHeight = 3; cv.nHeight = 3;
cv.claimId.SetHex("4567"); cv.claimId.SetHex("4567");
cv.nEffectiveAmount = 4; cv.nEffectiveAmount = 4;

View file

@ -276,7 +276,8 @@ BOOST_AUTO_TEST_CASE(hardfork_disk_test)
BOOST_CHECK_EQUAL(fixture.expirationTime(), 3); BOOST_CHECK_EQUAL(fixture.expirationTime(), 3);
fixture.IncrementBlocks(7, true); fixture.IncrementBlocks(7, true);
BOOST_CHECK_EQUAL(fixture.expirationTime(), 6); BOOST_CHECK_EQUAL(fixture.expirationTime(), 6);
fixture.ValidateTipMatches(chainActive.Tip()); auto tip = chainActive.Tip();
fixture.ReadFromDisk(tip->nHeight, tip->hashClaimTrie);
BOOST_CHECK_EQUAL(fixture.expirationTime(), 6); BOOST_CHECK_EQUAL(fixture.expirationTime(), 6);
// Create a claim and support 1 block before the fork height that will expire after the fork height. // Create a claim and support 1 block before the fork height that will expire after the fork height.
@ -287,7 +288,8 @@ BOOST_AUTO_TEST_CASE(hardfork_disk_test)
CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 1); CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 1);
fixture.IncrementBlocks(1); fixture.IncrementBlocks(1);
fixture.ValidateTipMatches(chainActive.Tip()); tip = chainActive.Tip();
fixture.ReadFromDisk(tip->nHeight, tip->hashClaimTrie);
BOOST_CHECK_EQUAL(fixture.expirationTime(), 3); BOOST_CHECK_EQUAL(fixture.expirationTime(), 3);
fixture.IncrementBlocks(1); fixture.IncrementBlocks(1);
BOOST_CHECK_EQUAL(fixture.expirationTime(), 6); BOOST_CHECK_EQUAL(fixture.expirationTime(), 6);
@ -308,7 +310,8 @@ BOOST_AUTO_TEST_CASE(hardfork_disk_test)
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test2","one",1); CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test2","one",1);
CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(),tx2,"test2",1); CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(),tx2,"test2",1);
fixture.IncrementBlocks(1); fixture.IncrementBlocks(1);
fixture.ValidateTipMatches(chainActive.Tip()); tip = chainActive.Tip();
fixture.ReadFromDisk(tip->nHeight, tip->hashClaimTrie);
CMutableTransaction u2 = fixture.MakeUpdate(tx2, "test2", "two", ClaimIdHash(tx2.GetHash(), 0), 1); CMutableTransaction u2 = fixture.MakeUpdate(tx2, "test2", "two", ClaimIdHash(tx2.GetHash(), 0), 1);
// increment to fork // increment to fork
fixture.IncrementBlocks(2); fixture.IncrementBlocks(2);
@ -503,7 +506,7 @@ BOOST_AUTO_TEST_CASE(claim_expiration_test)
BOOST_CHECK(!fixture.expirationQueueEmpty()); BOOST_CHECK(!fixture.expirationQueueEmpty());
BOOST_CHECK(fixture.getInfoForName(sName, val)); BOOST_CHECK(fixture.getInfoForName(sName, val));
BOOST_CHECK_EQUAL(val.outPoint, tx1OutPoint); BOOST_CHECK_EQUAL(val.outPoint, tx1OutPoint);
uint256 tx1MerkleHash = fixture.getMerkleHash(); auto tx1MerkleHash = fixture.getMerkleHash();
// roll back to before tx3 is valid // roll back to before tx3 is valid
fixture.DecrementBlocks(1); // 10 fixture.DecrementBlocks(1); // 10
@ -601,7 +604,7 @@ BOOST_AUTO_TEST_CASE(expiring_supports_test)
BOOST_CHECK(!fixture.queueEmpty()); BOOST_CHECK(!fixture.queueEmpty());
BOOST_CHECK(!fixture.supportEmpty()); BOOST_CHECK(!fixture.supportEmpty());
BOOST_CHECK(fixture.supportQueueEmpty()); BOOST_CHECK(fixture.supportQueueEmpty());
uint256 rootMerkleHash = fixture.getMerkleHash(); auto rootMerkleHash = fixture.getMerkleHash();
// Advance until tx2 is valid // Advance until tx2 is valid
fixture.IncrementBlocks(20); // 42 fixture.IncrementBlocks(20); // 42

View file

@ -95,16 +95,22 @@ ClaimTrieChainFixture::~ClaimTrieChainFixture()
added_unchecked = false; added_unchecked = false;
DecrementBlocks(chainActive.Height()); DecrementBlocks(chainActive.Height());
auto& consensus = const_cast<Consensus::Params&>(Params().GetConsensus()); auto& consensus = const_cast<Consensus::Params&>(Params().GetConsensus());
if (normalization_original >= 0) if (normalization_original >= 0) {
consensus.nNormalizedNameForkHeight = normalization_original; consensus.nNormalizedNameForkHeight = normalization_original;
const_cast<int&>(base->nNormalizedNameForkHeight) = normalization_original;
}
if (expirationForkHeight >= 0) { if (expirationForkHeight >= 0) {
consensus.nExtendedClaimExpirationForkHeight = expirationForkHeight; consensus.nExtendedClaimExpirationForkHeight = expirationForkHeight;
consensus.nExtendedClaimExpirationTime = extendedExpiration; consensus.nExtendedClaimExpirationTime = extendedExpiration;
consensus.nOriginalClaimExpirationTime = originalExpiration; consensus.nOriginalClaimExpirationTime = originalExpiration;
const_cast<int64_t&>(base->nExtendedClaimExpirationForkHeight) = expirationForkHeight;
const_cast<int64_t&>(base->nOriginalClaimExpirationTime) = originalExpiration;
const_cast<int64_t&>(base->nExtendedClaimExpirationTime) = extendedExpiration;
} }
if (forkhash_original >= 0) if (forkhash_original >= 0) {
consensus.nAllClaimsInMerkleForkHeight = forkhash_original; consensus.nAllClaimsInMerkleForkHeight = forkhash_original;
const_cast<int64_t&>(base->nAllClaimsInMerkleForkHeight) = forkhash_original;
}
} }
void ClaimTrieChainFixture::setExpirationForkHeight(int targetMinusCurrent, int64_t preForkExpirationTime, int64_t postForkExpirationTime) void ClaimTrieChainFixture::setExpirationForkHeight(int targetMinusCurrent, int64_t preForkExpirationTime, int64_t postForkExpirationTime)
@ -119,7 +125,9 @@ void ClaimTrieChainFixture::setExpirationForkHeight(int targetMinusCurrent, int6
consensus.nExtendedClaimExpirationForkHeight = target; consensus.nExtendedClaimExpirationForkHeight = target;
consensus.nExtendedClaimExpirationTime = postForkExpirationTime; consensus.nExtendedClaimExpirationTime = postForkExpirationTime;
consensus.nOriginalClaimExpirationTime = preForkExpirationTime; consensus.nOriginalClaimExpirationTime = preForkExpirationTime;
setExpirationTime(targetMinusCurrent >= 0 ? preForkExpirationTime : postForkExpirationTime); const_cast<int64_t&>(base->nExtendedClaimExpirationForkHeight) = target;
const_cast<int64_t&>(base->nOriginalClaimExpirationTime) = preForkExpirationTime;
const_cast<int64_t&>(base->nExtendedClaimExpirationTime) = postForkExpirationTime;
} }
void ClaimTrieChainFixture::setNormalizationForkHeight(int targetMinusCurrent) void ClaimTrieChainFixture::setNormalizationForkHeight(int targetMinusCurrent)
@ -129,6 +137,7 @@ void ClaimTrieChainFixture::setNormalizationForkHeight(int targetMinusCurrent)
if (normalization_original < 0) if (normalization_original < 0)
normalization_original = consensus.nNormalizedNameForkHeight; normalization_original = consensus.nNormalizedNameForkHeight;
consensus.nNormalizedNameForkHeight = target; consensus.nNormalizedNameForkHeight = target;
const_cast<int&>(base->nNormalizedNameForkHeight) = target;
} }
void ClaimTrieChainFixture::setHashForkHeight(int targetMinusCurrent) void ClaimTrieChainFixture::setHashForkHeight(int targetMinusCurrent)
@ -138,6 +147,7 @@ void ClaimTrieChainFixture::setHashForkHeight(int targetMinusCurrent)
if (forkhash_original < 0) if (forkhash_original < 0)
forkhash_original = consensus.nAllClaimsInMerkleForkHeight; forkhash_original = consensus.nAllClaimsInMerkleForkHeight;
consensus.nAllClaimsInMerkleForkHeight = target; consensus.nAllClaimsInMerkleForkHeight = target;
const_cast<int64_t&>(base->nAllClaimsInMerkleForkHeight) = target;
} }
bool ClaimTrieChainFixture::CreateBlock(const std::unique_ptr<CBlockTemplate>& pblocktemplate) bool ClaimTrieChainFixture::CreateBlock(const std::unique_ptr<CBlockTemplate>& pblocktemplate)
@ -277,9 +287,9 @@ void ClaimTrieChainFixture::IncrementBlocks(int num_blocks, bool mark)
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), num_txs_for_next_block + 1); BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), num_txs_for_next_block + 1);
BOOST_REQUIRE(CreateBlock(pblocktemplate)); BOOST_REQUIRE(CreateBlock(pblocktemplate));
num_txs_for_next_block = 0; num_txs_for_next_block = 0;
expirationHeight = chainActive.Height();
nNextHeight = chainActive.Height() + 1; nNextHeight = chainActive.Height() + 1;
} }
setExpirationTime(Params().GetConsensus().GetExpirationTime(nNextHeight - 1));
} }
// disconnect i blocks from tip // disconnect i blocks from tip
@ -295,8 +305,8 @@ void ClaimTrieChainFixture::DecrementBlocks(int num_blocks)
BOOST_CHECK_EQUAL(ActivateBestChain(state, Params()), true); BOOST_CHECK_EQUAL(ActivateBestChain(state, Params()), true);
mempool.clear(); mempool.clear();
num_txs_for_next_block = 0; num_txs_for_next_block = 0;
expirationHeight = chainActive.Height();
nNextHeight = chainActive.Height() + 1; nNextHeight = chainActive.Height() + 1;
setExpirationTime(Params().GetConsensus().GetExpirationTime(nNextHeight - 1));
} }
// decrement back to last mark // decrement back to last mark

View file

@ -6,7 +6,7 @@
#define _CLAIMTRIEFIXTURE_H_ #define _CLAIMTRIEFIXTURE_H_
#include <chainparams.h> #include <chainparams.h>
#include <claimtrie.h> #include <claimtrie/forks.h>
#include <coins.h> #include <coins.h>
#include <consensus/merkle.h> #include <consensus/merkle.h>
#include <consensus/validation.h> #include <consensus/validation.h>

View file

@ -6,7 +6,7 @@
using namespace std; using namespace std;
void ValidatePairs(CClaimTrieCache& cache, const std::vector<std::pair<bool, uint256>>& pairs, uint256 claimHash) void ValidatePairs(CClaimTrieCache& cache, const std::vector<std::pair<bool, CUint256>>& pairs, CUint256 claimHash)
{ {
for (auto& pair : pairs) for (auto& pair : pairs)
if (pair.first) // we're on the right because we were an odd index number if (pair.first) // we're on the right because we were an odd index number
@ -27,7 +27,7 @@ BOOST_AUTO_TEST_CASE(hash_includes_all_claims_rollback_test)
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1);
fixture.IncrementBlocks(1); fixture.IncrementBlocks(1);
uint256 currentRoot = fixture.getMerkleHash(); auto currentRoot = fixture.getMerkleHash();
fixture.IncrementBlocks(1); fixture.IncrementBlocks(1);
BOOST_CHECK_EQUAL(currentRoot, fixture.getMerkleHash()); BOOST_CHECK_EQUAL(currentRoot, fixture.getMerkleHash());
fixture.IncrementBlocks(3); fixture.IncrementBlocks(3);
@ -81,8 +81,7 @@ BOOST_AUTO_TEST_CASE(hash_includes_all_claims_triple_test)
BOOST_CHECK(fixture.getProofForName(name, claim.claimId, proof)); BOOST_CHECK(fixture.getProofForName(name, claim.claimId, proof));
BOOST_CHECK(proof.hasValue); BOOST_CHECK(proof.hasValue);
BOOST_CHECK_EQUAL(proof.outPoint, claim.outPoint); BOOST_CHECK_EQUAL(proof.outPoint, claim.outPoint);
BOOST_CHECK_EQUAL(proof.nHeightOfLastTakeover, cfn.nLastTakeoverHeight); auto claimHash = getValueHash(claim.outPoint, proof.nHeightOfLastTakeover);
uint256 claimHash = getValueHash(claim.outPoint, proof.nHeightOfLastTakeover);
ValidatePairs(fixture, proof.pairs, claimHash); ValidatePairs(fixture, proof.pairs, claimHash);
} }
} }
@ -111,7 +110,7 @@ BOOST_AUTO_TEST_CASE(hash_includes_all_claims_branched_test)
BOOST_CHECK(fixture.getProofForName(name, claim.claimId, proof)); BOOST_CHECK(fixture.getProofForName(name, claim.claimId, proof));
BOOST_CHECK(proof.hasValue); BOOST_CHECK(proof.hasValue);
BOOST_CHECK_EQUAL(proof.outPoint, claim.outPoint); BOOST_CHECK_EQUAL(proof.outPoint, claim.outPoint);
uint256 claimHash = getValueHash(claim.outPoint, proof.nHeightOfLastTakeover); auto claimHash = getValueHash(claim.outPoint, proof.nHeightOfLastTakeover);
ValidatePairs(fixture, proof.pairs, claimHash); ValidatePairs(fixture, proof.pairs, claimHash);
} }
} }
@ -172,15 +171,15 @@ BOOST_AUTO_TEST_CASE(hash_claims_children_fuzzer_test)
BOOST_CHECK(fixture.getProofForName(name, claim.claimId, proof)); BOOST_CHECK(fixture.getProofForName(name, claim.claimId, proof));
BOOST_CHECK(proof.hasValue); BOOST_CHECK(proof.hasValue);
BOOST_CHECK_EQUAL(proof.outPoint, claim.outPoint); BOOST_CHECK_EQUAL(proof.outPoint, claim.outPoint);
uint256 claimHash = getValueHash(claim.outPoint, proof.nHeightOfLastTakeover); auto claimHash = getValueHash(claim.outPoint, proof.nHeightOfLastTakeover);
ValidatePairs(fixture, proof.pairs, claimHash); ValidatePairs(fixture, proof.pairs, claimHash);
} }
} }
} }
bool verify_proof(const CClaimTrieProof proof, uint256 rootHash, const std::string& name) bool verify_proof(const CClaimTrieProof proof, CUint256 rootHash, const std::string& name)
{ {
uint256 previousComputedHash; CUint256 previousComputedHash;
std::string computedReverseName; std::string computedReverseName;
bool verifiedValue = false; bool verifiedValue = false;
@ -189,7 +188,7 @@ bool verify_proof(const CClaimTrieProof proof, uint256 rootHash, const std::stri
std::vector<unsigned char> vchToHash; std::vector<unsigned char> vchToHash;
for (auto itChildren = itNodes->children.begin(); itChildren != itNodes->children.end(); ++itChildren) { for (auto itChildren = itNodes->children.begin(); itChildren != itNodes->children.end(); ++itChildren) {
vchToHash.push_back(itChildren->first); vchToHash.push_back(itChildren->first);
uint256 childHash; CUint256 childHash;
if (itChildren->second.IsNull()) { if (itChildren->second.IsNull()) {
if (previousComputedHash.IsNull()) { if (previousComputedHash.IsNull()) {
return false; return false;
@ -209,7 +208,7 @@ bool verify_proof(const CClaimTrieProof proof, uint256 rootHash, const std::stri
return false; return false;
} }
if (itNodes->hasValue) { if (itNodes->hasValue) {
uint256 valHash; CUint256 valHash;
if (itNodes->valHash.IsNull()) { if (itNodes->valHash.IsNull()) {
if (itNodes != proof.nodes.rbegin()) { if (itNodes != proof.nodes.rbegin()) {
return false; return false;
@ -232,7 +231,7 @@ bool verify_proof(const CClaimTrieProof proof, uint256 rootHash, const std::stri
std::vector<unsigned char> vchHash(hasher.OUTPUT_SIZE); std::vector<unsigned char> vchHash(hasher.OUTPUT_SIZE);
hasher.Write(vchToHash.data(), vchToHash.size()); hasher.Write(vchToHash.data(), vchToHash.size());
hasher.Finalize(&(vchHash[0])); hasher.Finalize(&(vchHash[0]));
uint256 calculatedHash(vchHash); CUint256 calculatedHash(vchHash);
previousComputedHash = calculatedHash; previousComputedHash = calculatedHash;
} }
if (previousComputedHash != rootHash) { if (previousComputedHash != rootHash) {
@ -324,7 +323,7 @@ BOOST_AUTO_TEST_CASE(value_proof_test)
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName6)); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName6));
BOOST_CHECK_EQUAL(proof.hasValue, false); BOOST_CHECK_EQUAL(proof.hasValue, false);
BOOST_CHECK(fixture.getProofForName(sName7, ClaimIdHash(fixture.getMerkleHash(), 0), proof)); BOOST_CHECK(fixture.getProofForName(sName7, ClaimIdHash(uint256(fixture.getMerkleHash()), 0), proof));
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName7)); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName7));
BOOST_CHECK_EQUAL(proof.hasValue, false); BOOST_CHECK_EQUAL(proof.hasValue, false);
@ -363,8 +362,8 @@ BOOST_AUTO_TEST_CASE(value_proof_test)
// Check that blocks with bogus calimtrie hash is rejected // Check that blocks with bogus calimtrie hash is rejected
BOOST_AUTO_TEST_CASE(bogus_claimtrie_hash_test) BOOST_AUTO_TEST_CASE(bogus_claimtrie_hash_test)
{ {
ClaimTrieChainFixture fixture; ClaimTrieChainFixture fixture;
std::string sName("test"); std::string sName("test");
std::string sValue1("test"); std::string sValue1("test");

View file

@ -307,8 +307,8 @@ BOOST_AUTO_TEST_CASE(normalization_removal_test)
cache.addClaim("AB", COutPoint(tx1.GetHash(), 0), ClaimIdHash(tx1.GetHash(), 0), 1, height); cache.addClaim("AB", COutPoint(tx1.GetHash(), 0), ClaimIdHash(tx1.GetHash(), 0), 1, height);
cache.addClaim("Ab", COutPoint(tx2.GetHash(), 0), ClaimIdHash(tx2.GetHash(), 0), 2, height); cache.addClaim("Ab", COutPoint(tx2.GetHash(), 0), ClaimIdHash(tx2.GetHash(), 0), 2, height);
cache.addClaim("aB", COutPoint(tx3.GetHash(), 0), ClaimIdHash(tx3.GetHash(), 0), 3, height); cache.addClaim("aB", COutPoint(tx3.GetHash(), 0), ClaimIdHash(tx3.GetHash(), 0), 3, height);
cache.addSupport("AB", COutPoint(sx1.GetHash(), 0), 1, ClaimIdHash(tx1.GetHash(), 0), height); cache.addSupport("AB", COutPoint(sx1.GetHash(), 0), ClaimIdHash(tx1.GetHash(), 0), 1, height);
cache.addSupport("Ab", COutPoint(sx2.GetHash(), 0), 1, ClaimIdHash(tx2.GetHash(), 0), height); cache.addSupport("Ab", COutPoint(sx2.GetHash(), 0), ClaimIdHash(tx2.GetHash(), 0), 1, height);
insertUndoType insertUndo; insertUndoType insertUndo;
claimUndoType expireUndo; claimUndoType expireUndo;
insertUndoType insertSupportUndo; insertUndoType insertSupportUndo;

View file

@ -6,7 +6,7 @@
using namespace std; using namespace std;
extern void ValidatePairs(CClaimTrieCache& cache, const std::vector<std::pair<bool, uint256>>& pairs, uint256 claimHash); extern void ValidatePairs(CClaimTrieCache& cache, const std::vector<std::pair<bool, CUint256>>& pairs, CUint256 claimHash);
BOOST_FIXTURE_TEST_SUITE(claimtrierpc_tests, RegTestingSetup) BOOST_FIXTURE_TEST_SUITE(claimtrierpc_tests, RegTestingSetup)
@ -190,12 +190,12 @@ BOOST_AUTO_TEST_CASE(claim_rpcs_rollback3_test)
BOOST_CHECK_EQUAL(valueResults[T_AMOUNT].get_int(), 3); BOOST_CHECK_EQUAL(valueResults[T_AMOUNT].get_int(), 3);
} }
std::vector<std::pair<bool, uint256>> jsonToPairs(const UniValue& jsonPair) std::vector<std::pair<bool, CUint256>> jsonToPairs(const UniValue& jsonPair)
{ {
std::vector<std::pair<bool, uint256>> pairs; std::vector<std::pair<bool, CUint256>> pairs;
for (std::size_t i = 0; i < jsonPair.size(); ++i) { for (std::size_t i = 0; i < jsonPair.size(); ++i) {
auto& jpair = jsonPair[i]; auto& jpair = jsonPair[i];
pairs.emplace_back(jpair[T_ODD].get_bool(), uint256S(jpair[T_HASH].get_str())); pairs.emplace_back(jpair[T_ODD].get_bool(), CUint256S(jpair[T_HASH].get_str()));
} }
return pairs; return pairs;
} }

View file

@ -19,7 +19,6 @@
#include <rpc/register.h> #include <rpc/register.h>
#include <script/sigcache.h> #include <script/sigcache.h>
#include "claimtrie.h"
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <boost/test/unit_test_parameters.hpp> #include <boost/test/unit_test_parameters.hpp>
@ -61,24 +60,33 @@ std::ostream& operator<<(std::ostream& os, const COutPoint& point)
return os; return os;
} }
std::ostream& operator<<(std::ostream& os, const CUint256& num)
{
os << num.ToString();
return os;
}
std::ostream& operator<<(std::ostream& os, const CUint160& num)
{
os << num.ToString();
return os;
}
std::ostream& operator<<(std::ostream& os, const CTxOutPoint& point)
{
os << point.ToString();
return os;
}
std::ostream& operator<<(std::ostream& os, const CClaimValue& claim) std::ostream& operator<<(std::ostream& os, const CClaimValue& claim)
{ {
os << "claim(" << claim.outPoint.ToString() os << claim.ToString();
<< ", " << claim.claimId.ToString()
<< ", " << claim.nAmount
<< ", " << claim.nEffectiveAmount
<< ", " << claim.nHeight
<< ", " << claim.nValidAtHeight << ')';
return os; return os;
} }
std::ostream& operator<<(std::ostream& os, const CSupportValue& support) std::ostream& operator<<(std::ostream& os, const CSupportValue& support)
{ {
os << "support(" << support.outPoint.ToString() os << support.ToString();
<< ", " << support.supportedClaimId.ToString()
<< ", " << support.nAmount
<< ", " << support.nHeight
<< ", " << support.nValidAtHeight << ')';
return os; return os;
} }
@ -91,6 +99,7 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
g_logger->m_print_to_console = true; g_logger->m_print_to_console = true;
g_logger->m_log_time_micros = true; g_logger->m_log_time_micros = true;
g_logger->EnableCategory(BCLog::ALL); g_logger->EnableCategory(BCLog::ALL);
CLogPrint::global().setLogger(g_logger);
} }
SHA256AutoDetect(); SHA256AutoDetect();
@ -138,7 +147,14 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
pblocktree.reset(new CBlockTreeDB(1 << 20, true)); pblocktree.reset(new CBlockTreeDB(1 << 20, true));
pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true)); pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true));
pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get())); pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get()));
pclaimTrie = new CClaimTrie(true, 0, 1); auto& consensus = chainparams.GetConsensus();
pclaimTrie = new CClaimTrie(true, false,
consensus.nNormalizedNameForkHeight,
consensus.nOriginalClaimExpirationTime,
consensus.nExtendedClaimExpirationTime,
consensus.nExtendedClaimExpirationForkHeight,
consensus.nAllClaimsInMerkleForkHeight, 1);
if (!LoadGenesisBlock(chainparams)) { if (!LoadGenesisBlock(chainparams)) {
throw std::runtime_error("LoadGenesisBlock failed."); throw std::runtime_error("LoadGenesisBlock failed.");
} }

View file

@ -6,6 +6,7 @@
#define BITCOIN_TEST_TEST_BITCOIN_H #define BITCOIN_TEST_TEST_BITCOIN_H
#include <chainparamsbase.h> #include <chainparamsbase.h>
#include <claimtrie/forks.h>
#include <fs.h> #include <fs.h>
#include <key.h> #include <key.h>
#include <pubkey.h> #include <pubkey.h>
@ -134,10 +135,9 @@ std::ostream& operator<<(std::ostream& os, const uint256& num);
std::ostream& operator<<(std::ostream& os, const uint160& num); std::ostream& operator<<(std::ostream& os, const uint160& num);
std::ostream& operator<<(std::ostream& os, const COutPoint& point); std::ostream& operator<<(std::ostream& os, const COutPoint& point);
struct CClaimValue; std::ostream& operator<<(std::ostream& os, const CUint256& num);
std::ostream& operator<<(std::ostream& os, const CUint160& num);
std::ostream& operator<<(std::ostream& os, const CTxOutPoint& point);
std::ostream& operator<<(std::ostream& os, const CClaimValue& claim); std::ostream& operator<<(std::ostream& os, const CClaimValue& claim);
struct CSupportValue;
std::ostream& operator<<(std::ostream& os, const CSupportValue& support); std::ostream& operator<<(std::ostream& os, const CSupportValue& support);
#endif #endif

View file

@ -14,6 +14,8 @@
#include <vector> #include <vector>
#include <crypto/common.h> #include <crypto/common.h>
#include <claimtrie/uints.h>
/** Template base class for fixed-sized opaque blobs. */ /** Template base class for fixed-sized opaque blobs. */
template<unsigned int BITS> template<unsigned int BITS>
class base_blob class base_blob
@ -27,6 +29,11 @@ public:
memset(data, 0, sizeof(data)); memset(data, 0, sizeof(data));
} }
explicit base_blob(const CBaseBlob<BITS>& b)
{
std::copy(b.begin(), b.end(), begin());
}
explicit base_blob(const std::vector<unsigned char>& vch); explicit base_blob(const std::vector<unsigned char>& vch);
bool IsNull() const bool IsNull() const
@ -102,6 +109,13 @@ public:
{ {
s.read((char*)data, sizeof(data)); s.read((char*)data, sizeof(data));
} }
operator CBaseBlob<BITS>() const
{
CBaseBlob<BITS> c;
std::copy(begin(), end(), c.begin());
return c;
}
}; };
/** 160-bit opaque blob. /** 160-bit opaque blob.
@ -110,8 +124,7 @@ public:
*/ */
class uint160 : public base_blob<160> { class uint160 : public base_blob<160> {
public: public:
uint160() {} using base_blob<160>::base_blob;
explicit uint160(const std::vector<unsigned char>& vch) : base_blob<160>(vch) {}
}; };
/** 256-bit opaque blob. /** 256-bit opaque blob.
@ -121,8 +134,7 @@ public:
*/ */
class uint256 : public base_blob<256> { class uint256 : public base_blob<256> {
public: public:
uint256() {} using base_blob<256>::base_blob;
explicit uint256(const std::vector<unsigned char>& vch) : base_blob<256>(vch) {}
/** A cheap hash function that just returns 64 bits from the result, it can be /** A cheap hash function that just returns 64 bits from the result, it can be
* used when the contents are considered uniformly random. It is not appropriate * used when the contents are considered uniformly random. It is not appropriate

View file

@ -7,7 +7,7 @@
#define BITCOIN_UNDO_H #define BITCOIN_UNDO_H
#include <compressor.h> #include <compressor.h>
#include <claimtrie.h> #include <claimtrie/forks.h>
#include <primitives/transaction.h> #include <primitives/transaction.h>
#include <serialize.h> #include <serialize.h>

View file

@ -11,7 +11,7 @@
#endif #endif
#include <amount.h> #include <amount.h>
#include <claimtrie.h> #include <claimtrie/forks.h>
#include <coins.h> #include <coins.h>
#include <fs.h> #include <fs.h>
#include <index/txindex.h> #include <index/txindex.h>

View file

@ -7,6 +7,7 @@
#include <chain.h> #include <chain.h>
#include <consensus/validation.h> #include <consensus/validation.h>
#include <core_io.h> #include <core_io.h>
#include <claimtrie/forks.h>
#include <httpserver.h> #include <httpserver.h>
#include <validation.h> #include <validation.h>
#include <key_io.h> #include <key_io.h>
@ -952,7 +953,7 @@ UniValue supportclaim(const JSONRPCRequest& request)
if (isTip) { if (isTip) {
CTransactionRef ref; CTransactionRef ref;
uint256 block; uint256 block;
if (!GetTransaction(claimNsupports.claim.outPoint.hash, ref, Params().GetConsensus(), block, true)) if (!GetTransaction(uint256(claimNsupports.claim.outPoint.hash), ref, Params().GetConsensus(), block, true))
throw JSONRPCError(RPC_INVALID_PARAMETER, "Unable to locate the TX with the claim's output."); throw JSONRPCError(RPC_INVALID_PARAMETER, "Unable to locate the TX with the claim's output.");
if (!ExtractDestination(ref->vout[claimNsupports.claim.outPoint.n].scriptPubKey, dest)) if (!ExtractDestination(ref->vout[claimNsupports.claim.outPoint.n].scriptPubKey, dest))
throw JSONRPCError(RPC_INVALID_PARAMETER, "Unable to extract the destination from the chosen claim."); throw JSONRPCError(RPC_INVALID_PARAMETER, "Unable to extract the destination from the chosen claim.");