removed duplicate trie in RAM, other norm fixes

also includes code to validate incoming utf8
moved normalization from claimTrie; all in cache now

also fixed a few post-merge issues
added handling for support normalization

fixed failure to handle unnormalized items reinserted on rollback

fixing ICU deps for Travis build

get more info on Travis build failure

Travis experiment 2: ICU fPIC

add independent tests to check string normalization only

move comment to proper location, and note what excpetion is thrown

add RPC call checknormalization so user can see what normalization does

made expiration at norm time smarter

also rearranged unit test code to avoid some spurious errors
made ICU compile statically

also fixed early exit in reproducible_build script
changed to keep original name

removed ability to return just-added supports

it was impossible to get the normalized names correct there
apparently the -s is no longer appreciated

moved normalization code to separate file

also fixed bug on effective amount
fixed performance problem on trie upgrade

fixed issue with valid height on rollback

fixed issue with post-normalization name q data

fixed failure to remove normalized claims on rollback

post-merge fixes

post-merge fixes
This commit is contained in:
Brannon King 2018-12-14 23:21:52 +01:00
parent 223b6047cd
commit fd6e26608d
20 changed files with 1407 additions and 1226 deletions

View file

@ -31,8 +31,8 @@ before_install:
install: true
script:
- mkdir -p "dist/${TRAVIS_BRANCH}"
- if [[ "${TARGET}" == "osx" ]]; then ./reproducible_build.sh -t -o -c; fi
- if [[ "${TARGET}" == "linux" ]]; then ./reproducible_build.sh -t -o -c -f; fi
- if [[ "${TARGET}" == "osx" ]]; then ./reproducible_build.sh -t -o -r; fi
- if [[ "${TARGET}" == "linux" ]]; then ./reproducible_build.sh -t -o; fi
- if [[ "${TARGET}" == "windows" ]]; then ./packaging/build_windows.sh; fi
- if [[ "${TARGET}" == "osx" ]]; then zip -j "dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip" src/lbrycrdd src/lbrycrd-cli src/lbrycrd-tx; fi
- if [[ "${TARGET}" == "linux" ]]; then zip -j "dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip" src/lbrycrdd src/lbrycrd-cli src/lbrycrd-tx; fi

View file

@ -749,22 +749,19 @@ if test x$use_pkgconfig = xyes; then
AC_MSG_ERROR(pkg-config not found.)
fi
if test "${ICU_PREFIX}" != "auto"; then
PKG_CONFIG_PATH="${ICU_PREFIX}/lib/pkgconfig:$PKG_CONFIG_PATH"
export PKG_CONFIG_PATH
fi
: #NOP
m4_ifdef(
[PKG_CHECK_MODULES],
[
ICU_CPPFLAGS="-I$ICU_PREFIX/include"
CPPFLAGS="$ICU_CPPFLAGS $CPPFLAGS"
ICU_LIBS="-L$ICU_PREFIX/lib -licui18n -licuuc -licudata -dl"
AC_MSG_WARN([Using ICU_CPPFLAGS $ICU_CPPFLAGS])
AC_MSG_WARN([Using CPPFLAGS $CPPFLAGS])
AC_CHECK_HEADER([unicode/errorcode.h],,AC_MSG_ERROR(libicu headers missing))
AC_CHECK_LIB([icudata], [main], ICU_LIBS="-L$ICU_PREFIX/lib -licui18n -licuuc -licudata -dl",
AC_CHECK_LIB([icu18n], [main],ICU_LIBS=$ICU_LIBS, ICU_LIBS="-L$ICU_PREFIX/lib -lsicudt -lsicuin -lsicuio -lsicule -lsiculx -lsicutest -lsicutu -lsicuuc"))
PKG_CHECK_MODULES([SSL], [libssl],, [AC_MSG_ERROR(openssl not found.)])
PKG_CHECK_MODULES([CRYPTO], [libcrypto],,[AC_MSG_ERROR(libcrypto not found.)])
PKG_CHECK_MODULES([ICU], [icu-i18n],, [AC_MSG_ERROR(icu-i18n not found.)])
AC_CHECK_HEADER([unicode/errorcode.h],, AC_MSG_ERROR(libicu headers missing))
PKG_CHECK_MODULES([SSL], [libssl],, [AC_MSG_ERROR(openssl not found.)])
PKG_CHECK_MODULES([CRYPTO], [libcrypto],, [AC_MSG_ERROR(libcrypto not found.)])
BITCOIN_QT_CHECK([PKG_CHECK_MODULES([PROTOBUF], [protobuf], [have_protobuf=yes], [BITCOIN_QT_FAIL(libprotobuf not found)])])
if test x$use_qr != xno; then
@ -876,8 +873,8 @@ AC_SUBST(UNIVALUE_LIBS)
CXXFLAGS_TEMP="$CXXFLAGS"
LIBS_TEMP="$LIBS"
CXXFLAGS="$CXXFLAGS $CPPFLAGS $SSL_CFLAGS $CRYPTO_CFLAGS $ICU_PREFIX/include"
LIBS="$LIBS $SSL_LIBS $CRYPTO_LIBS"
CXXFLAGS="$CXXFLAGS $CPPFLAGS $SSL_CFLAGS $CRYPTO_CFLAGS"
LIBS="$LIBS $SSL_LIBS $CRYPTO_LIBS $ICU_LIBS"
#AC_CHECK_HEADER([openssl/ec.h],, AC_MSG_ERROR(OpenSSL ec header missing),)
CXXFLAGS="$CXXFLAGS_TEMP"
LIBS="$LIBS_TEMP"
@ -1069,7 +1066,6 @@ AC_SUBST(LIBTOOL_APP_LDFLAGS)
AC_SUBST(USE_UPNP)
AC_SUBST(USE_QRCODE)
AC_SUBST(BOOST_LIBS)
AC_SUBST(ICU_PREFIX)
AC_SUBST(ICU_CPPFLAGS)
AC_SUBST(ICU_LIBS)
AC_SUBST(TESTDEFS)

View file

@ -6,7 +6,7 @@ sudo apt-get update
sudo apt-get install -y --no-install-recommends \
g++-mingw-w64-i686 mingw-w64-i686-dev g++-mingw-w64-x86-64 \
mingw-w64-x86-64-dev build-essential libtool autotools-dev automake pkg-config \
libssl-dev libevent-dev bsdmainutils curl ca-certificates libicu-dev
libssl-dev libevent-dev bsdmainutils curl ca-certificates
#################################################################
# Build ICU for Linux first so that we can cross compile it below
@ -15,8 +15,8 @@ staging_dir=/tmp/icu_staging
icu_linux_dir=$staging_dir/build_icu_linux
mkdir -p $staging_dir
pushd $staging_dir
wget http://download.icu-project.org/files/icu4c/55.1/icu4c-55_1-src.tgz
tar -xvzf icu4c-55_1-src.tgz
wget -c http://download.icu-project.org/files/icu4c/57.1/icu4c-57_1-src.tgz
tar -xvzf icu4c-57_1-src.tgz
pushd icu/source
./runConfigureICU Linux --prefix=$icu_linux_dir --enable-extras=no --enable-strict=no -enable-static --enable-shared=no --enable-tests=no --enable-samples=no --enable-dyload=no
make

View file

@ -15,7 +15,6 @@ function HELP {
echo
echo "Optional arguments:"
echo
echo "-c: don't clone a fresh copy of the repo"
echo "-f: check formatting of committed code relative to master"
echo "-r: remove intermediate files."
echo "-l: build only lbrycrd"
@ -26,8 +25,7 @@ function HELP {
exit 1
}
CLONE=false
CLEAN=true
CLEAN=false
CHECK_CODE_FORMAT=false
BUILD_DEPENDENCIES=true
BUILD_LBRYCRD=true
@ -39,15 +37,12 @@ OUTPUT_LOG=true
while getopts :crfldoth:w:d: FLAG; do
case $FLAG in
c)
CLONE=false
;;
r)
CLEAN=true
;;
f)
CHECK_CODE_FORMAT=true
;;
f)
CHECK_CODE_FORMAT=true
;;
l)
BUILD_DEPENDENCIES=false
;;
@ -81,13 +76,11 @@ if (( EUID != 0 )); then
SUDO='sudo'
fi
if [ "${CLONE}" = false ]; then
if [ "$(basename "$PWD")" != "lbrycrd" ]; then
echo "Not currently in the lbrycrd directory. Cowardly refusing to go forward"
exit 1
fi
SOURCE_DIR=$PWD
if [ "$(basename "$PWD")" != "lbrycrd" ]; then
echo "Not currently in the lbrycrd directory. Cowardly refusing to go forward"
exit 1
fi
SOURCE_DIR=$PWD
if [ -z "${TRAVIS_OS_NAME+x}" ]; then
if [ "$(uname -s)" = "Darwin" ]; then
@ -133,44 +126,40 @@ function exit_at_60() {
# - echo message
function wait_and_echo() {
PID=$1
(set -o | grep xtrace | grep -q on)
TRACE_STATUS=$?
# disable xtrace or else this will get verbose, which is what
# I'm trying to avoid by going through all of this nonsense anyway
set +o xtrace
TIME=0
SLEEP=5
SLEEP=3
# loop until the process is no longer running
# check every $SLEEP seconds, echoing a message every minute
while (ps -p "${PID}" > /dev/null); do
exit_at_60 "$2"
sleep "${SLEEP}"
done
# restore the xtrace setting
if [ "${TRACE_STATUS}" -eq 0 ]; then
set -o xtrace
fi
wait "$PID"
return $?
}
# run a command ($1) in the background
# logging its stdout and stderr to $2
# and wait until it completed
function background() {
$1 >> "$2" 2>&1 &
eval $1 >> "$2" 2>&1 &
BACKGROUND_PID=$!
wait_and_echo $BACKGROUND_PID "$3"
(
set +xe # do not echo each sleep call in trace mode
wait_and_echo $BACKGROUND_PID "$3"
)
wait $BACKGROUND_PID
}
function cleanup() {
rv=$?
if [ $rv -eq 0 ]; then
return $rv
fi
# cat the log file if it exists
if [ -f "$2" ] && [ "${OUTPUT_LOG}" = true ]; then
echo
echo "Output of log file $2"
echo
tail -n 1000 "$2"
tail -n 200 "$2"
echo
fi
# delete the build directory
@ -209,7 +198,7 @@ function install_brew_packages() {
brew_if_not_installed automake
# something weird happened where glibtoolize was failing to find
# sed, and reinstalling fixes it.
brew reinstall -s libtool
brew reinstall libtool
brew_if_not_installed pkg-config
brew_if_not_installed protobuf
brew_if_not_installed gmp
@ -220,6 +209,10 @@ function install_brew_packages() {
}
function install_apt_packages() {
if [ -d "${OUTPUT_DIR}" ]; then
return 0
fi
if [ -z "${TRAVIS+x}" ]; then
# if not on travis, its nice to see progress
QUIET=""
@ -265,7 +258,7 @@ function build_dependencies() {
build_dependency "${BDB_PREFIX}" "${LOG_DIR}/bdb_build.log" build_bdb
set +u
export PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:${OPENSSL_PREFIX}/lib/pkgconfig/"
export PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:${OPENSSL_PREFIX}/lib/pkgconfig"
set -u
build_dependency "${BOOST_PREFIX}" "${LOG_DIR}/boost_build.log" build_boost
@ -275,6 +268,7 @@ function build_dependencies() {
function build_bdb() {
BDB_LOG="$1"
if [ "${OS_NAME}" = "osx" ]; then
# TODO: make this handle already patched files
patch db-4.8.30.NC/dbinc/atomic.h < atomic.patch
fi
cd db-4.8.30.NC/build_unix
@ -309,29 +303,31 @@ function build_boost() {
echo "int main() { return 0; }" > libs/regex/build/has_icu_test.cpp
echo "int main() { return 0; }" > libs/locale/build/has_icu_test.cpp
export BOOST_ICU_LIBS="$(pkg-config icu-i18n --libs) -dl"
export BOOST_LDFLAGS="${BOOST_PREFIX}/lib ${ICU_PREFIX}/lib ${BOOST_ICU_LIBS}"
export BOOST_ICU_LIBS="-L${ICU_PREFIX}/lib -licui18n -licuuc -licudata -dl"
export BOOST_LDFLAGS="-L${BOOST_PREFIX}/lib ${BOOST_ICU_LIBS}"
echo "BOOST_ICU_LIBS: $BOOST_ICU_LIBS"
echo "BOOST_LDFLAGS: $BOOST_ICU_LIBS"
echo "BOOST_LDFLAGS: $BOOST_LDFLAGS"
echo "Building Boost. tail -f ${BOOST_LOG} to see the details and monitor progress"
./bootstrap.sh --prefix="${BOOST_PREFIX}" "--with-icu=${ICU_PREFIX}" > "${BOOST_LOG}" 2>&1
b2cmd="./b2 link=static cxxflags=-fPIC install boost.locale.iconv=off boost.locale.posix=off -sICU_PATH=${ICU_PREFIX} -sICU_LINK=${BOOST_ICU_LIBS}"
./bootstrap.sh --prefix="${BOOST_PREFIX}" --with-icu="${ICU_PREFIX}" > "${BOOST_LOG}" 2>&1
b2cmd="./b2 --reconfigure ${PARALLEL} link=static cxxflags=-fPIC install boost.locale.iconv=off boost.locale.posix=off -sICU_PATH=\"${ICU_PREFIX}\" -sICU_LINK=\"${BOOST_ICU_LIBS}\""
background "${b2cmd}" "${BOOST_LOG}" "Waiting for boost to finish building"
if grep -q "icu[[:space:]]*:[[:space:]]*no$" "${BOOST_LOG}"; then
echo "Failed to find ICU dependencies. Exiting..."
exit 1
fi
}
function build_icu() {
ICU_LOG="$1"
mkdir -p "${ICU_PREFIX}/icu"
wget http://download.icu-project.org/files/icu4c/55.1/icu4c-55_1-src.tgz
tar -xf icu4c-55_1-src.tgz
rm -f icu4c-55_1-src.tgz
wget -c http://download.icu-project.org/files/icu4c/57.1/icu4c-57_1-src.tgz
tar -xf icu4c-57_1-src.tgz
pushd icu/source > /dev/null
echo "Building icu. tail -f $ICU_LOG to see the details and monitor progress"
./configure --prefix="${ICU_PREFIX}" --enable-draft --enable-tools \
--enable-shared --disable-extras --disable-icuio \
--disable-layout --disable-layoutex --disable-tests --disable-samples
--disable-shared --enable-static --disable-extras --disable-icuio --disable-dyload \
--disable-layout --disable-layoutex --disable-tests --disable-samples CFLAGS=-fPIC CPPFLAGS=-fPIC > "${ICU_LOG}"
if [ ! -z ${TARGET+x} ]; then
TMP_TARGET="${TARGET}"
unset TARGET
@ -355,7 +351,7 @@ function build_libevent() {
echo "Building libevent. tail -f ${LIBEVENT_LOG} to see the details and monitor progress"
./autogen.sh > "${LIBEVENT_LOG}" 2>&1
./configure --prefix="${LIBEVENT_PREFIX}" --enable-static --disable-shared --with-pic \
LDFLAGS="-L${OPENSSL_PREFIX}/lib/" \
LDFLAGS="-L${OPENSSL_PREFIX}/lib" \
CPPFLAGS="-I${OPENSSL_PREFIX}/include" >> "${LIBEVENT_LOG}" 2>&1
background "make ${PARALLEL}" "${LIBEVENT_LOG}" "Waiting for libevent to finish building"
make install >> "${LIBEVENT_LOG}"
@ -378,39 +374,22 @@ function build_dependency() {
}
function build_lbrycrd() {
if [ "$CLONE" == true ]; then
cd "${LBRYCRD_DEPENDENCIES}"
git clone https://github.com/lbryio/lbrycrd
cd lbrycrd
else
cd "${SOURCE_DIR}"
fi
cd "${SOURCE_DIR}"
./autogen.sh > "${LBRYCRD_LOG}" 2>&1
LDFLAGS="-L${OPENSSL_PREFIX}/lib/ -L${BDB_PREFIX}/lib/ -L${LIBEVENT_PREFIX}/lib/ -L${ICU_PREFIX}/lib/ -static-libstdc++"
LDFLAGS="-L${OPENSSL_PREFIX}/lib -L${BDB_PREFIX}/lib -L${LIBEVENT_PREFIX}/lib -L${ICU_PREFIX}/lib -static-libstdc++ -licui18n -licuuc -licudata -dl"
OPTIONS="--enable-cxx --enable-static --disable-shared --with-pic"
if [ "${OS_NAME}" = "osx" ]; then
OPTIONS="--enable-cxx --enable-static --disable-shared --with-pic"
CPPFLAGS="-I${OPENSSL_PREFIX}/include -I${BDB_PREFIX}/include -I${LIBEVENT_PREFIX}/include/ -I${ICU_PREFIX}/include"
CPPFLAGS="-I${OPENSSL_PREFIX}/include -I${BDB_PREFIX}/include -I${LIBEVENT_PREFIX}/include -I${ICU_PREFIX}/include"
else
OPTIONS=""
CPPFLAGS="-I${OPENSSL_PREFIX}/include -I${BDB_PREFIX}/include -I${LIBEVENT_PREFIX}/include/ -I${ICU_PREFIX}/include -Wno-unused-local-typedefs"
CPPFLAGS="-I${OPENSSL_PREFIX}/include -I${BDB_PREFIX}/include -I${LIBEVENT_PREFIX}/include -I${ICU_PREFIX}/include -Wno-unused-local-typedefs -Wno-deprecated -Wno-implicit-fallthrough"
fi
CPPFLAGS="${CPPFLAGS}" LDFLAGS="${LDFLAGS}" \
./configure --without-gui ${OPTIONS} \
--with-boost="${BOOST_PREFIX}" \
--with-icu="${ICU_PREFIX}" >> "${LBRYCRD_LOG}" 2>&1
background "make ${PARALLEL}" "${LBRYCRD_LOG}" "Waiting for lbrycrd to finish building"
if [ "${OS_NAME}" = "linux" ]; then
LD_LIBRARY_PATH="${ICU_PREFIX}/lib" src/test/test_lbrycrd
else
DYLD_LIBRARY_PATH="${ICU_PREFIX}/lib" src/test/test_lbrycrd
fi
strip src/lbrycrdd
strip src/lbrycrd-cli
strip src/lbrycrd-tx
strip src/test/test_lbrycrd
}
function clang_format_diff(){
@ -443,7 +422,7 @@ if [ "${CHECK_CODE_FORMAT}" = true ]; then
fi
set +u
export PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:${OPENSSL_PREFIX}/lib/pkgconfig/:${LIBEVENT_PREFIX}/lib/pkgconfig/"
export PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:${OPENSSL_PREFIX}/lib/pkgconfig:${LIBEVENT_PREFIX}/lib/pkgconfig:${ICU_PREFIX}/lib/pkgconfig"
set -u
if [ "${BUILD_LBRYCRD}" = true ]; then
@ -452,4 +431,12 @@ if [ "${BUILD_LBRYCRD}" = true ]; then
trap 'cat_and_exit "${LBRYCRD_LOG}"' INT TERM EXIT
build_lbrycrd
trap - INT TERM EXIT
./src/test/test_lbrycrd
set +u
if [[ ! $CXXFLAGS =~ -g ]]; then
strip src/lbrycrdd
strip src/lbrycrd-cli
strip src/lbrycrd-tx
fi
fi

View file

@ -191,6 +191,7 @@ libbitcoin_server_a_SOURCES = \
merkleblock.cpp \
miner.cpp \
claimtrie.cpp \
claimtrieForks.cpp \
net.cpp \
noui.cpp \
policy/fees.cpp \
@ -354,7 +355,7 @@ nodist_libbitcoin_util_a_SOURCES = $(srcdir)/obj/build.h
lbrycrdd_SOURCES = bitcoind.cpp
lbrycrdd_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
lbrycrdd_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
lbrycrdd_LDFLAGS = -L$(ICU_PREFIX)/lib $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
lbrycrdd_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
if TARGET_WINDOWS
lbrycrdd_SOURCES += bitcoin-cli-res.rc

View file

@ -9,7 +9,7 @@ bench_bench_bitcoin_SOURCES = \
bench/bench.h \
bench/Examples.cpp
bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/
bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $(EVENT_PTHREADS_CFLAGS) $(ICU_CPPFLAGS) $(BOOST_CPPFLAGS) -I$(builddir)/bench/
bench_bench_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
bench_bench_bitcoin_LDADD = \
$(LIBBITCOIN_SERVER) \
@ -30,8 +30,8 @@ if ENABLE_WALLET
bench_bench_bitcoin_LDADD += $(LIBBITCOIN_WALLET)
endif
bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
bench_bench_bitcoin_LDFLAGS = -L$(ICU_PREFIX)/lib $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
bench_bench_bitcoin_LDADD += $(ICU_LIBS) $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
bench_bench_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
CLEAN_BITCOIN_BENCH = bench/*.gcda bench/*.gcno

View file

@ -382,7 +382,7 @@ endif
qt_lbrycrd_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \
$(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(ICU_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
qt_lbrycrd_qt_LDFLAGS = -L$(ICU_PREFIX)/lib $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
qt_lbrycrd_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
qt_lbrycrd_qt_LIBTOOLFLAGS = --tag CXX
#locale/foo.ts -> locale/foo.qm

View file

@ -37,7 +37,7 @@ qt_test_test_lbrycrd_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBIT
$(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \
$(QR_LIBS) $(PROTOBUF_LIBS) $(ICU_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
qt_test_test_lbrycrd_qt_LDFLAGS = -L$(ICU_PREFIX)/lib $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
qt_test_test_lbrycrd_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
qt_test_test_lbrycrd_qt_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS)
CLEAN_BITCOIN_QT_TEST = $(TEST_QT_MOC_CPP) qt/test/*.gcda qt/test/*.gcno

View file

@ -100,16 +100,16 @@ BITCOIN_TESTS += \
endif
test_test_lbrycrd_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES)
test_test_lbrycrd_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS)
test_test_lbrycrd_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(ICU_CPPFLAGS) $(BOOST_CPPFLAGS) -I$(builddir)/test/ $(TESTDEFS)
test_test_lbrycrd_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \
$(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1)
$(ICU_LIBS) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1)
test_test_lbrycrd_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
if ENABLE_WALLET
test_test_lbrycrd_LDADD += $(LIBBITCOIN_WALLET)
endif
test_test_lbrycrd_LDADD += $(LIBBITCOIN_CONSENSUS) $(ICU_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS)
test_test_lbrycrd_LDFLAGS = -L$(ICU_PREFIX)/lib $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static
test_test_lbrycrd_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS)
test_test_lbrycrd_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
if ENABLE_ZMQ
test_test_lbrycrd_LDADD += $(ZMQ_LIBS)

View file

@ -305,7 +305,7 @@ public:
consensus.nExtendedClaimExpirationForkHeight = 800;
consensus.fPowAllowMinDifficultyBlocks = false;
consensus.fPowNoRetargeting = false;
consensus.nNormalizedNameForkHeight = 2000; // FIXME: pick a real fork height
consensus.nNormalizedNameForkHeight = 2000;
consensus.nRuleChangeActivationThreshold = 108; // 75% for testchains
consensus.nMinerConfirmationWindow = 144; // Faster than normal for regtest (144 instead of 2016)
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;

File diff suppressed because it is too large Load diff

View file

@ -13,11 +13,6 @@
#include <vector>
#include <map>
#include <boost/algorithm/string.hpp>
#include <boost/locale/conversion.hpp>
#include <boost/locale/localization_backend.hpp>
#include <boost/locale.hpp>
// leveldb keys
#define HASH_BLOCK 'h'
#define CURRENT_HEIGHT 't'
@ -33,34 +28,6 @@
uint256 getValueHash(COutPoint outPoint, int nHeightOfLastTakeover);
// lower-case and normalize any input string name
// see: https://unicode.org/reports/tr15/#Norm_Forms
inline std::string normalizeClaimName(const std::string& name)
{
static std::locale utf8;
static bool initialized = false;
if (!initialized) {
static boost::locale::localization_backend_manager manager =
boost::locale::localization_backend_manager::global();
manager.select("icu");
static boost::locale::generator curLocale(manager);
utf8 = curLocale("en_US.UTF8");
initialized = true;
}
std::string normalized = boost::locale::normalize(name, boost::locale::norm_nfd, utf8);
// Non-locale aware lowercase
boost::algorithm::to_lower(normalized);
// Locale aware lowercase
/* normalized = boost::locale::to_lower(normalized, utf8); */
LogPrintf("%s: Normalized \"%s\" (%lu, %lu) to \"%s\" (%lu, %lu)\n", __func__, name, name.size(), sizeof(name), normalized, normalized.size(), sizeof(normalized));
// code points can be lost if we're not careful to make sure the string isn't shrinking here
return (normalized.size() >= name.size()) ? normalized : name;
}
class CClaimValue
{
public:
@ -191,63 +158,6 @@ public:
READWRITE(nHeightOfLastTakeover);
}
CClaimTrieNode& cloneState(const CClaimTrieNode& other)
{
hash = other.hash;
nHeightOfLastTakeover = other.nHeightOfLastTakeover;
if (!claims.empty()) {
claims.reserve(other.claims.size());
std::copy(other.claims.begin(), other.claims.end(), claims.begin());
}
std::string sPos;
for (nodeMapType::const_iterator it = other.children.begin(); it != other.children.end(); ++it) {
std::stringstream ss;
ss << it->first;
sPos = ss.str();
CClaimTrieNode* newNode = new CClaimTrieNode();
newNode->cloneState(*it->second);
if (!it->second->claims.empty()) {
newNode->claims.reserve(it->second->claims.size());
for (std::vector<CClaimValue>::const_iterator cit = it->second->claims.begin(); cit != it->second->claims.end(); ++cit)
newNode->claims.push_back(*cit);
}
children[sPos[sPos.size() - 1]] = newNode;
}
return *this;
}
// NOTE: While normalization is hardcoded into this method, it's
// *only* used while enabling the normalization fork in order to
// flatten the namespace.
CClaimTrieNode& normalizeClone(const CClaimTrieNode& other)
{
hash = uint256S("0000000000000000000000000000000000000000000000000000000000000001");
nHeightOfLastTakeover = other.nHeightOfLastTakeover;
if (!claims.empty()) {
claims.reserve(other.claims.size());
std::copy(other.claims.begin(), other.claims.end(), claims.begin());
}
std::string sPos;
for (nodeMapType::const_iterator it = other.children.begin(); it != other.children.end(); ++it) {
std::stringstream ss;
ss << it->first;
sPos = normalizeClaimName(ss.str());
CClaimTrieNode* newNode = new CClaimTrieNode();
newNode->normalizeClone(*it->second);
if (!it->second->claims.empty()) {
newNode->claims.reserve(it->second->claims.size());
for (std::vector<CClaimValue>::const_iterator cit = it->second->claims.begin(); cit != it->second->claims.end(); ++cit)
newNode->claims.push_back(*cit);
}
children[sPos[sPos.size() - 1]] = newNode;
}
return *this;
}
bool operator==(const CClaimTrieNode& other) const
{
return hash == other.hash && claims == other.claims;
@ -375,33 +285,34 @@ typedef std::vector<CClaimIndexElement> claimIndexElementListType;
struct claimsForNameType
{
std::vector<CClaimValue> claims;
std::vector<CSupportValue> supports;
int nLastTakeoverHeight;
const std::vector<CClaimValue> claims;
const std::vector<CSupportValue> supports;
const int nLastTakeoverHeight;
const std::string name;
claimsForNameType(std::vector<CClaimValue> claims, std::vector<CSupportValue> supports, int nLastTakeoverHeight)
: claims(claims), supports(supports), nLastTakeoverHeight(nLastTakeoverHeight) {}
claimsForNameType(std::vector<CClaimValue> claims, std::vector<CSupportValue> supports,
int nLastTakeoverHeight, const std::string& name)
: claims(claims), supports(supports), nLastTakeoverHeight(nLastTakeoverHeight), name(name) {}
};
class CClaimTrieCache;
class CClaimTrieCacheBase;
class CClaimTrieCacheExpirationFork;
class CClaimTrie
{
public:
CClaimTrie(bool fMemory = false, bool fWipe = false, bool fNormalize = false, int nProportionalDelayFactor = 32)
: db(GetDataDir() / "claimtrie", 100, fMemory, fWipe, false), nCurrentHeight(0), nExpirationTime(Params().GetConsensus().nOriginalClaimExpirationTime), nProportionalDelayFactor(nProportionalDelayFactor), root(uint256S("0000000000000000000000000000000000000000000000000000000000000001")), fNormalize(fNormalize)
CClaimTrie(bool fMemory = false, bool fWipe = false, int nProportionalDelayFactor = 32)
: db(GetDataDir() / "claimtrie", 100, fMemory, fWipe, false), nCurrentHeight(0),
nExpirationTime(Params().GetConsensus().nOriginalClaimExpirationTime),
nProportionalDelayFactor(nProportionalDelayFactor),
root(uint256S("0000000000000000000000000000000000000000000000000000000000000001"))
{}
// Does not change the current trie, but returns a normalized equivalent trie
CClaimTrie* enableNormalizationFork(bool enable, int nHeight, CClaimTrieCache& trieCache);
uint256 getMerkleHash();
bool empty() const;
void clear();
bool shouldNormalize();
bool checkConsistency() const;
bool WriteToDisk();
@ -410,16 +321,12 @@ public:
bool getInfoForName(const std::string& name, CClaimValue& claim) const;
bool getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const;
claimsForNameType getClaimsForName(const std::string& name) const;
CAmount getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector<CSupportValue>* supports = NULL) const;
CAmount getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector<CSupportValue>* supports = NULL) const;
std::vector<CClaimValue> getClaimsForName(const std::string& name) const;
bool queueEmpty() const;
bool supportEmpty() const;
bool supportQueueEmpty() const;
bool expirationQueueEmpty() const;
bool supportExpirationQueueEmpty() const;
void setExpirationTime(int t);
@ -427,14 +334,6 @@ public:
void removeFromClaimIndex(const CClaimValue& claim);
bool getClaimById(const uint160 claimId, std::string& name, CClaimValue& claim) const;
bool getQueueRow(int nHeight, claimQueueRowType& row) const;
bool getQueueNameRow(const std::string& name, queueNameRowType& row) const;
bool getExpirationQueueRow(int nHeight, expirationQueueRowType& row) const;
bool getSupportNode(std::string name, supportMapEntryType& node) const;
bool getSupportQueueRow(int nHeight, supportQueueRowType& row) const;
bool getSupportQueueNameRow(const std::string& name, queueNameRowType& row) const;
bool getSupportExpirationQueueRow(int nHeight, expirationQueueRowType& row) const;
bool haveClaim(const std::string& name, const COutPoint& outPoint) const;
bool haveClaimInQueue(const std::string& name, const COutPoint& outPoint,
@ -448,7 +347,8 @@ public:
unsigned int getTotalClaimsInTrie() const;
CAmount getTotalValueOfClaimsInTrie(bool fControllingOnly) const;
friend class CClaimTrieCache;
friend class CClaimTrieCacheBase;
friend class CClaimTrieCacheExpirationFork;
CDBWrapper db;
int nCurrentHeight;
@ -470,7 +370,6 @@ private:
expirationQueueType& supportExpirationQueueCache);
bool updateName(const std::string& name, CClaimTrieNode* updatedNode);
bool updateHash(const std::string& name, uint256& hash);
bool updateHashNormalized(const std::string& name, uint256& hash);
bool updateTakeoverHeight(const std::string& name, int nTakeoverHeight);
bool recursiveNullify(CClaimTrieNode* node, const std::string& name);
@ -483,6 +382,14 @@ private:
CAmount getTotalValueOfClaimsRecursive(const CClaimTrieNode* current,
bool fControllingOnly) const;
bool getQueueRow(int nHeight, claimQueueRowType& row) const;
bool getQueueNameRow(const std::string& name, queueNameRowType& row) const;
bool getExpirationQueueRow(int nHeight, expirationQueueRowType& row) const;
bool getSupportNode(std::string name, supportMapEntryType& node) const;
bool getSupportQueueRow(int nHeight, supportQueueRowType& row) const;
bool getSupportQueueNameRow(const std::string& name, queueNameRowType& row) const;
bool getSupportExpirationQueueRow(int nHeight, expirationQueueRowType& row) const;
void markNodeDirty(const std::string& name, CClaimTrieNode* node);
void updateQueueRow(int nHeight, claimQueueRowType& row);
void updateQueueNameRow(const std::string& name,
@ -496,8 +403,6 @@ private:
void BatchWriteNode(CDBBatch& batch, const std::string& name,
const CClaimTrieNode* pNode) const;
void BatchEraseNode(CDBBatch& batch, const std::string& nome) const;
void BatchWriteClaimIndex(CDBBatch& batch) const;
void BatchWriteQueueRows(CDBBatch& batch);
void BatchWriteQueueNameRows(CDBBatch& batch);
void BatchWriteExpirationQueueRows(CDBBatch& batch);
@ -507,9 +412,6 @@ private:
void BatchWriteSupportExpirationQueueRows(CDBBatch& batch);
template<typename K> bool keyTypeEmpty(char key, K& dummy) const;
void cloneState(const CClaimTrie&);
void copyAndNormalizeQueues(const CClaimTrie&);
CClaimTrieNode root;
uint256 hashBlock;
@ -523,8 +425,6 @@ private:
nodeCacheType dirtyNodes;
supportMapType dirtySupportNodes;
bool fNormalize;
};
class CClaimTrieProofNode
@ -572,10 +472,10 @@ struct CNodeCallback {
virtual void visit(const std::string& name, const CClaimTrieNode* node) = 0;
};
class CClaimTrieCache
class CClaimTrieCacheBase
{
public:
CClaimTrieCache(CClaimTrie* base, bool fRequireTakeoverHeights = true)
CClaimTrieCacheBase(CClaimTrie* base, bool fRequireTakeoverHeights = true)
: base(base),
fRequireTakeoverHeights(fRequireTakeoverHeights)
{
@ -597,8 +497,8 @@ public:
bool addClaim(const std::string& name, const COutPoint& outPoint,
uint160 claimId, CAmount nAmount, int nHeight) const;
bool undoAddClaim(const std::string& name, const COutPoint& outPoint) const;
bool spendClaim(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const;
bool undoAddClaim(const std::string& name, const COutPoint& outPoint, int nHeight) const;
bool spendClaim(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight) const;
bool undoSpendClaim(const std::string& name, const COutPoint& outPoint,
uint160 claimId, CAmount nAmount, int nHeight,
int nValidAtHeight) const;
@ -617,38 +517,27 @@ public:
uint256 getBestBlock();
void setBestBlock(const uint256& hashBlock);
bool incrementBlock(insertUndoType& insertUndo,
virtual bool incrementBlock(insertUndoType& insertUndo,
claimQueueRowType& expireUndo,
insertUndoType& insertSupportUndo,
supportQueueRowType& expireSupportUndo,
std::vector<std::pair<std::string, int> >& takeoverHeightUndo) const;
bool decrementBlock(insertUndoType& insertUndo,
std::vector<std::pair<std::string, int> >& takeoverHeightUndo);
virtual bool decrementBlock(insertUndoType& insertUndo,
claimQueueRowType& expireUndo,
insertUndoType& insertSupportUndo,
supportQueueRowType& expireSupportUndo,
std::vector<std::pair<std::string, int> >& takeoverHeightUndo) const;
std::vector<std::pair<std::string, int> >& takeoverHeightUndo);
~CClaimTrieCache() { clear(); }
~CClaimTrieCacheBase() { clear(); }
bool insertClaimIntoTrie(const std::string& name, CClaimValue claim,
bool fCheckTakeover = false) const;
bool removeClaimFromTrie(const std::string& name, const COutPoint& outPoint,
CClaimValue& claim,
bool fCheckTakeover = false) const;
bool getProofForName(const std::string& name, CClaimTrieProof& proof) const;
bool getInfoForName(const std::string& name, CClaimValue& claim) const;
virtual bool getProofForName(const std::string& name, CClaimTrieProof& proof) const;
virtual bool getInfoForName(const std::string& name, CClaimValue& claim) const;
bool finalizeDecrement() const;
void removeAndAddSupportToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const;
void removeAndAddToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const;
bool forkForExpirationChange(bool increment) const;
bool iterateTrie(CNodeCallback& callback) const;
claimsForNameType getClaimsForName(const std::string& name) const;
virtual claimsForNameType getClaimsForName(const std::string& name) const;
CAmount getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector<CSupportValue>* supports = NULL) const;
CAmount getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector<CSupportValue>* supports = NULL) const;
@ -660,11 +549,48 @@ protected:
const std::string& sPos,
bool forceCompute = false) const;
bool recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, const std::string& sName, bool* pfNullified = NULL) const;
void checkNamesForTakeover(insertUndoType& insertUndo, insertUndoType& insertSupportUndo,
std::vector<std::pair<std::string, int> >& takeoverHeightUndo) const;
virtual bool insertClaimIntoTrie(const std::string& name, CClaimValue claim,
bool fCheckTakeover = false) const;
virtual bool removeClaimFromTrie(const std::string& name, const COutPoint& outPoint,
CClaimValue& claim,
bool fCheckTakeover = false) const;
virtual bool insertSupportIntoMap(const std::string& name,
CSupportValue support,
bool fCheckTakeover) const;
virtual bool removeSupportFromMap(const std::string& name, const COutPoint& outPoint,
CSupportValue& support,
bool fCheckTakeover) const;
virtual void addClaimToQueues(const std::string& name, CClaimValue& claim) const;
virtual bool addSupportToQueues(const std::string& name, CSupportValue& support) const;
virtual std::string adjustNameForValidHeight(const std::string& name, int validHeight) const;
void addToExpirationQueue(int nExpirationHeight, nameOutPointType& entry) const;
void removeFromExpirationQueue(const std::string& name, const COutPoint& outPoint,
int nHeight) const;
void addSupportToExpirationQueue(int nExpirationHeight,
nameOutPointType& entry) const;
void removeSupportFromExpirationQueue(const std::string& name,
const COutPoint& outPoint,
int nHeight) const;
bool getSupportsForName(const std::string& name,
supportMapEntryType& supports) const;
virtual int getDelayForName(const std::string& name, const uint160& claimId) const;
mutable nodeCacheType cache;
private:
CClaimTrie* base;
mutable int nCurrentHeight; // Height of the block that is being worked on, which is
// one greater than the height of the chain's tip
private:
bool fRequireTakeoverHeights;
@ -680,26 +606,19 @@ private:
mutable expirationQueueType supportExpirationQueueCache;
mutable std::set<std::string> namesToCheckForTakeover;
mutable std::map<std::string, int> cacheTakeoverHeights;
mutable int nCurrentHeight; // Height of the block that is being worked on, which is
// one greater than the height of the chain's tip
mutable claimIndexElementListType claimsToAdd;
mutable claimIndexClaimListType claimsToDelete;
uint256 hashBlock;
uint256 computeHash() const;
bool reorderTrieNode(const std::string& name, bool fCheckTakeover) const;
bool clear() const;
bool removeClaim(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight, bool fCheckTakeover) const;
bool addClaimToQueues(const std::string& name, CClaimValue& claim) const;
// generally the opposite of addClaimToQueues, but they aren't perfectly symmetrical:
bool removeClaim(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight, bool fCheckTakeover) const;
bool removeClaimFromQueue(const std::string& name, const COutPoint& outPoint,
CClaimValue& claim) const;
void addToExpirationQueue(int nExpirationHeight, nameOutPointType& entry) const;
void removeFromExpirationQueue(const std::string& name, const COutPoint& outPoint,
int nHeight) const;
claimQueueType::iterator getQueueCacheRow(int nHeight,
bool createIfNotExists) const;
@ -711,13 +630,6 @@ private:
bool removeSupport(const std::string& name, const COutPoint& outPoint,
int nHeight, int& nValidAtHeight,
bool fCheckTakeover) const;
bool removeSupportFromMap(const std::string& name, const COutPoint& outPoint,
CSupportValue& support,
bool fCheckTakeover) const;
bool insertSupportIntoMap(const std::string& name,
CSupportValue support,
bool fCheckTakeover) const;
supportQueueType::iterator getSupportQueueCacheRow(int nHeight,
bool createIfNotExists) const;
@ -726,25 +638,14 @@ private:
expirationQueueType::iterator getSupportExpirationQueueCacheRow(int nHeight,
bool createIfNotExists) const;
bool addSupportToQueues(const std::string& name, CSupportValue& support) const;
bool removeSupportFromQueue(const std::string& name, const COutPoint& outPoint,
CSupportValue& support) const;
void addSupportToExpirationQueue(int nExpirationHeight,
nameOutPointType& entry) const;
void removeSupportFromExpirationQueue(const std::string& name,
const COutPoint& outPoint,
int nHeight) const;
bool getSupportsForName(const std::string& name,
supportMapEntryType& node) const;
bool getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const;
int getDelayForName(const std::string& name) const;
uint256 getLeafHashForProof(const std::string& currentPosition, unsigned char nodeChar,
const CClaimTrieNode* currentNode) const;
uint256 getLeafHashForProof(const std::string& currentPosition, const CClaimTrieNode* currentNode) const;
bool getOriginalInfoForName(const std::string& name, CClaimValue& claim) const;
@ -755,4 +656,70 @@ private:
const CClaimTrieNode* getNodeForName(const std::string& name) const;
};
class CClaimTrieCacheExpirationFork: public CClaimTrieCacheBase {
public:
CClaimTrieCacheExpirationFork(CClaimTrie* base, bool fRequireTakeoverHeights = true)
: CClaimTrieCacheBase(base, fRequireTakeoverHeights) {}
bool forkForExpirationChange(bool increment) const;
// TODO: move the expiration fork code from main.cpp to overrides of increment/decrement block
private:
void removeAndAddSupportToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const;
void removeAndAddToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const;
};
class CClaimTrieCacheNormalizationFork: public CClaimTrieCacheExpirationFork {
public:
CClaimTrieCacheNormalizationFork(CClaimTrie* base, bool fRequireTakeoverHeights = true)
: CClaimTrieCacheExpirationFork(base, fRequireTakeoverHeights),
overrideInsertNormalization(false), overrideRemoveNormalization(false) {}
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
virtual bool incrementBlock(insertUndoType& insertUndo,
claimQueueRowType& expireUndo,
insertUndoType& insertSupportUndo,
supportQueueRowType& expireSupportUndo,
std::vector<std::pair<std::string, int> >& takeoverHeightUndo);
virtual bool decrementBlock(insertUndoType& insertUndo,
claimQueueRowType& expireUndo,
insertUndoType& insertSupportUndo,
supportQueueRowType& expireSupportUndo,
std::vector<std::pair<std::string, int> >& takeoverHeightUndo);
virtual bool getProofForName(const std::string& name, CClaimTrieProof& proof) const;
virtual bool getInfoForName(const std::string& name, CClaimValue& claim) const;
virtual claimsForNameType getClaimsForName(const std::string& name) const;
protected:
virtual bool insertClaimIntoTrie(const std::string& name, CClaimValue claim, bool fCheckTakeover = false) const;
virtual bool removeClaimFromTrie(const std::string& name, const COutPoint& outPoint,
CClaimValue& claim, bool fCheckTakeover = false) const;
virtual bool insertSupportIntoMap(const std::string& name, CSupportValue support, bool fCheckTakeover) const;
virtual bool removeSupportFromMap(const std::string& name, const COutPoint& outPoint,
CSupportValue& support, bool fCheckTakeover) const;
virtual int getDelayForName(const std::string& name, const uint160& claimId) const;
virtual void addClaimToQueues(const std::string& name, CClaimValue& claim) const;
virtual bool addSupportToQueues(const std::string& name, CSupportValue& support) const;
virtual std::string adjustNameForValidHeight(const std::string& name, int validHeight) const;
private:
bool overrideInsertNormalization, overrideRemoveNormalization;
bool normalizeAllNamesInTrieIfNecessary(insertUndoType& insertUndo, claimQueueRowType& removeUndo,
insertUndoType& insertSupportUndo, supportQueueRowType& expireSupportUndo,
std::vector<std::pair<std::string, int> >& takeoverHeightUndo) const;
};
typedef CClaimTrieCacheNormalizationFork CClaimTrieCache;
#endif // BITCOIN_CLAIMTRIE_H

300
src/claimtrieForks.cpp Normal file
View file

@ -0,0 +1,300 @@
#include "claimtrie.h"
#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include <boost/locale/conversion.hpp>
#include <boost/locale/localization_backend.hpp>
#include <boost/locale.hpp>
#include <boost/scope_exit.hpp>
void CClaimTrieCacheExpirationFork::removeAndAddToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const
{
for (expirationQueueRowType::iterator e = row.begin(); e != row.end(); ++e)
{
// remove and insert with new expiration time
removeFromExpirationQueue(e->name, e->outPoint, height);
int extend_expiration = Params().GetConsensus().nExtendedClaimExpirationTime - Params().GetConsensus().nOriginalClaimExpirationTime;
int new_expiration_height = increment ? height + extend_expiration : height - extend_expiration;
nameOutPointType entry(e->name, e->outPoint);
addToExpirationQueue(new_expiration_height, entry);
}
}
void CClaimTrieCacheExpirationFork::removeAndAddSupportToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const
{
for (expirationQueueRowType::iterator e = row.begin(); e != row.end(); ++e)
{
// remove and insert with new expiration time
removeSupportFromExpirationQueue(e->name, e->outPoint, height);
int extend_expiration = Params().GetConsensus().nExtendedClaimExpirationTime - Params().GetConsensus().nOriginalClaimExpirationTime;
int new_expiration_height = increment ? height + extend_expiration : height - extend_expiration;
nameOutPointType entry(e->name, e->outPoint);
addSupportToExpirationQueue(new_expiration_height, entry);
}
}
bool CClaimTrieCacheExpirationFork::forkForExpirationChange(bool increment) const
{
/*
If increment is True, we have forked to extend the expiration time, thus items in the expiration queue
will have their expiration extended by "new expiration time - original expiration time"
If increment is False, we are decremented a block to reverse the fork. Thus items in the expiration queue
will have their expiration extension removed.
*/
// look through dirty expiration queues
std::set<int> dirtyHeights;
for (expirationQueueType::const_iterator i = base->dirtyExpirationQueueRows.begin(); i != base->dirtyExpirationQueueRows.end(); ++i)
{
int height = i->first;
dirtyHeights.insert(height);
expirationQueueRowType row = i->second;
removeAndAddToExpirationQueue(row, height, increment);
}
std::set<int> dirtySupportHeights;
for (expirationQueueType::const_iterator i = base->dirtySupportExpirationQueueRows.begin(); i != base->dirtySupportExpirationQueueRows.end(); ++i)
{
int height = i->first;
dirtySupportHeights.insert(height);
expirationQueueRowType row = i->second;
removeAndAddSupportToExpirationQueue(row, height, increment);
}
//look through db for expiration queues, if we haven't already found it in dirty expiration queue
boost::scoped_ptr<CDBIterator> pcursor(const_cast<CDBWrapper*>(&base->db)->NewIterator());
pcursor->SeekToFirst();
while (pcursor->Valid())
{
std::pair<char, int> key;
if (pcursor->GetKey(key))
{
int height = key.second;
// if we've looked through this in dirtyExprirationQueueRows, don't use it
// because its stale
if ((key.first == EXP_QUEUE_ROW) & (dirtyHeights.count(height) == 0))
{
expirationQueueRowType row;
if (pcursor->GetValue(row))
{
removeAndAddToExpirationQueue(row, height, increment);
}
else
{
return error("%s(): error reading expiration queue rows from disk", __func__);
}
}
else if ((key.first == SUPPORT_EXP_QUEUE_ROW) & (dirtySupportHeights.count(height) == 0))
{
expirationQueueRowType row;
if (pcursor->GetValue(row))
{
removeAndAddSupportToExpirationQueue(row, height, increment);
}
else
{
return error("%s(): error reading support expiration queue rows from disk", __func__);
}
}
}
pcursor->Next();
}
return true;
}
bool CClaimTrieCacheNormalizationFork::shouldNormalize() const {
return nCurrentHeight > Params().GetConsensus().nNormalizedNameForkHeight;
}
std::string CClaimTrieCacheNormalizationFork::normalizeClaimName(const std::string& name, bool force) const {
if (!force && !shouldNormalize())
return name;
static std::locale utf8;
static bool initialized = false;
if (!initialized) {
static boost::locale::localization_backend_manager manager =
boost::locale::localization_backend_manager::global();
manager.select("icu");
static boost::locale::generator curLocale(manager);
utf8 = curLocale("en_US.UTF8");
initialized = true;
}
std::string normalized;
try {
// Check if it is a valid utf-8 string. If not, it will throw a
// boost::locale::conv::conversion_error exception which we catch later
normalized = boost::locale::conv::to_utf<char>(name, "UTF-8", boost::locale::conv::stop);
if (normalized.empty())
return name;
normalized = boost::locale::normalize(normalized, boost::locale::norm_nfd, utf8);
// Locale aware lowercase (the non-locale-aware version seemed to struggle with some international chars):
normalized = boost::locale::to_lower(normalized, utf8);
}
catch (const boost::locale::conv::conversion_error& e){
return name;
}
catch (const std::bad_cast& e) {
LogPrintf("%s() is invalid or dependencies are missing: %s\n", __func__, e.what());
throw;
}
catch (const std::exception& e) { // TODO: change to use ... with current_exception() in c++11
LogPrintf("%s() had an unexpected exception: %s\n", __func__, e.what());
return name;
}
return normalized;
}
bool CClaimTrieCacheNormalizationFork::insertClaimIntoTrie(const std::string& name, CClaimValue claim,
bool fCheckTakeover) const {
return CClaimTrieCacheExpirationFork::insertClaimIntoTrie(normalizeClaimName(name, overrideInsertNormalization), claim, fCheckTakeover);
}
bool CClaimTrieCacheNormalizationFork::removeClaimFromTrie(const std::string& name, const COutPoint& outPoint,
CClaimValue& claim, bool fCheckTakeover) const {
return CClaimTrieCacheExpirationFork::removeClaimFromTrie(normalizeClaimName(name, overrideRemoveNormalization), outPoint, claim, fCheckTakeover);
}
bool CClaimTrieCacheNormalizationFork::insertSupportIntoMap(const std::string& name, CSupportValue support,
bool fCheckTakeover) const {
return CClaimTrieCacheExpirationFork::insertSupportIntoMap(normalizeClaimName(name, overrideInsertNormalization), support, fCheckTakeover);
}
bool CClaimTrieCacheNormalizationFork::removeSupportFromMap(const std::string& name, const COutPoint& outPoint,
CSupportValue& support, bool fCheckTakeover) const {
return CClaimTrieCacheExpirationFork::removeSupportFromMap(normalizeClaimName(name, overrideRemoveNormalization), outPoint, support, fCheckTakeover);
}
struct claimsForNormalization: public claimsForNameType {
const std::string normalized;
claimsForNormalization(std::vector<CClaimValue> claims, std::vector<CSupportValue> supports,
int nLastTakeoverHeight, const std::string& name, const std::string& normalized)
: claimsForNameType(claims, supports, nLastTakeoverHeight, name), normalized(normalized) {}
};
bool CClaimTrieCacheNormalizationFork::normalizeAllNamesInTrieIfNecessary(insertUndoType& insertUndo, claimQueueRowType& removeUndo,
insertUndoType& insertSupportUndo, supportQueueRowType& expireSupportUndo,
std::vector<std::pair<std::string, int> >& takeoverHeightUndo) const {
struct CNameChangeDetector: public CNodeCallback {
std::vector<claimsForNormalization> hits;
const CClaimTrieCacheNormalizationFork* owner;
CNameChangeDetector(const CClaimTrieCacheNormalizationFork* owner): owner(owner) {}
void visit(const std::string& name, const CClaimTrieNode* node) {
if (node->claims.empty()) return;
const std::string normalized = owner->normalizeClaimName(name, true);
if (normalized == name) return;
supportMapEntryType supports;
owner->getSupportsForName(name, supports);
hits.push_back(claimsForNormalization(node->claims, supports, node->nHeightOfLastTakeover, name, normalized));
}
};
if (nCurrentHeight == Params().GetConsensus().nNormalizedNameForkHeight) {
// run the one-time upgrade of all names that need to change
// it modifies the (cache) trie as it goes, so we need to grab everything to be modified first
CNameChangeDetector detector(this);
iterateTrie(detector);
for (std::vector<claimsForNormalization>::iterator it = detector.hits.begin(); it != detector.hits.end(); ++it) {
BOOST_FOREACH(CSupportValue support, it->supports) {
// if it's already going to expire just skip it
if (support.nHeight + base->nExpirationTime <= nCurrentHeight)
continue;
bool success = removeSupportFromMap(it->name, support.outPoint, support, false);
assert(success);
expireSupportUndo.push_back(std::make_pair(it->name, support));
success = insertSupportIntoMap(it->normalized, support, false);
assert(success);
insertSupportUndo.push_back(nameOutPointHeightType(it->name, support.outPoint, -1));
}
BOOST_FOREACH(CClaimValue claim, it->claims) {
if (claim.nHeight + base->nExpirationTime <= nCurrentHeight)
continue;
bool success = removeClaimFromTrie(it->name, claim.outPoint, claim, false);
assert(success);
removeUndo.push_back(std::make_pair(it->name, claim));
success = insertClaimIntoTrie(it->normalized, claim, true);
assert(success);
insertUndo.push_back(nameOutPointHeightType(it->name, claim.outPoint, -1));
}
takeoverHeightUndo.push_back(std::make_pair(it->name, it->nLastTakeoverHeight));
}
return true;
}
return false;
}
bool CClaimTrieCacheNormalizationFork::incrementBlock(insertUndoType& insertUndo,
claimQueueRowType& expireUndo,
insertUndoType& insertSupportUndo,
supportQueueRowType& expireSupportUndo,
std::vector<std::pair<std::string, int> >& takeoverHeightUndo) {
overrideInsertNormalization = normalizeAllNamesInTrieIfNecessary(insertUndo, expireUndo, insertSupportUndo,
expireSupportUndo, takeoverHeightUndo);
BOOST_SCOPE_EXIT(&overrideInsertNormalization) { overrideInsertNormalization = false; } BOOST_SCOPE_EXIT_END
return CClaimTrieCacheExpirationFork::incrementBlock(insertUndo, expireUndo, insertSupportUndo,
expireSupportUndo, takeoverHeightUndo);
}
bool CClaimTrieCacheNormalizationFork::decrementBlock(insertUndoType& insertUndo,
claimQueueRowType& expireUndo,
insertUndoType& insertSupportUndo,
supportQueueRowType& expireSupportUndo,
std::vector<std::pair<std::string, int> >& takeoverHeightUndo) {
overrideRemoveNormalization = shouldNormalize();
BOOST_SCOPE_EXIT(&overrideRemoveNormalization) { overrideRemoveNormalization = false; } BOOST_SCOPE_EXIT_END
return CClaimTrieCacheExpirationFork::decrementBlock(insertUndo, expireUndo, insertSupportUndo,
expireSupportUndo, takeoverHeightUndo);
}
bool CClaimTrieCacheNormalizationFork::getProofForName(const std::string& name, CClaimTrieProof& proof) const {
return CClaimTrieCacheExpirationFork::getProofForName(normalizeClaimName(name), proof);
}
bool CClaimTrieCacheNormalizationFork::getInfoForName(const std::string& name, CClaimValue& claim) const {
return CClaimTrieCacheExpirationFork::getInfoForName(normalizeClaimName(name), claim);
}
claimsForNameType CClaimTrieCacheNormalizationFork::getClaimsForName(const std::string& name) const {
return CClaimTrieCacheExpirationFork::getClaimsForName(normalizeClaimName(name));
}
int CClaimTrieCacheNormalizationFork::getDelayForName(const std::string& name, const uint160& claimId) const {
return CClaimTrieCacheExpirationFork::getDelayForName(normalizeClaimName(name), claimId);
}
void CClaimTrieCacheNormalizationFork::addClaimToQueues(const std::string& name, CClaimValue& claim) const {
return CClaimTrieCacheExpirationFork::addClaimToQueues(normalizeClaimName(name,
claim.nValidAtHeight > Params().GetConsensus().nNormalizedNameForkHeight), claim);
}
bool CClaimTrieCacheNormalizationFork::addSupportToQueues(const std::string& name, CSupportValue& support) const {
return CClaimTrieCacheExpirationFork::addSupportToQueues(normalizeClaimName(name,
support.nValidAtHeight > Params().GetConsensus().nNormalizedNameForkHeight), support);
}
std::string CClaimTrieCacheNormalizationFork::adjustNameForValidHeight(const std::string& name, int validHeight) const {
return normalizeClaimName(name, validHeight > Params().GetConsensus().nNormalizedNameForkHeight);
}

View file

@ -1425,27 +1425,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
RandAddSeedPerfmon();
pclaimTrie->setExpirationTime(consensusParams.GetExpirationTime(chainActive.Height()));
// Possible enhancement TODO: Instead of forcing a re-init, store
// fork status on disk and just load at start-up (on initial
// load).
if ((chainActive.Height() >= (Params().GetConsensus().nNormalizedNameForkHeight - 1)) &&
!pclaimTrie->shouldNormalize()) {
LogPrintf("Reloading ClaimTrie with normalization enabled\n");
delete pclaimTrie;
pclaimTrie = new CClaimTrie(false, fReindex, true);
assert(pclaimTrie->shouldNormalize());
if (!pclaimTrie->ReadFromDisk(true)) {
LogPrintf("Error re-loading the claim trie from disk");
return false;
}
LogPrintf("Finished reloading ClaimTrie with normalization enabled\n");
}
//// debug print
LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size());
LogPrintf("nBestHeight = %d\n", chainActive.Height());
LogPrintf("nBestHeight = %d\n", chainActive.Height());
#ifdef ENABLE_WALLET
LogPrintf("setKeyPool.size() = %u\n", pwalletMain ? pwalletMain->setKeyPool.size() : 0);
LogPrintf("mapWallet.size() = %u\n", pwalletMain ? pwalletMain->mapWallet.size() : 0);

View file

@ -2067,7 +2067,6 @@ static bool ApplyTxInUndo(const CTxInUndo& undo, CCoinsViewCache& view, CClaimTr
std::vector<std::vector<unsigned char> > vvchParams;
if (undo.fIsClaim && DecodeClaimScript(undo.txout.scriptPubKey, op, vvchParams))
{
const bool shouldNormalize = pclaimTrie->shouldNormalize();
if (op == OP_CLAIM_NAME || op == OP_UPDATE_CLAIM)
{
uint160 claimId;
@ -2086,7 +2085,7 @@ static bool ApplyTxInUndo(const CTxInUndo& undo, CCoinsViewCache& view, CClaimTr
if (nValidHeight > 0 && nValidHeight >= coins->nHeight)
{
LogPrintf("%s: (txid: %s, nOut: %d) Restoring %s to the claim trie due to a block being disconnected (normalize claim active: %s)\n",
__func__, out.hash.ToString(), out.n, name.c_str(), (shouldNormalize ? "true" : "false"));
__func__, out.hash.ToString(), out.n, name.c_str(), (trieCache.shouldNormalize() ? "true" : "false"));
if (!trieCache.undoSpendClaim(name, COutPoint(out.hash, out.n), claimId, undo.txout.nValue, coins->nHeight, nValidHeight))
LogPrintf("%s: Something went wrong inserting the claim\n", __func__);
}
@ -2141,13 +2140,6 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI
assert(trieCache.decrementBlock(blockUndo.insertUndo, blockUndo.expireUndo, blockUndo.insertSupportUndo, blockUndo.expireSupportUndo, blockUndo.takeoverHeightUndo));
if (pindex->nHeight == Params().GetConsensus().nNormalizedNameForkHeight) {
LogPrintf("Decremented past the normalization hard fork height\n");
const uint256 prevHash = trieCache.getBestBlock();
pclaimTrie = pclaimTrie->enableNormalizationFork(false, pindex->nHeight, trieCache);
trieCache.setBestBlock(prevHash);
}
// undo transactions in reverse order
for (int i = block.vtx.size() - 1; i >= 0; i--) {
const CTransaction &tx = block.vtx[i];
@ -2177,7 +2169,6 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI
std::vector<std::vector<unsigned char> > vvchParams;
if (DecodeClaimScript(txout.scriptPubKey, op, vvchParams))
{
bool shouldNormalize = pclaimTrie->shouldNormalize();
if (op == OP_CLAIM_NAME || op == OP_UPDATE_CLAIM)
{
uint160 claimId;
@ -2203,7 +2194,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI
}
std::string name(vvchParams[0].begin(), vvchParams[0].end());
LogPrintf("%s: (txid: %s, nOut: %d) Trying to remove %s from the claim trie due to its block being disconnected\n", __func__, hash.ToString(), i, name.c_str());
if (!trieCache.undoAddClaim(name, COutPoint(hash, i))) {
if (!trieCache.undoAddClaim(name, COutPoint(hash, i), pindex->nHeight)) {
LogPrintf("%s: Could not find the claim in the trie or the cache\n", __func__);
}
}
@ -2215,7 +2206,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI
LogPrintf("--- %s[%lu]: OP_SUPPORT_CLAIM \"%s\" with claimId %s and tx prevout %s at index %d\n",
__func__, pindex->nHeight, name, supportedClaimId.GetHex(), hash.ToString(), i);
LogPrintf("%s: (txid: %s, nOut: %d) Removing support for claim id %s on %s due to its block being disconnected (normalize fork active: %s)\n",
__func__, hash.ToString(), i, supportedClaimId.ToString(), name.c_str(), (shouldNormalize ? "true" : "false"));
__func__, hash.ToString(), i, supportedClaimId.ToString(), name.c_str(), (trieCache.shouldNormalize() ? "true" : "false"));
if (!trieCache.undoAddSupport(name, COutPoint(hash, i), pindex->nHeight))
LogPrintf("%s: Something went wrong removing support for name %s in hash %s\n", __func__, name.c_str(), hash.ToString());
}
@ -2612,13 +2603,12 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
std::vector<std::vector<unsigned char> > vvchParams;
if (DecodeClaimScript(coins->vout[txin.prevout.n].scriptPubKey, op, vvchParams))
{
std::string name(vvchParams[0].begin(), vvchParams[0].end());
if (op == OP_CLAIM_NAME || op == OP_UPDATE_CLAIM)
{
uint160 claimId;
if (op == OP_CLAIM_NAME)
{
assert(vvchParams.size() == 2);
std::string name(vvchParams[0].begin(), vvchParams[0].end());
std::string value(vvchParams[1].begin(), vvchParams[1].end());
claimId = ClaimIdHash(txin.prevout.hash, txin.prevout.n);
LogPrintf("+++ %s[%lu]: OP_CLAIM_NAME \"%s\" = \"%s\" with claimId %s and tx prevout %s at index %d\n",
@ -2627,18 +2617,15 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
}
else if (op == OP_UPDATE_CLAIM)
{
assert(vvchParams.size() == 3);
std::string name(vvchParams[0].begin(), vvchParams[0].end());
std::string value(vvchParams[1].begin(), vvchParams[1].end());
claimId = uint160(vvchParams[1]);
std::string value(vvchParams[2].begin(), vvchParams[2].end());
LogPrintf("+++ %s[%lu]: OP_UPDATE_CLAIM \"%s\" = \"%s\" with claimId %s and tx prevout %s at index %d\n",
__func__, pindex->nHeight, name, SanitizeString(value),
claimId.GetHex(), txin.prevout.hash.GetHex(), txin.prevout.n);
}
std::string name(vvchParams[0].begin(), vvchParams[0].end());
int nValidAtHeight;
LogPrintf("%s: Removing %s from the claim trie. Tx: %s, nOut: %d\n", __func__, name, txin.prevout.hash.GetHex(), txin.prevout.n);
if (trieCache.spendClaim(name, COutPoint(txin.prevout.hash, txin.prevout.n), nValidAtHeight)) {
if (trieCache.spendClaim(name, COutPoint(txin.prevout.hash, txin.prevout.n), coins->nHeight, nValidAtHeight)) {
mClaimUndoHeights[i] = nValidAtHeight;
std::pair<std::string, uint160> entry(name, claimId);
spentClaims.push_back(entry);
@ -2648,8 +2635,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
}
else if (op == OP_SUPPORT_CLAIM)
{
assert(vvchParams.size() == 2);
std::string name(vvchParams[0].begin(), vvchParams[0].end());
uint160 supportedClaimId(vvchParams[1]);
LogPrintf("+++ %s[%lu]: OP_SUPPORT_CLAIM \"%s\" with claimId %s and tx prevout %s at index %d\n",
__func__, pindex->nHeight, name,
@ -2695,13 +2680,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
spentClaimsType::iterator itSpent;
for (itSpent = spentClaims.begin(); itSpent != spentClaims.end(); ++itSpent)
{
if (pclaimTrie->shouldNormalize()) {
const std::string normalizedName1 = normalizeClaimName(name);
const std::string normalizedName2 = normalizeClaimName(itSpent->first);
if (normalizedName1 == normalizedName2 && itSpent->second == claimId)
if (itSpent->second == claimId) {
if (trieCache.normalizeClaimName(name) == trieCache.normalizeClaimName(itSpent->first))
break;
} else if (itSpent->first == name && itSpent->second == claimId) {
break;
}
}
if (itSpent != spentClaims.end())
@ -2757,15 +2738,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
}
if (pindex->nHeight == Params().GetConsensus().nNormalizedNameForkHeight) {
LogPrintf("Incremented past the normalization hard fork height\n");
pclaimTrie = pclaimTrie->enableNormalizationFork(true, pindex->nHeight, trieCache);
CClaimTrieCache tmpTrieCache(pclaimTrie);
tmpTrieCache.setBestBlock(trieCache.getBestBlock());
trieCache = tmpTrieCache;
trieCache.getMerkleHash(true);
}
assert(trieCache.incrementBlock(blockUndo.insertUndo, blockUndo.expireUndo, blockUndo.insertSupportUndo, blockUndo.expireSupportUndo, blockUndo.takeoverHeightUndo));
if (trieCache.getMerkleHash() != block.hashClaimTrie) {

View file

@ -294,7 +294,7 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s
}
std::string name(vvchParams[0].begin(), vvchParams[0].end());
int throwaway;
if (trieCache.spendClaim(name, COutPoint(txin.prevout.hash, txin.prevout.n), throwaway)) {
if (trieCache.spendClaim(name, COutPoint(txin.prevout.hash, txin.prevout.n), nTxinHeight, throwaway)) {
std::pair<std::string, uint160> entry(name, claimId);
spentClaims.push_back(entry);
}
@ -341,12 +341,10 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s
spentClaimsType::iterator itSpent;
for (itSpent = spentClaims.begin(); itSpent != spentClaims.end(); ++itSpent)
{
if (pclaimTrie->shouldNormalize() &&
(normalizeClaimName(name) == normalizeClaimName(itSpent->first)) &&
itSpent->second == claimId)
break;
else if (itSpent->first == name && itSpent->second == claimId)
break;
if (itSpent->second == claimId) {
if (trieCache.normalizeClaimName(name) == trieCache.normalizeClaimName(itSpent->first))
break;
}
}
if (itSpent != spentClaims.end())
{
@ -445,31 +443,14 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s
supportQueueRowType dummyExpireSupportUndo;
std::vector<std::pair<std::string, int> > dummyTakeoverHeightUndo;
if (nHeight == Params().GetConsensus().nNormalizedNameForkHeight) {
trieCache.setBestBlock(pindexPrev->GetBlockHash());
pclaimTrie = pclaimTrie->enableNormalizationFork(true, nHeight, trieCache);
CClaimTrieCache tmpTrieCache(pclaimTrie);
tmpTrieCache.setBestBlock(trieCache.getBestBlock());
trieCache = tmpTrieCache;
trieCache.getMerkleHash(true);
}
trieCache.incrementBlock(dummyInsertUndo, dummyExpireUndo, dummyInsertSupportUndo, dummyExpireSupportUndo, dummyTakeoverHeightUndo);
pblock->hashClaimTrie = trieCache.getMerkleHash();
// disable the fork enabled above
if (nHeight == Params().GetConsensus().nNormalizedNameForkHeight)
pclaimTrie = pclaimTrie->enableNormalizationFork(false, nHeight, trieCache);
CValidationState state;
if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) {
throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state)));
}
// disable the fork enabled in TestBlockValidity
if (nHeight == Params().GetConsensus().nNormalizedNameForkHeight)
pclaimTrie = pclaimTrie->enableNormalizationFork(false, nHeight, trieCache);
}
return pblocktemplate.release();
}

View file

@ -1,4 +1,3 @@
#include "boost/scope_exit.hpp"
#include "consensus/validation.h"
#include "init.h"
#include "main.h"
@ -88,15 +87,16 @@ UniValue getclaimsintrie(const UniValue& params, bool fHelp)
"Result: \n"
"[\n"
" {\n"
" \"name\" (string) the name claimed\n"
" \"claims\": [ (array of object) the claims for this name\n"
" \"normalized_name\" (string) the name of these claims (after normalization)\n"
" \"claims\": [ (array of object) the claims for this name\n"
" {\n"
" \"claimId\" (string) the claimId of the claim\n"
" \"txid\" (string) the txid of the claim\n"
" \"n\" (numeric) the vout value of the claim\n"
" \"amount\" (numeric) txout amount\n"
" \"height\" (numeric) the height of the block in which this transaction is located\n"
" \"value\" (string) the value of this claim\n"
" \"claimId\" (string) the claimId of the claim\n"
" \"txid\" (string) the txid of the claim\n"
" \"n\" (numeric) the vout value of the claim\n"
" \"amount\" (numeric) txout amount\n"
" \"height\" (numeric) the height of the block in which this transaction is located\n"
" \"value\" (string) the value of this claim\n"
" \"name\" (string) the original name of this claim (before normalization)\n"
" }\n"
" ]\n"
" }\n"
@ -154,11 +154,15 @@ UniValue getclaimsintrie(const UniValue& params, bool fHelp)
std::string sValue(vvchParams[1].begin(), vvchParams[1].end());
claim.push_back(Pair("value", sValue));
}
std::string targetName;
CClaimValue targetClaim;
if (pclaimTrie->getClaimById(itClaims->claimId, targetName, targetClaim))
claim.push_back(Pair("name", targetName));
claims.push_back(claim);
}
UniValue nodeObj(UniValue::VOBJ);
nodeObj.push_back(Pair("name", name));
nodeObj.push_back(Pair("normalized_name", name));
nodeObj.push_back(Pair("claims", claims));
nodes.push_back(nodeObj);
}
@ -286,7 +290,7 @@ UniValue getvalueforname(const UniValue& params, bool fHelp)
if (fHelp || params.size() > 2)
throw std::runtime_error(
"getvalueforname \"name\"\n"
"Return the value associated with a name, if one exists\n"
"Return the winning value associated with a name, if one exists\n"
"Arguments:\n"
"1. \"name\" (string) the name to look up\n"
"2. \"blockhash\" (string, optional) get the value\n"
@ -303,7 +307,8 @@ UniValue getvalueforname(const UniValue& params, bool fHelp)
"\"n\" (numeric) vout value\n"
"\"amount\" (numeric) txout amount\n"
"\"effective amount\" (numeric) txout amount plus amount from all supports associated with the claim\n"
"\"height\" (numeric) the height of the block in which this transaction is located\n");
"\"height\" (numeric) the height of the block in which this transaction is located\n"
"\"name\" (string) the original name of this claim (before normalization)\n");
LOCK(cs_main);
@ -334,6 +339,12 @@ UniValue getvalueforname(const UniValue& params, bool fHelp)
ret.push_back(Pair("amount", claim.nAmount));
ret.push_back(Pair("effective amount", nEffectiveAmount));
ret.push_back(Pair("height", claim.nHeight));
std::string targetName;
CClaimValue targetClaim;
if (pclaimTrie->getClaimById(claim.claimId, targetName, targetClaim))
ret.push_back(Pair("name", targetName));
return ret;
}
@ -371,6 +382,12 @@ UniValue claimAndSupportsToJSON(const CCoinsViewCache& coinsCache, CAmount nEffe
ret.push_back(Pair("value", sValue));
ret.push_back(Pair("nEffectiveAmount", nEffectiveAmount));
ret.push_back(Pair("supports", supportObjs));
std::string targetName;
CClaimValue targetClaim;
if (pclaimTrie->getClaimById(claim.claimId, targetName, targetClaim))
ret.push_back(Pair("name", targetName));
return ret;
}
@ -391,6 +408,7 @@ UniValue getclaimsforname(const UniValue& params, bool fHelp)
"Result:\n"
"{\n"
" \"nLastTakeoverHeight\" (numeric) the last height at which ownership of the name changed\n"
" \"normalized_name\" (string) the name of these claims after normalization\n"
" \"claims\": [ (array of object) claims for this name\n"
" {\n"
" \"claimId\" (string) the claimId of this claim\n"
@ -408,6 +426,7 @@ UniValue getclaimsforname(const UniValue& params, bool fHelp)
" \"nValidAtHeight\" (numeric) the height at which the support became/becomes valid\n"
" \"nAmount\" (numeric) the amount of the support\n"
" ]\n"
" \"name\" (string) the original name of this claim before normalization\n"
" }\n"
" ],\n"
" \"supports without claims\": [ (array of object) supports that did not match a claim for this name\n"
@ -454,6 +473,7 @@ UniValue getclaimsforname(const UniValue& params, bool fHelp)
UniValue ret(UniValue::VOBJ);
ret.push_back(Pair("nLastTakeoverHeight", claimsForName.nLastTakeoverHeight));
ret.push_back(Pair("normalized_name", claimsForName.name));
for (claimSupportMapType::const_iterator itClaimsAndSupports = claimSupportMap.begin(); itClaimsAndSupports != claimSupportMap.end(); ++itClaimsAndSupports) {
CAmount nEffectiveAmount = trieCache.getEffectiveAmountForClaim(claimsForName, itClaimsAndSupports->first);
@ -476,7 +496,8 @@ UniValue getclaimbyid(const UniValue& params, bool fHelp)
"1. \"claimId\" (string) the claimId of this claim\n"
"Result:\n"
"{\n"
" \"name\" (string) the name of the claim\n"
" \"name\" (string) the original name of the claim (before normalization)\n"
" \"normalized_name\" (string) the name of this claim (after normalization)\n"
" \"value\" (string) claim metadata\n"
" \"claimId\" (string) the claimId of this claim\n"
" \"txid\" (string) the hash of the transaction which has successfully claimed this name\n"
@ -503,13 +524,15 @@ UniValue getclaimbyid(const UniValue& params, bool fHelp)
pclaimTrie->getClaimById(claimId, name, claimValue);
if (claimValue.claimId == claimId)
{
CClaimTrieCache cache(pclaimTrie);
std::vector<CSupportValue> supports;
CAmount effectiveAmount = pclaimTrie->getEffectiveAmountForClaim(name, claimValue.claimId, &supports);
CAmount effectiveAmount = cache.getEffectiveAmountForClaim(name, claimValue.claimId, &supports);
std::string sValue;
CCoinsViewCache coins(pcoinsTip);
getValueForClaim(coins, claimValue.outPoint, sValue);
claim.push_back(Pair("name", name));
claim.push_back(Pair("normalized_name", cache.normalizeClaimName(name, true)));
claim.push_back(Pair("value", sValue));
claim.push_back(Pair("claimId", claimValue.claimId.GetHex()));
claim.push_back(Pair("txid", claimValue.outPoint.hash.GetHex()));
@ -866,6 +889,30 @@ UniValue getnameproof(const UniValue& params, bool fHelp)
return proofToJSON(proof);
}
UniValue checknormalization(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw std::runtime_error(
"checknormalization\n"
"Given an unnormalized name of a claim, return normalized version of it\n"
"Arguments:\n"
"1. \"name\" (string) the name to normalize\n"
"Result: \n"
"\"normalized\" (string) fully normalized name\n"
);
std::string name = params[0].get_str();
CClaimTrieCache triecache(pclaimTrie);
bool force = true;
std::string out = triecache.normalizeClaimName(name, force);
return out;
}
static const CRPCCommand commands[] =
{ // category name actor (function) okSafeMode
// --------------------- ------------------------ ----------------------- ----------
@ -879,6 +926,7 @@ static const CRPCCommand commands[] =
{ "Claimtrie", "getclaimsfortx", &getclaimsfortx, true },
{ "Claimtrie", "getnameproof", &getnameproof, true },
{ "Claimtrie", "getclaimbyid", &getclaimbyid, true },
{ "Claimtrie", "checknormalization", &checknormalization, true },
};
void RegisterClaimTrieRPCCommands(CRPCTable &tableRPC)

View file

@ -21,7 +21,6 @@
using namespace std;
BOOST_FIXTURE_TEST_SUITE(claimtriebranching_tests, RegTestingSetup)
//is a claim in queue
@ -63,7 +62,8 @@ boost::test_tools::predicate_result
best_claim_effective_amount_equals(std::string name, CAmount amount)
{
CClaimValue val;
bool have_info = pclaimTrie->getInfoForName(name, val);
CClaimTrieCache cache(pclaimTrie);
bool have_info = cache.getInfoForName(name, val);
if (!have_info)
{
boost::test_tools::predicate_result res(false);
@ -72,7 +72,7 @@ best_claim_effective_amount_equals(std::string name, CAmount amount)
}
else
{
CAmount effective_amount = pclaimTrie->getEffectiveAmountForClaim(name, val.claimId);
CAmount effective_amount = cache.getEffectiveAmountForClaim(name, val.claimId);
if (effective_amount != amount)
{
boost::test_tools::predicate_result res(false);
@ -117,20 +117,20 @@ struct ClaimTrieChainFixture{
std::vector<CTransaction> coinbase_txs;
std::vector<int> marks;
int coinbase_txs_used;
int unique_block_counter;
unsigned int num_txs;
unsigned int num_txs_for_next_block;
// these will take on regtest parameters
const int normalizationForkHeight;
const int expirationForkHeight;
const int originalExpiration;
const int extendedExpiration;
int unique_block_counter;
int normalization_original;
ClaimTrieChainFixture() : normalizationForkHeight(Params(CBaseChainParams::REGTEST).GetConsensus().nNormalizedNameForkHeight),
expirationForkHeight(Params(CBaseChainParams::REGTEST).GetConsensus().nExtendedClaimExpirationForkHeight),
ClaimTrieChainFixture() : expirationForkHeight(Params(CBaseChainParams::REGTEST).GetConsensus().nExtendedClaimExpirationForkHeight),
originalExpiration(Params(CBaseChainParams::REGTEST).GetConsensus().nOriginalClaimExpirationTime),
extendedExpiration(Params(CBaseChainParams::REGTEST).GetConsensus().nExtendedClaimExpirationTime)
extendedExpiration(Params(CBaseChainParams::REGTEST).GetConsensus().nExtendedClaimExpirationTime),
unique_block_counter(0), normalization_original(-1)
{
fRequireStandard = false;
ENTER_CRITICAL_SECTION(cs_main);
@ -139,7 +139,6 @@ struct ClaimTrieChainFixture{
num_txs_for_next_block = 0;
num_txs = 0;
coinbase_txs_used = 0;
unique_block_counter = 0;
// generate coinbases to spend
CreateCoinbases(40, coinbase_txs);
}
@ -147,14 +146,26 @@ struct ClaimTrieChainFixture{
~ClaimTrieChainFixture()
{
DecrementBlocks(chainActive.Height());
if (normalization_original >= 0) {
const Consensus::Params& consensus = Params().GetConsensus();
const_cast<Consensus::Params&>(consensus).nNormalizedNameForkHeight = normalization_original;
}
pclaimTrie->setExpirationTime(originalExpiration); // in case it was changed during the test
LEAVE_CRITICAL_SECTION(cs_main);
}
void setNormalizationForkHeight(int targetMinusCurrent) {
int target = chainActive.Height() + targetMinusCurrent;
const Consensus::Params& consensus = Params().GetConsensus();
normalization_original = consensus.nNormalizedNameForkHeight;
const_cast<Consensus::Params&>(consensus).nNormalizedNameForkHeight = target;
}
bool CreateBlock(CBlockTemplate* pblocktemplate)
{
CBlock* pblock = &pblocktemplate->block;
pblock->nVersion = 1;
pblock->nTime = chainActive.Tip()->GetBlockTime() + Params().GetConsensus().nPowTargetSpacing;
pblock->nTime = chainActive.Tip()->GetBlockTime()+Params().GetConsensus().nPowTargetSpacing;
CMutableTransaction txCoinbase(pblock->vtx[0]);
txCoinbase.vin[0].scriptSig = CScript() << CScriptNum(unique_block_counter++) << CScriptNum(chainActive.Height());
txCoinbase.vout[0].nValue = GetBlockSubsidy(chainActive.Height() + 1, Params().GetConsensus());
@ -162,7 +173,8 @@ struct ClaimTrieChainFixture{
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
for (uint32_t i = 0;; ++i) {
pblock->nNonce = i;
if (CheckProofOfWork(pblock->GetPoWHash(), pblock->nBits, Params().GetConsensus())) {
if (CheckProofOfWork(pblock->GetPoWHash(), pblock->nBits, Params().GetConsensus()))
{
break;
}
}
@ -170,16 +182,18 @@ struct ClaimTrieChainFixture{
bool success = (ProcessNewBlock(state, Params(), NULL, pblock, true, NULL) && state.IsValid() && pblock->GetHash() == chainActive.Tip()->GetBlockHash());
pblock->hashPrevBlock = pblock->GetHash();
return success;
}
bool CreateCoinbases(unsigned int num_coinbases, std::vector<CTransaction>& coinbases)
{
CBlockTemplate* pblocktemplate;
CBlockTemplate *pblocktemplate;
coinbases.clear();
BOOST_CHECK(pblocktemplate = CreateNewBlock(Params(), CScript() << OP_TRUE));
BOOST_CHECK(pblocktemplate = CreateNewBlock(Params(), CScript()<<OP_TRUE ));
BOOST_CHECK(pblocktemplate->block.vtx.size() == 1);
pblocktemplate->block.hashPrevBlock = chainActive.Tip()->GetBlockHash();
for (unsigned int i = 0; i < 100 + num_coinbases; ++i) {
for (unsigned int i = 0; i < 100 + num_coinbases; ++i)
{
BOOST_CHECK(CreateBlock(pblocktemplate));
if (coinbases.size() < num_coinbases)
coinbases.push_back(CTransaction(pblocktemplate->block.vtx[0]));
@ -188,6 +202,7 @@ struct ClaimTrieChainFixture{
return true;
}
void CommitTx(CMutableTransaction &tx){
num_txs_for_next_block++;
num_txs++;
@ -263,8 +278,7 @@ struct ClaimTrieChainFixture{
CMutableTransaction GetCoinbase()
{
CMutableTransaction tx = coinbase_txs[coinbase_txs_used];
coinbase_txs_used++;
CMutableTransaction tx = coinbase_txs.at(coinbase_txs_used++);
return tx;
}
@ -295,10 +309,10 @@ struct ClaimTrieChainFixture{
for (int i = 0; i < num_blocks; i++) {
CValidationState state;
CBlockIndex* pblockindex = chainActive.Tip();
InvalidateBlock(state, Params().GetConsensus(), pblockindex);
BOOST_CHECK(InvalidateBlock(state, Params().GetConsensus(), pblockindex));
if (state.IsValid())
{
ActivateBestChain(state, Params());
BOOST_CHECK(ActivateBestChain(state, Params()));
}
else
{
@ -357,12 +371,12 @@ BOOST_AUTO_TEST_CASE(claim_test)
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("test",tx3));
BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size());
BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").size());
fixture.DecrementBlocks(1);
BOOST_CHECK(!is_best_claim("test",tx2));
BOOST_CHECK(!is_best_claim("test",tx3));
BOOST_CHECK_EQUAL(0U, pclaimTrie->getClaimsForName("test").claims.size());
BOOST_CHECK_EQUAL(0U, pclaimTrie->getClaimsForName("test").size());
// make two claims , one older
CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1);
@ -374,7 +388,7 @@ BOOST_AUTO_TEST_CASE(claim_test)
BOOST_CHECK(is_best_claim("test", tx4));
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("test",tx4));
BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size());
BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").size());
fixture.DecrementBlocks(1);
BOOST_CHECK(is_best_claim("test", tx4));
@ -394,7 +408,7 @@ BOOST_AUTO_TEST_CASE(claim_test)
BOOST_CHECK(is_best_claim("test", tx6));
fixture.IncrementBlocks(10);
BOOST_CHECK(is_best_claim("test",tx7));
BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size());
BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").size());
fixture.DecrementBlocks(10);
BOOST_CHECK(is_claim_in_queue("test",tx7));
@ -596,7 +610,7 @@ BOOST_AUTO_TEST_CASE(support_spend_test)
CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(),tx5,"test",2);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("test",tx5));
BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size());
BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").size());
// build the spend where s2 is sppent on txin[1] and tx3 is spent on txin[0]
uint32_t prevout = 0;
@ -661,7 +675,7 @@ BOOST_AUTO_TEST_CASE(claimtrie_update_test)
CMutableTransaction u3 = fixture.MakeUpdate(tx3, "test", "one", ClaimIdHash(tx3.GetHash(), 0), 2);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("test",u3));
BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size());
BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").size());
fixture.DecrementBlocks(11);
// losing update on winning claim happens without delay
@ -669,7 +683,7 @@ BOOST_AUTO_TEST_CASE(claimtrie_update_test)
CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2);
fixture.IncrementBlocks(10);
BOOST_CHECK(is_best_claim("test", tx5));
BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size());
BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").size());
CMutableTransaction u4 = fixture.MakeUpdate(tx5, "test", "one", ClaimIdHash(tx5.GetHash(), 0), 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("test",tx6));
@ -788,38 +802,38 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_get_effective_amount_for_claim)
uint160 claimId = ClaimIdHash(claimtx.GetHash(), 0);
fixture.IncrementBlocks(1);
BOOST_CHECK(pclaimTrie->getEffectiveAmountForClaim("test", claimId) == 2);
BOOST_CHECK(pclaimTrie->getEffectiveAmountForClaim("inexistent", claimId) == 0); //not found returns 0
BOOST_CHECK(CClaimTrieCache(pclaimTrie).getEffectiveAmountForClaim("test", claimId) == 2);
BOOST_CHECK(CClaimTrieCache(pclaimTrie).getEffectiveAmountForClaim("inexistent", claimId) == 0); //not found returns 0
// one claim, one support
fixture.MakeSupport(fixture.GetCoinbase(), claimtx, "test", 40);
fixture.IncrementBlocks(1);
BOOST_CHECK(pclaimTrie->getEffectiveAmountForClaim("test", claimId) == 42);
BOOST_CHECK(CClaimTrieCache(pclaimTrie).getEffectiveAmountForClaim("test", claimId) == 42);
// Two claims, first one with supports
CMutableTransaction claimtx2 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "two", 1);
uint160 claimId2 = ClaimIdHash(claimtx2.GetHash(), 0);
fixture.IncrementBlocks(10);
BOOST_CHECK(pclaimTrie->getEffectiveAmountForClaim("test", claimId) == 42);
BOOST_CHECK(pclaimTrie->getEffectiveAmountForClaim("test", claimId2) == 1);
BOOST_CHECK(pclaimTrie->getEffectiveAmountForClaim("inexistent", claimId) == 0);
BOOST_CHECK(pclaimTrie->getEffectiveAmountForClaim("inexistent", claimId2) == 0);
BOOST_CHECK(CClaimTrieCache(pclaimTrie).getEffectiveAmountForClaim("test", claimId) == 42);
BOOST_CHECK(CClaimTrieCache(pclaimTrie).getEffectiveAmountForClaim("test", claimId2) == 1);
BOOST_CHECK(CClaimTrieCache(pclaimTrie).getEffectiveAmountForClaim("inexistent", claimId) == 0);
BOOST_CHECK(CClaimTrieCache(pclaimTrie).getEffectiveAmountForClaim("inexistent", claimId2) == 0);
// Two claims, both with supports, second claim effective amount being less than first claim
fixture.MakeSupport(fixture.GetCoinbase(), claimtx2, "test", 6);
fixture.IncrementBlocks(13); //delay
BOOST_CHECK(pclaimTrie->getEffectiveAmountForClaim("test", claimId) == 42);
BOOST_CHECK(pclaimTrie->getEffectiveAmountForClaim("test", claimId2) == 7);
BOOST_CHECK(CClaimTrieCache(pclaimTrie).getEffectiveAmountForClaim("test", claimId) == 42);
BOOST_CHECK(CClaimTrieCache(pclaimTrie).getEffectiveAmountForClaim("test", claimId2) == 7);
// Two claims, both with supports, second one taking over
fixture.MakeSupport(fixture.GetCoinbase(), claimtx2, "test", 1330);
fixture.IncrementBlocks(26); //delay
BOOST_CHECK(pclaimTrie->getEffectiveAmountForClaim("test", claimId) == 42);
BOOST_CHECK(pclaimTrie->getEffectiveAmountForClaim("test", claimId2) == 1337);
BOOST_CHECK(CClaimTrieCache(pclaimTrie).getEffectiveAmountForClaim("test", claimId) == 42);
BOOST_CHECK(CClaimTrieCache(pclaimTrie).getEffectiveAmountForClaim("test", claimId2) == 1337);
}
/*
@ -1077,6 +1091,51 @@ BOOST_AUTO_TEST_CASE(supports_fall_through)
BOOST_CHECK(is_best_claim("A", tx2)); //tx2 support should be active now
}
/*
normalization
test normalization function indpendent from rest of the code
*/
BOOST_AUTO_TEST_CASE(normalization_only)
{
CClaimTrieCache ccache(pclaimTrie);
// basic ASCII casing tests
BOOST_CHECK_EQUAL("test", ccache.normalizeClaimName("TESt", true));
BOOST_CHECK_EQUAL("test", ccache.normalizeClaimName("tesT", true));
BOOST_CHECK_EQUAL("test", ccache.normalizeClaimName("TesT", true));
BOOST_CHECK_EQUAL("test", ccache.normalizeClaimName("test", true));
BOOST_CHECK_EQUAL("test this", ccache.normalizeClaimName("Test This", true));
// test invalid utf8 bytes are returned as is
BOOST_CHECK_EQUAL("\xFF", ccache.normalizeClaimName("\xFF", true));
BOOST_CHECK_EQUAL("\xC3\x28", ccache.normalizeClaimName("\xC3\x28", true));
// ohm sign unicode code point \x2126 should be transformed to equivalent
// unicode code point \x03C9 , greek small letter omega
BOOST_CHECK_EQUAL("\xCF\x89", ccache.normalizeClaimName("\xE2\x84\xA6", true));
// cyrillic capital ef code point \x0424 should be transformed to lower case
// \x0444
BOOST_CHECK_EQUAL("\xD1\x84", ccache.normalizeClaimName("\xD0\xA4", true));
// armenian capital ben code point \x0532 should be transformed to lower case
// \x0562
BOOST_CHECK_EQUAL("\xD5\xA2", ccache.normalizeClaimName("\xD4\xB2", true));
// japanese pbu code point \x3076 should be transformed by NFD decomposition
// into \x3075 and \x3099
BOOST_CHECK_EQUAL("\xE3\x81\xB5\xE3\x82\x99",
ccache.normalizeClaimName("\xE3\x81\xB6", true));
// hangul ggwalg unicode code point \xAF51 should be transformed by NFD
// decomposition into unicode code points \x1101 \x116A \x11B0
// source: http://unicode.org/L2/L2009/09052-tr47.html
BOOST_CHECK_EQUAL("\xE1\x84\x81\xE1\x85\xAA\xE1\x86\xB0",
ccache.normalizeClaimName("\xEA\xBD\x91", true));
}
/*
normalization
check claim name normalization before the fork
@ -1085,64 +1144,65 @@ BOOST_AUTO_TEST_CASE(supports_fall_through)
BOOST_AUTO_TEST_CASE(claimtriebranching_normalization)
{
ClaimTrieChainFixture fixture;
BOOST_CHECK(!pclaimTrie->shouldNormalize());
// Disable reg-test expiration during this test
pclaimTrie->setExpirationTime(5000);
// check claim names are not normalized
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "normalizeTest", "one", 3);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("normalizeTest", tx1));
fixture.DecrementBlocks(1);
BOOST_CHECK(pclaimTrie->getTotalNamesInTrie() == 0);
fixture.CommitTx(tx1);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("normalizeTest", tx1));
CMutableTransaction tx2a = fixture.MakeClaim(fixture.GetCoinbase(), "Normalizetest", "one_a", 2);
CMutableTransaction tx2 = fixture.MakeUpdate(tx2a, "Normalizetest", "one", ClaimIdHash(tx2a.GetHash(), 0), 2);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("normalizeTest", tx1));
BOOST_CHECK(is_best_claim("Normalizetest", tx2));
// Activate the fork (which rebuilds the existing claimtrie and
// cache), flattening all previously existing name clashes due to
// the normalization
fixture.IncrementBlocks(fixture.normalizationForkHeight - chainActive.Height());
BOOST_CHECK(pclaimTrie->shouldNormalize());
fixture.setNormalizationForkHeight(2);
// Disable reg-test expiration during this test
pclaimTrie->setExpirationTime(5000);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("normalizeTest", tx1));
BOOST_CHECK(is_best_claim("Normalizetest", tx2));
fixture.IncrementBlocks(1, true);
// Post-fork, tx1 (the previous winning claim) assumes all name
// variants of what it originally was ...
BOOST_CHECK(is_best_claim("normalizeTest", tx1)); // effective amount is 3
BOOST_CHECK(best_claim_effective_amount_equals("normalizeTest", 3));
BOOST_CHECK(is_best_claim("normalizetest", tx1));
BOOST_CHECK(best_claim_effective_amount_equals("normalizetest", 3));
CClaimValue val;
pclaimTrie->getInfoForName("normalizeTest", val);
BOOST_CHECK(!pclaimTrie->getInfoForName("normalizeTest", val));
// Check equivalence of normalized claim names
BOOST_CHECK(is_best_claim("NORMALIZETEST", tx1));
BOOST_CHECK(is_best_claim("NormalizeTeST", tx1));
BOOST_CHECK(is_best_claim("NormaLizeTeST", tx1));
BOOST_CHECK(is_best_claim("Normalizetest", tx1)); // collapsed tx2
BOOST_CHECK(is_best_claim("normalizetest", tx1)); // collapsed tx2
fixture.IncrementBlocks(1);
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "NORMALIZETEST", "one", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(!is_best_claim("NORMALIZETEST", tx3));
BOOST_CHECK(!is_best_claim("normalizetest", tx3));
CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "NoRmAlIzEtEsT", 2);
fixture.IncrementBlocks(1);
// Ensure that supports work for normalized claim names
BOOST_CHECK(is_best_claim("normalizeTest", tx1)); // effective amount is 5
BOOST_CHECK(best_claim_effective_amount_equals("normalizeTEST", 5));
BOOST_CHECK(is_best_claim("normalizetest", tx1)); // effective amount is 5
BOOST_CHECK(best_claim_effective_amount_equals("normalizetest", 5));
CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "foo", "bar", 1);
CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(), tx4, "Foo", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("FOO", tx4));
BOOST_CHECK(is_best_claim("foo", tx4));
CMutableTransaction u1 = fixture.MakeUpdate(tx4, "foo", "baz", ClaimIdHash(tx4.GetHash(), 0), 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("fOO", u1));
BOOST_CHECK(is_best_claim("foo", u1));
CMutableTransaction u2 = fixture.MakeUpdate(tx1, "nOrmalIzEtEst", "two", ClaimIdHash(tx1.GetHash(), 0), 3);
fixture.IncrementBlocks(1);
@ -1155,60 +1215,364 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_normalization)
CClaimValue nval1;
pclaimTrie->getInfoForName("amélie", nval1);
BOOST_CHECK(nval1.claimId == ClaimIdHash(tx5.GetHash(), 0));
BOOST_CHECK(best_claim_effective_amount_equals("Ame\u0301lie", 2));
BOOST_CHECK(best_claim_effective_amount_equals("amélie", 2));
// Check equivalence of normalized claim names
BOOST_CHECK(is_best_claim("Ame\u0301lie", tx5));
BOOST_CHECK(is_best_claim("Amélie", tx5));
BOOST_CHECK(is_best_claim("amélie", tx5));
BOOST_CHECK(is_best_claim("améLIE", tx5));
CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(), "あてはまる", "jn1", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("あてはまる", tx7));
CMutableTransaction tx8 = fixture.MakeClaim(fixture.GetCoinbase(), "añejo", "es1", 1);
CMutableTransaction tx8 = fixture.MakeClaim(fixture.GetCoinbase(), "AÑEJO", "es1", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("añejo", tx8));
BOOST_CHECK(is_best_claim("Añejo", tx8));
BOOST_CHECK(is_best_claim("AñeJO", tx8));
BOOST_CHECK(is_best_claim("AñEjO", tx8));
// Rewind to 1 block before the fork and be sure that the fork is
// no longer active
fixture.DecrementBlocks((chainActive.Height() - fixture.normalizationForkHeight) + 1);
BOOST_CHECK(!pclaimTrie->shouldNormalize());
// Rewind to 1 block before the fork and be sure that the fork is no longer active
fixture.DecrementBlocks();
// Now check that our old (non-normalized) claims are 'alive' again
BOOST_CHECK(is_best_claim("normalizeTest", tx1));
BOOST_CHECK(!is_best_claim("NORMALIZETEST", tx1)); // no longer equivalent
BOOST_CHECK(!is_best_claim("Normalizetest", tx1)); // no longer equivalent
BOOST_CHECK(is_best_claim("Normalizetest", tx2));
// Create new claim
CMutableTransaction tx9 = fixture.MakeClaim(fixture.GetCoinbase(), "blah", "blah", 1);
std::string invalidUtf8("\xFF\xFF");
CMutableTransaction tx10 = fixture.MakeClaim(fixture.GetCoinbase(), invalidUtf8, "blah", 1); // invalid UTF8
// Roll forward to fork height again and check again that we're normalized
fixture.IncrementBlocks(1);
BOOST_CHECK(chainActive.Height() == fixture.normalizationForkHeight);
BOOST_CHECK(is_best_claim("NORMALIZETEST", tx1));
BOOST_CHECK(is_best_claim("NormalizeTeST", tx1));
BOOST_CHECK(is_best_claim("NormaLizeTeST", tx1));
BOOST_CHECK(is_best_claim("Normalizetest", tx1)); // collapsed tx2
BOOST_CHECK(chainActive.Height() == Params().GetConsensus().nNormalizedNameForkHeight);
BOOST_CHECK(is_best_claim("normalizetest", tx1)); // collapsed tx2
BOOST_CHECK(is_best_claim(invalidUtf8, tx10));
// Rewind to 1 block before the fork and be sure that the fork is
// no longer active
fixture.DecrementBlocks((chainActive.Height() - fixture.normalizationForkHeight) + 1);
BOOST_CHECK(!pclaimTrie->shouldNormalize());
fixture.DecrementBlocks(1);
BOOST_CHECK(is_best_claim("Normalizetest", tx2));
// Roll forward to fork height again and check again that we're normalized
fixture.IncrementBlocks(1);
BOOST_CHECK(chainActive.Height() == fixture.normalizationForkHeight);
BOOST_CHECK(is_best_claim("NORMALIZETEST", tx1));
BOOST_CHECK(is_best_claim("NormalizeTeST", tx1));
BOOST_CHECK(is_best_claim("NormaLizeTeST", tx1));
BOOST_CHECK(is_best_claim("Normalizetest", tx1)); // collapsed tx2
BOOST_CHECK(chainActive.Height() == Params().GetConsensus().nNormalizedNameForkHeight);
BOOST_CHECK(is_best_claim("normalizetest", tx1)); // collapsed tx2
}
BOOST_AUTO_TEST_CASE(claimtriecache_normalization)
{
ClaimTrieChainFixture fixture;
std::string name = "Ame\u0301lie";
std::string name_upper = "Amélie";
std::string name_normd = "amélie"; // this accented e is not actually the same as the one above; this has been "normalized"
BOOST_CHECK(name != name_upper);
// Add another set of unicode claims that will collapse after the fork
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), name, "amilie", 2);
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), name_upper, "amelie", 2);
fixture.MakeClaim(fixture.GetCoinbase(), "amelie1", "amelie", 2);
fixture.IncrementBlocks(1);
CClaimValue lookupClaim;
std::string lookupName;
BOOST_CHECK(pclaimTrie->getClaimById(ClaimIdHash(tx2.GetHash(), 0), lookupName, lookupClaim));
CClaimValue nval1;
BOOST_CHECK(pclaimTrie->getInfoForName("amelie1", nval1));
// amélie is not found cause normalization still not appear
BOOST_CHECK(!pclaimTrie->getInfoForName(name_normd, nval1));
// Activate the fork (which rebuilds the existing claimtrie and
// cache), flattening all previously existing name clashes due to
// the normalization
fixture.setNormalizationForkHeight(1);
int currentHeight = chainActive.Height();
fixture.IncrementBlocks(1);
// Ok normalization fix the name problem
BOOST_CHECK(pclaimTrie->getInfoForName(name_normd, nval1));
BOOST_CHECK(nval1.nHeight == currentHeight);
BOOST_CHECK(lookupClaim == nval1);
CCoinsViewCache coins(pcoinsTip);
CClaimTrieCache trieCache(pclaimTrie);
CBlockIndex* pindex = chainActive.Tip();
CValidationState state;
CBlock block;
int amelieValidHeight;
BOOST_CHECK(trieCache.shouldNormalize());
BOOST_CHECK(ReadBlockFromDisk(block, pindex, Params().GetConsensus()));
BOOST_CHECK(DisconnectBlock(block, state, pindex, coins, trieCache, NULL));
BOOST_CHECK(state.IsValid());
BOOST_CHECK(!trieCache.shouldNormalize());
BOOST_CHECK(!trieCache.spendClaim(name_normd, COutPoint(tx2.GetHash(), 0), currentHeight, amelieValidHeight));
BOOST_CHECK(trieCache.spendClaim(name_upper, COutPoint(tx2.GetHash(), 0), currentHeight, amelieValidHeight));
BOOST_CHECK(!pclaimTrie->getInfoForName(name, nval1));
BOOST_CHECK(trieCache.getInfoForName(name, nval1));
BOOST_CHECK(trieCache.addClaim(name, COutPoint(tx1.GetHash(), 0), ClaimIdHash(tx1.GetHash(), 0), CAmount(2), currentHeight + 1));
BOOST_CHECK(trieCache.getInfoForName(name, nval1));
insertUndoType insertUndo;
claimQueueRowType expireUndo;
insertUndoType insertSupportUndo;
supportQueueRowType expireSupportUndo;
std::vector<std::pair<std::string, int> > takeoverHeightUndo;
BOOST_CHECK(trieCache.incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverHeightUndo));
BOOST_CHECK(trieCache.shouldNormalize());
// we cannot use getXXXForName cause they will normalized name
struct CNameVerifierCallback : public CNodeCallback {
const std::string& cmp;
CNameVerifierCallback(const std::string& cmp) : cmp(cmp) {}
void visit(const std::string& nodeName, const CClaimTrieNode* node) {
BOOST_CHECK(nodeName != cmp);
}
};
CNameVerifierCallback callback(name);
trieCache.iterateTrie(callback);
}
BOOST_AUTO_TEST_CASE(undo_normalization_does_not_kill_claim_order) {
ClaimTrieChainFixture fixture;
fixture.setNormalizationForkHeight(5);
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 1);
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "a", "3", 3);
fixture.IncrementBlocks(1);
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "2", 2);
fixture.IncrementBlocks(2);
BOOST_CHECK(is_best_claim("A", tx2));
fixture.IncrementBlocks(3, true);
BOOST_CHECK(is_best_claim("a", tx3));
fixture.DecrementBlocks();
BOOST_CHECK(is_best_claim("A", tx2));
}
BOOST_AUTO_TEST_CASE(normalized_activations_fall_through) {
ClaimTrieChainFixture fixture;
fixture.setNormalizationForkHeight(5);
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "AB", "1", 1);
fixture.IncrementBlocks(3);
BOOST_CHECK(pclaimTrie->nProportionalDelayFactor == 1);
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "Ab", "2", 4);
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "aB", "2", 3);
CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "ab", "2", 2);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("AB", tx1));
fixture.IncrementBlocks(3);
BOOST_CHECK(is_best_claim("ab", tx2));
BOOST_CHECK(pclaimTrie->getClaimsForName("ab").size() == 4U);
fixture.DecrementBlocks(3);
fixture.Spend(tx1);
fixture.Spend(tx2);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("ab", tx3));
BOOST_CHECK(pclaimTrie->getClaimsForName("ab").size() == 2U);
fixture.DecrementBlocks(1);
BOOST_CHECK(is_best_claim("AB", tx1));
fixture.Spend(tx1);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("ab", tx2));
for (int i = 0; i < 7; ++i) {
fixture.IncrementBlocks(i, true); // well into normalized teritory
CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), "CD", "a", 1 + i);
fixture.IncrementBlocks(3);
CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(), "Cd", "b", 2 + i);
CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(), "cD", "c", 3 + i);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("cd", tx5));
fixture.Spend(tx5);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("cd", tx7));
fixture.DecrementBlocks();
}
}
BOOST_AUTO_TEST_CASE(normalization_removal_test)
{
ClaimTrieChainFixture fixture;
fixture.setNormalizationForkHeight(2);
fixture.IncrementBlocks(3);
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "AB", "1", 1);
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "Ab", "2", 2);
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "aB", "3", 3);
CMutableTransaction sx1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "AB", 1);
CMutableTransaction sx2 = fixture.MakeSupport(fixture.GetCoinbase(), tx2, "Ab", 1);
CClaimTrieCache cache(pclaimTrie);
cache.addClaim("AB", COutPoint(tx1.GetHash(), 0), ClaimIdHash(tx1.GetHash(), 0), 1, pclaimTrie->nCurrentHeight);
cache.addClaim("Ab", COutPoint(tx2.GetHash(), 0), ClaimIdHash(tx2.GetHash(), 0), 2, pclaimTrie->nCurrentHeight);
cache.addClaim("aB", COutPoint(tx3.GetHash(), 0), ClaimIdHash(tx3.GetHash(), 0), 3, pclaimTrie->nCurrentHeight);
cache.addSupport("AB", COutPoint(sx1.GetHash(), 0), 1, ClaimIdHash(tx1.GetHash(), 0), pclaimTrie->nCurrentHeight);
cache.addSupport("Ab", COutPoint(sx2.GetHash(), 0), 1, ClaimIdHash(tx2.GetHash(), 0), pclaimTrie->nCurrentHeight);
insertUndoType insertUndo;
claimQueueRowType expireUndo;
insertUndoType insertSupportUndo;
supportQueueRowType expireSupportUndo;
std::vector<std::pair<std::string, int> > takeoverHeightUndo;
BOOST_CHECK(cache.incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverHeightUndo));
BOOST_CHECK(cache.getClaimsForName("ab").claims.size() == 3U);
BOOST_CHECK(cache.getClaimsForName("ab").supports.size() == 2U);
BOOST_CHECK(cache.decrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverHeightUndo));
BOOST_CHECK(cache.undoAddSupport("AB", COutPoint(sx1.GetHash(), 0), pclaimTrie->nCurrentHeight));
BOOST_CHECK(cache.undoAddSupport("Ab", COutPoint(sx2.GetHash(), 0), pclaimTrie->nCurrentHeight));
BOOST_CHECK(cache.undoAddClaim("AB", COutPoint(tx1.GetHash(), 0), pclaimTrie->nCurrentHeight));
BOOST_CHECK(cache.undoAddClaim("Ab", COutPoint(tx2.GetHash(), 0), pclaimTrie->nCurrentHeight));
BOOST_CHECK(cache.undoAddClaim("aB", COutPoint(tx3.GetHash(), 0), pclaimTrie->nCurrentHeight));
BOOST_CHECK(cache.getClaimsForName("ab").claims.size() == 0U);
}
BOOST_AUTO_TEST_CASE(normalization_does_not_kill_supports) {
ClaimTrieChainFixture fixture;
fixture.setNormalizationForkHeight(3);
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 1);
fixture.MakeSupport(fixture.GetCoinbase(), tx1, "A", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("A", 2));
fixture.MakeSupport(fixture.GetCoinbase(), tx1, "A", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("A", 3));
fixture.MakeSupport(fixture.GetCoinbase(), tx1, "A", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("a", 4));
fixture.MakeSupport(fixture.GetCoinbase(), tx1, "A", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("a", 5));
fixture.DecrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("a", 4));
fixture.DecrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("A", 3));
fixture.DecrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("A", 2));
fixture.IncrementBlocks(5);
BOOST_CHECK(best_claim_effective_amount_equals("a", 3));
}
BOOST_AUTO_TEST_CASE(normalization_does_not_fail_on_spend) {
ClaimTrieChainFixture fixture;
fixture.setNormalizationForkHeight(2);
std::string sName1("testN");
std::string sName2("testn");
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, "1", 3);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim(sName1, tx1));
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, "2", 2);
CMutableTransaction tx1s = fixture.MakeSupport(fixture.GetCoinbase(), tx1, sName1, 2);
fixture.IncrementBlocks(2, true);
BOOST_CHECK(is_best_claim(sName2, tx1));
CMutableTransaction tx3 = fixture.Spend(tx1); // abandon the claim
CMutableTransaction tx3s = fixture.Spend(tx1s);
fixture.IncrementBlocks(2);
BOOST_CHECK(is_best_claim(sName2, tx2));
fixture.DecrementBlocks();
BOOST_CHECK(is_best_claim(sName1, tx1));
}
BOOST_AUTO_TEST_CASE(normalization_does_not_kill_sort_order) {
ClaimTrieChainFixture fixture;
fixture.setNormalizationForkHeight(2);
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 1);
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "2", 2);
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "a", "3", 3);
fixture.IncrementBlocks(1);
BOOST_CHECK(is_best_claim("A", tx2));
BOOST_CHECK(is_best_claim("a", tx3));
fixture.IncrementBlocks(1);
BOOST_CHECK(!is_best_claim("A", tx2));
BOOST_CHECK(is_best_claim("a", tx3));
BOOST_CHECK(pclaimTrie->getClaimsForName("a").size() == 3U);
fixture.DecrementBlocks(1);
BOOST_CHECK(is_best_claim("A", tx2));
BOOST_CHECK(is_best_claim("a", tx3));
}
BOOST_AUTO_TEST_CASE(normalization_does_not_kill_expirations) {
ClaimTrieChainFixture fixture;
pclaimTrie->setExpirationTime(3);
fixture.setNormalizationForkHeight(4);
// need to see that claims expiring on the frame when we normalize aren't kept
// need to see that supports expiring on the frame when we normalize aren't kept
// need to see that claims & supports carried through the normalization fork do expire
// and that they come back correctly when we roll backwards
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 1);
fixture.MakeSupport(fixture.GetCoinbase(), tx1, "A", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("A", 2));
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "B", "1", 1);
fixture.MakeSupport(fixture.GetCoinbase(), tx2, "B", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("A", 2));
BOOST_CHECK(best_claim_effective_amount_equals("B", 2));
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "C", "1", 1);
fixture.MakeSupport(fixture.GetCoinbase(), tx3, "C", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("A", 2));
BOOST_CHECK(best_claim_effective_amount_equals("B", 2));
BOOST_CHECK(best_claim_effective_amount_equals("C", 2));
CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "D", "1", 1);
fixture.MakeSupport(fixture.GetCoinbase(), tx4, "D", 1);
fixture.IncrementBlocks(1);
BOOST_CHECK(!best_claim_effective_amount_equals("a", 2));
BOOST_CHECK(best_claim_effective_amount_equals("b", 2));
BOOST_CHECK(best_claim_effective_amount_equals("c", 2));
BOOST_CHECK(best_claim_effective_amount_equals("d", 2));
fixture.IncrementBlocks(1);
BOOST_CHECK(!best_claim_effective_amount_equals("a", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("b", 2));
BOOST_CHECK(best_claim_effective_amount_equals("c", 2));
BOOST_CHECK(best_claim_effective_amount_equals("d", 2));
fixture.IncrementBlocks(1);
BOOST_CHECK(!best_claim_effective_amount_equals("a", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("b", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("c", 2));
BOOST_CHECK(best_claim_effective_amount_equals("d", 2));
fixture.IncrementBlocks(1);
BOOST_CHECK(!best_claim_effective_amount_equals("a", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("b", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("c", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("d", 2));
fixture.DecrementBlocks(2);
BOOST_CHECK(!best_claim_effective_amount_equals("a", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("b", 2));
BOOST_CHECK(best_claim_effective_amount_equals("c", 2));
BOOST_CHECK(best_claim_effective_amount_equals("d", 2));
fixture.DecrementBlocks(1);
BOOST_CHECK(!best_claim_effective_amount_equals("a", 2));
BOOST_CHECK(best_claim_effective_amount_equals("b", 2));
BOOST_CHECK(best_claim_effective_amount_equals("c", 2));
BOOST_CHECK(best_claim_effective_amount_equals("d", 2));
fixture.DecrementBlocks(1);
BOOST_CHECK(best_claim_effective_amount_equals("A", 2));
BOOST_CHECK(best_claim_effective_amount_equals("B", 2));
BOOST_CHECK(best_claim_effective_amount_equals("C", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("d", 2));
fixture.IncrementBlocks(3);
BOOST_CHECK(!best_claim_effective_amount_equals("a", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("b", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("c", 2));
BOOST_CHECK(!best_claim_effective_amount_equals("d", 2)); // (not re-added)
}
/*
@ -3368,14 +3732,14 @@ BOOST_AUTO_TEST_CASE(getclaimsintrie_test)
UniValue results = getclaimsintrie(params, false);
BOOST_CHECK(results.size() == 2U);
BOOST_CHECK(results[0]["name"].get_str() == sName1);
BOOST_CHECK(results[1]["name"].get_str() == sName2);
BOOST_CHECK(results[0]["normalized_name"].get_str() == sName1);
BOOST_CHECK(results[1]["normalized_name"].get_str() == sName2);
params.push_back(blockHash.GetHex());
results = getclaimsintrie(params, false);
BOOST_CHECK(results.size() == 1U);
BOOST_CHECK(results[0]["name"].get_str() == sName1);
BOOST_CHECK(results[0]["normalized_name"].get_str() == sName1);
}
BOOST_AUTO_TEST_CASE(getclaimsintrie_test2)
@ -3493,12 +3857,10 @@ BOOST_AUTO_TEST_CASE(getclaimsforname_test)
UniValue results = getclaimsforname(params, false);
UniValue claims = results["claims"];
BOOST_CHECK(claims.size() == 2U);
BOOST_CHECK(claims.size() == 1U);
BOOST_CHECK(results["nLastTakeoverHeight"].get_int() == height + 1);
BOOST_CHECK(claims[0]["nEffectiveAmount"].get_int() == 0);
BOOST_CHECK(claims[1]["nEffectiveAmount"].get_int() == 2);
BOOST_CHECK(claims[0]["nEffectiveAmount"].get_int() == 2);
BOOST_CHECK(claims[0]["supports"].size() == 0U);
BOOST_CHECK(claims[1]["supports"].size() == 0U);
fixture.IncrementBlocks(1);

View file

@ -39,6 +39,14 @@ public:
return cache.find(key);
}
bool insertClaimIntoTrie(const std::string& name, CClaimValue claim,
bool fCheckTakeover = false) const {
return CClaimTrieCache::insertClaimIntoTrie(name, claim, fCheckTakeover);
}
bool removeClaimFromTrie(const std::string& name, const COutPoint& outPoint,
CClaimValue& claim, bool fCheckTakeover = false) const {
return CClaimTrieCache::removeClaimFromTrie(name, outPoint, claim, fCheckTakeover);
}
};
CMutableTransaction BuildTransaction(const uint256& prevhash)
@ -106,7 +114,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
BOOST_CHECK(pclaimTrie->empty());
CClaimTrieCache ntState(pclaimTrie, false);
CClaimTrieCacheTest ntState(pclaimTrie);
ntState.insertClaimIntoTrie(std::string("test"), CClaimValue(tx1OutPoint, hash160, 50, 100, 200));
ntState.insertClaimIntoTrie(std::string("test2"), CClaimValue(tx2OutPoint, hash160, 50, 100, 200));
@ -127,7 +135,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2);
BOOST_CHECK(pclaimTrie->checkConsistency());
CClaimTrieCache ntState1(pclaimTrie, false);
CClaimTrieCacheTest ntState1(pclaimTrie);
ntState1.removeClaimFromTrie(std::string("test"), tx1OutPoint, unused);
ntState1.removeClaimFromTrie(std::string("test2"), tx2OutPoint, unused);
ntState1.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused);
@ -135,7 +143,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
BOOST_CHECK(ntState1.getMerkleHash() == hash0);
CClaimTrieCache ntState2(pclaimTrie, false);
CClaimTrieCacheTest ntState2(pclaimTrie);
ntState2.insertClaimIntoTrie(std::string("abab"), CClaimValue(tx6OutPoint, hash160, 50, 100, 200));
ntState2.removeClaimFromTrie(std::string("test"), tx1OutPoint, unused);
@ -147,7 +155,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash3);
BOOST_CHECK(pclaimTrie->checkConsistency());
CClaimTrieCache ntState3(pclaimTrie, false);
CClaimTrieCacheTest ntState3(pclaimTrie);
ntState3.insertClaimIntoTrie(std::string("test"), CClaimValue(tx1OutPoint, hash160, 50, 100, 200));
BOOST_CHECK(ntState3.getMerkleHash() == hash4);
ntState3.flush();
@ -155,7 +163,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash4);
BOOST_CHECK(pclaimTrie->checkConsistency());
CClaimTrieCache ntState4(pclaimTrie, false);
CClaimTrieCacheTest ntState4(pclaimTrie);
ntState4.removeClaimFromTrie(std::string("abab"), tx6OutPoint, unused);
BOOST_CHECK(ntState4.getMerkleHash() == hash2);
ntState4.flush();
@ -163,7 +171,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2);
BOOST_CHECK(pclaimTrie->checkConsistency());
CClaimTrieCache ntState5(pclaimTrie, false);
CClaimTrieCacheTest ntState5(pclaimTrie);
ntState5.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused);
BOOST_CHECK(ntState5.getMerkleHash() == hash2);
@ -172,7 +180,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2);
BOOST_CHECK(pclaimTrie->checkConsistency());
CClaimTrieCache ntState6(pclaimTrie, false);
CClaimTrieCacheTest ntState6(pclaimTrie);
ntState6.insertClaimIntoTrie(std::string("test"), CClaimValue(tx3OutPoint, hash160, 50, 101, 201));
BOOST_CHECK(ntState6.getMerkleHash() == hash2);
@ -181,7 +189,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2);
BOOST_CHECK(pclaimTrie->checkConsistency());
CClaimTrieCache ntState7(pclaimTrie, false);
CClaimTrieCacheTest ntState7(pclaimTrie);
ntState7.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused);
ntState7.removeClaimFromTrie(std::string("test"), tx1OutPoint, unused);
ntState7.removeClaimFromTrie(std::string("tes"), tx4OutPoint, unused);
@ -201,7 +209,6 @@ BOOST_AUTO_TEST_CASE(basic_insertion_info_test)
CClaimTrieCacheTest ctc(pclaimTrie);
// create and insert claim
CClaimValue unused;
uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
CMutableTransaction tx1 = BuildTransaction(hash0);
uint160 claimId = ClaimIdHash(tx1.GetHash(), 0);
@ -270,8 +277,8 @@ BOOST_AUTO_TEST_CASE(recursive_prune_test)
BOOST_CHECK_EQUAL(1, cc.cacheSize());
nodeCacheType::iterator it = cc.getCache(std::string("t"));
BOOST_CHECK_EQUAL(10, it->second->nHeightOfLastTakeover);
BOOST_CHECK_EQUAL(1, it->second->claims.size());
BOOST_CHECK_EQUAL(0, it->second->children.size());
BOOST_CHECK_EQUAL(1U, it->second->claims.size());
BOOST_CHECK_EQUAL(0U, it->second->children.size());
}
BOOST_AUTO_TEST_CASE(iteratetrie_test)

View file

@ -68,7 +68,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
pblocktree = new CBlockTreeDB(1 << 20, true);
pcoinsdbview = new CCoinsViewDB(1 << 23, true);
pcoinsTip = new CCoinsViewCache(pcoinsdbview);
pclaimTrie = new CClaimTrie(true, false, false, 1);
pclaimTrie = new CClaimTrie(true, false, 1);
InitBlockIndex(chainparams);
#ifdef ENABLE_WALLET
bool fFirstRun;