Rebase LBRY on top of Bitcoin 0.17 #263
59 changed files with 6844 additions and 2063 deletions
37
configure.ac
37
configure.ac
|
@ -146,6 +146,12 @@ AC_ARG_WITH([qrencode],
|
|||
[use_qr=$withval],
|
||||
[use_qr=auto])
|
||||
|
||||
AC_ARG_WITH([icu],
|
||||
[AS_HELP_STRING([--with-icu],
|
||||
[Required ICU root path])],
|
||||
[ICU_PREFIX=$withval],
|
||||
[ICU_PREFIX=auto])
|
||||
|
||||
AC_ARG_ENABLE([hardening],
|
||||
[AS_HELP_STRING([--disable-hardening],
|
||||
[do not attempt to harden the resulting executables (default is to harden when possible)])],
|
||||
|
@ -640,6 +646,7 @@ if test x$ac_cv_sys_large_files != x &&
|
|||
CPPFLAGS="$CPPFLAGS -D_LARGE_FILES=$ac_cv_sys_large_files"
|
||||
fi
|
||||
|
||||
AX_CHECK_LINK_FLAG([[-static-libstdc++]], [LDFLAGS="$LDFLAGS -static-libstdc++"])
|
||||
AX_CHECK_LINK_FLAG([[-Wl,--large-address-aware]], [LDFLAGS="$LDFLAGS -Wl,--large-address-aware"])
|
||||
|
||||
AX_GCC_FUNC_ATTRIBUTE([visibility])
|
||||
|
@ -895,6 +902,7 @@ AX_BOOST_SYSTEM
|
|||
AX_BOOST_FILESYSTEM
|
||||
AX_BOOST_THREAD
|
||||
AX_BOOST_CHRONO
|
||||
AX_BOOST_LOCALE
|
||||
|
||||
dnl Boost 1.56 through 1.62 allow using std::atomic instead of its own atomic
|
||||
dnl counter implementations. In 1.63 and later the std::atomic approach is default.
|
||||
|
@ -961,7 +969,7 @@ fi
|
|||
|
||||
if test x$use_boost = xyes; then
|
||||
|
||||
BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB $BOOST_THREAD_LIB $BOOST_CHRONO_LIB"
|
||||
BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB $BOOST_PROGRAM_OPTIONS_LIB $BOOST_THREAD_LIB $BOOST_CHRONO_LIB $BOOST_LOCALE_LIB"
|
||||
|
||||
|
||||
dnl If boost (prior to 1.57) was built without c++11, it emulated scoped enums
|
||||
|
@ -1057,6 +1065,16 @@ if test x$use_pkgconfig = xyes; then
|
|||
m4_ifdef(
|
||||
[PKG_CHECK_MODULES],
|
||||
[
|
||||
ICU_CPPFLAGS="-I$ICU_PREFIX/include"
|
||||
CPPFLAGS="$ICU_CPPFLAGS $CPPFLAGS"
|
||||
ICU_LIBS="-L$ICU_PREFIX/lib -licui18n -licuuc -licudata -ldl"
|
||||
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 -ldl",
|
||||
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.)])
|
||||
BITCOIN_QT_CHECK([PKG_CHECK_MODULES([PROTOBUF], [protobuf], [have_protobuf=yes], [BITCOIN_QT_FAIL(libprotobuf not found)])])
|
||||
|
@ -1082,6 +1100,18 @@ if test x$use_pkgconfig = xyes; then
|
|||
]
|
||||
)
|
||||
else
|
||||
ICU_CPPFLAGS="-I$ICU_PREFIX/include"
|
||||
CPPFLAGS="$ICU_CPPFLAGS $CPPFLAGS"
|
||||
ICU_LIBS="-L$ICU_PREFIX/lib -licui18n -licuuc -licudata -ldl"
|
||||
|
||||
AC_MSG_WARN([Using ICU_CPPFLAGS $ICU_CPPFLAGS])
|
||||
AC_MSG_WARN([Using ICU_LIBS $ICU_LIBS])
|
||||
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 -ldl",
|
||||
AC_CHECK_LIB([icu18n], [main],ICU_LIBS=$ICU_LIBS, ICU_LIBS="-L$ICU_PREFIX/lib -lsicudt -lsicuin -lsicuio -lsicule -lsiculx -lsicutest -lsicutu -lsicuuc"))
|
||||
|
||||
AC_CHECK_HEADER([openssl/crypto.h],,AC_MSG_ERROR(libcrypto headers missing))
|
||||
AC_CHECK_LIB([crypto], [main],CRYPTO_LIBS=-lcrypto, AC_MSG_ERROR(libcrypto missing))
|
||||
|
||||
|
@ -1385,6 +1415,9 @@ 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)
|
||||
AC_SUBST(LEVELDB_TARGET_FLAGS)
|
||||
AC_SUBST(MINIUPNPC_CPPFLAGS)
|
||||
|
@ -1431,7 +1464,7 @@ if test x$need_bundled_univalue = xyes; then
|
|||
AC_CONFIG_SUBDIRS([src/univalue])
|
||||
fi
|
||||
|
||||
ac_configure_args="${ac_configure_args} --disable-shared --with-pic --with-bignum=no --enable-module-recovery --disable-jni"
|
||||
ac_configure_args="${ac_configure_args} --enable-static --disable-shared --with-pic --with-bignum=no --enable-module-recovery --disable-jni"
|
||||
AC_CONFIG_SUBDIRS([src/secp256k1])
|
||||
|
||||
AC_OUTPUT
|
||||
|
|
457
reproducible_build.sh
Executable file
457
reproducible_build.sh
Executable file
|
@ -0,0 +1,457 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -xeuo pipefail
|
||||
|
||||
function HELP {
|
||||
echo "Build lbrycrd"
|
||||
echo "-----"
|
||||
echo "When run without any arguments, this script expects the current directory"
|
||||
echo "to be the lbrycrd repo and it builds what is in that directory"
|
||||
echo
|
||||
echo "This is a long build process so it can be split into two parts"
|
||||
echo "Specify the -d flag to build only the dependencies"
|
||||
echo "and the -l flag to build only lbrycrd. This will fail"
|
||||
echo "if the dependencies weren't built earlier"
|
||||
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"
|
||||
echo "-d: build only the dependencies"
|
||||
echo "-o: timeout build after 40 minutes"
|
||||
echo "-t: turn trace on"
|
||||
echo "-h: show help"
|
||||
exit 1
|
||||
}
|
||||
|
||||
CLONE=true
|
||||
CLEAN=false
|
||||
CHECK_CODE_FORMAT=false
|
||||
BUILD_DEPENDENCIES=true
|
||||
BUILD_LBRYCRD=true
|
||||
TIMEOUT=false
|
||||
THREE_MB=3145728
|
||||
# this flag gets set to False if
|
||||
# the script exits due to a timeout
|
||||
OUTPUT_LOG=true
|
||||
|
||||
while getopts :crfldoth:w:d: FLAG; do
|
||||
case $FLAG in
|
||||
c)
|
||||
CLONE=false
|
||||
;;
|
||||
r)
|
||||
CLEAN=true
|
||||
;;
|
||||
f)
|
||||
CHECK_CODE_FORMAT=true
|
||||
;;
|
||||
l)
|
||||
BUILD_DEPENDENCIES=false
|
||||
;;
|
||||
d)
|
||||
BUILD_LBRYCRD=false
|
||||
;;
|
||||
o)
|
||||
TIMEOUT=true
|
||||
;;
|
||||
t)
|
||||
set -o xtrace
|
||||
;;
|
||||
h)
|
||||
HELP
|
||||
;;
|
||||
\?) #unrecognized option - show help
|
||||
echo "Option -$OPTARG not allowed."
|
||||
HELP
|
||||
;;
|
||||
:)
|
||||
echo "Option -$OPTARG requires an argument."
|
||||
HELP
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND-1))
|
||||
|
||||
SUDO=''
|
||||
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
|
||||
fi
|
||||
|
||||
if [ -z "${TRAVIS_OS_NAME+x}" ]; then
|
||||
if [ "$(uname -s)" = "Darwin" ]; then
|
||||
OS_NAME="osx"
|
||||
else
|
||||
OS_NAME="linux"
|
||||
fi
|
||||
else
|
||||
OS_NAME="${TRAVIS_OS_NAME}"
|
||||
fi
|
||||
|
||||
if [ -z "${TRAVIS_BUILD_DIR+x}" ]; then
|
||||
START_TIME_FILE="$PWD/start_time"
|
||||
else
|
||||
# if we are on travis (the primary use case for setting a timeout)
|
||||
# this file is created when the build starts
|
||||
START_TIME_FILE="$TRAVIS_BUILD_DIR/start_time"
|
||||
fi
|
||||
rm -f ${START_TIME_FILE}
|
||||
date +%s > ${START_TIME_FILE}
|
||||
|
||||
NEXT_TIME=60
|
||||
function exit_at_60() {
|
||||
if [ -f "${START_TIME_FILE}" ]; then
|
||||
NOW=$(date +%s)
|
||||
START=$(cat "${START_TIME_FILE}")
|
||||
TIMEOUT_SECS=3600 # 60 * 60
|
||||
TIME=$((NOW - START))
|
||||
if (( TIME > NEXT_TIME )); then
|
||||
echo "Build has taken $((TIME / 60)) minutes: $1"
|
||||
NEXT_TIME=$((TIME + 60))
|
||||
fi
|
||||
if [ "$TIMEOUT" = true ] && (( TIME > TIMEOUT_SECS )); then
|
||||
echo 'Exiting at 60 minutes to allow the cache to populate'
|
||||
OUTPUT_LOG=false
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# two arguments
|
||||
# - pid (probably from $!)
|
||||
# - 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
|
||||
# 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 &
|
||||
BACKGROUND_PID=$!
|
||||
wait_and_echo $BACKGROUND_PID "$3"
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
rv=$?
|
||||
# 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"
|
||||
echo
|
||||
fi
|
||||
# delete the build directory
|
||||
rm -rf "$1"
|
||||
echo "Build failed. Removing $1"
|
||||
exit $rv
|
||||
}
|
||||
|
||||
function cat_and_exit() {
|
||||
rv=$?
|
||||
# cat the log file if it exists
|
||||
if [ -f "$1" ] && [ "${OUTPUT_LOG}" = true ]; then
|
||||
echo
|
||||
echo "Output of log file $1"
|
||||
echo
|
||||
# This used to be the last 3MB but outputing that
|
||||
# caused problems on travis.
|
||||
# Hopefully the last 1000 lines is enough
|
||||
# to debug whatever went wrong
|
||||
tail -n 1000 "$1"
|
||||
echo
|
||||
fi
|
||||
exit $rv
|
||||
}
|
||||
|
||||
function brew_if_not_installed() {
|
||||
if ! brew ls | grep $1 --quiet; then
|
||||
brew install $1
|
||||
fi
|
||||
}
|
||||
|
||||
function install_brew_packages() {
|
||||
brew update > /dev/null
|
||||
brew unlink python
|
||||
brew_if_not_installed autoconf
|
||||
brew_if_not_installed automake
|
||||
# something weird happened where glibtoolize was failing to find
|
||||
# sed, and reinstalling fixes it.
|
||||
brew reinstall -s libtool
|
||||
brew_if_not_installed pkg-config
|
||||
brew_if_not_installed protobuf
|
||||
brew_if_not_installed gmp
|
||||
|
||||
if [ "${CHECK_CODE_FORMAT}" = true ]; then
|
||||
brew_if_not_installed clang-format
|
||||
fi
|
||||
}
|
||||
|
||||
function install_apt_packages() {
|
||||
if [ -z "${TRAVIS+x}" ]; then
|
||||
# if not on travis, its nice to see progress
|
||||
QUIET=""
|
||||
else
|
||||
QUIET="-qq"
|
||||
fi
|
||||
# get the required OS packages
|
||||
$SUDO apt-get ${QUIET} update
|
||||
$SUDO apt-get ${QUIET} install -y --no-install-recommends \
|
||||
build-essential python-dev libbz2-dev libtool \
|
||||
autotools-dev autoconf git pkg-config wget \
|
||||
ca-certificates automake bsdmainutils
|
||||
|
||||
if [ "${CHECK_CODE_FORMAT}" = true ]; then
|
||||
$SUDO apt-get ${QUIET} install -y --no-install-recommends \
|
||||
clang-format-3.4
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
function build_dependencies() {
|
||||
if [ "${OS_NAME}" = "osx" ]; then
|
||||
PARALLEL="-j $(sysctl -n hw.ncpu)"
|
||||
install_brew_packages
|
||||
else
|
||||
PARALLEL="-j $(grep -c processor /proc/cpuinfo)"
|
||||
install_apt_packages
|
||||
fi
|
||||
|
||||
if [ "$CLEAN" = true ]; then
|
||||
rm -rf "${LBRYCRD_DEPENDENCIES}"
|
||||
rm -rf "${OUTPUT_DIR}"
|
||||
fi
|
||||
|
||||
if [ ! -d "${LBRYCRD_DEPENDENCIES}" ]; then
|
||||
git clone https://github.com/lbrynaut/lbrycrd-dependencies.git "${LBRYCRD_DEPENDENCIES}"
|
||||
fi
|
||||
# TODO: if the repo exists, make sure its clean: revert to head.
|
||||
mkdir -p "${LOG_DIR}"
|
||||
|
||||
build_dependency "${OPENSSL_PREFIX}" "${LOG_DIR}/openssl_build.log" build_openssl
|
||||
build_dependency "${ICU_PREFIX}" "${LOG_DIR}/icu_build.log" build_icu
|
||||
build_dependency "${BDB_PREFIX}" "${LOG_DIR}/bdb_build.log" build_bdb
|
||||
|
||||
set +u
|
||||
export PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:${OPENSSL_PREFIX}/lib/pkgconfig/"
|
||||
set -u
|
||||
|
||||
build_dependency "${BOOST_PREFIX}" "${LOG_DIR}/boost_build.log" build_boost
|
||||
build_dependency "${LIBEVENT_PREFIX}" "${LOG_DIR}/libevent_build.log" build_libevent
|
||||
}
|
||||
|
||||
function build_bdb() {
|
||||
BDB_LOG="$1"
|
||||
if [ "${OS_NAME}" = "osx" ]; then
|
||||
patch db-4.8.30.NC/dbinc/atomic.h < atomic.patch
|
||||
fi
|
||||
cd db-4.8.30.NC/build_unix
|
||||
echo "Building bdb. tail -f $BDB_LOG to see the details and monitor progress"
|
||||
../dist/configure --prefix="${BDB_PREFIX}" --enable-cxx --disable-shared --with-pic > "${BDB_LOG}"
|
||||
background "make ${PARALLEL}" "${BDB_LOG}" "Waiting for bdb to finish building"
|
||||
make install >> "${BDB_LOG}" 2>&1
|
||||
}
|
||||
|
||||
function build_openssl() {
|
||||
OPENSSL_LOG="$1"
|
||||
mkdir -p "${OPENSSL_PREFIX}/ssl"
|
||||
cd openssl-1.0.1p
|
||||
echo "Building openssl. tail -f $OPENSSL_LOG to see the details and monitor progress"
|
||||
if [ "${OS_NAME}" = "osx" ]; then
|
||||
./Configure --prefix="${OPENSSL_PREFIX}" --openssldir="${OPENSSL_PREFIX}/ssl" \
|
||||
-fPIC darwin64-x86_64-cc \
|
||||
no-shared no-dso no-engines > "${OPENSSL_LOG}"
|
||||
else
|
||||
[[ $(uname -m) = 'i686' ]] && OS_ARCH="linux-generic32" || OS_ARCH="linux-x86_64"
|
||||
./Configure --prefix="${OPENSSL_PREFIX}" --openssldir="${OPENSSL_PREFIX}/ssl" \
|
||||
${OS_ARCH} -fPIC -static no-shared no-dso > "${OPENSSL_LOG}"
|
||||
fi
|
||||
background "make ${PARALLEL}" "${OPENSSL_LOG}" "Waiting for openssl to finish building"
|
||||
make install >> "${OPENSSL_LOG}" 2>&1
|
||||
}
|
||||
|
||||
function build_boost() {
|
||||
BOOST_LOG="$1"
|
||||
cd boost_1_67_0
|
||||
|
||||
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}"
|
||||
|
||||
echo "BOOST_ICU_LIBS: $BOOST_ICU_LIBS"
|
||||
echo "BOOST_LDFLAGS: $BOOST_ICU_LIBS"
|
||||
|
||||
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}"
|
||||
background "${b2cmd}" "${BOOST_LOG}" "Waiting for boost to finish building"
|
||||
}
|
||||
|
||||
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
|
||||
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-static --enable-shared --disable-extras --disable-icuio \
|
||||
--disable-layout --disable-layoutex --disable-tests --disable-samples
|
||||
if [ ! -z ${TARGET+x} ]; then
|
||||
TMP_TARGET="${TARGET}"
|
||||
unset TARGET
|
||||
fi
|
||||
set +e
|
||||
background "make ${PARALLEL} VERBOSE=1" "${ICU_LOG}" "Waiting for icu to finish building"
|
||||
make install >> "${ICU_LOG}" 2>&1
|
||||
if [ ! -z ${TARGET+x} ]; then
|
||||
TARGET="${TMP_TARGET}"
|
||||
fi
|
||||
set -e
|
||||
popd > /dev/null
|
||||
}
|
||||
|
||||
function build_libevent() {
|
||||
LIBEVENT_LOG="$1"
|
||||
if [ ! -d libevent ]; then
|
||||
git clone --branch release-2.0.22-stable https://github.com/libevent/libevent.git
|
||||
fi
|
||||
cd 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/" \
|
||||
CPPFLAGS="-I${OPENSSL_PREFIX}/include" >> "${LIBEVENT_LOG}" 2>&1
|
||||
background "make ${PARALLEL}" "${LIBEVENT_LOG}" "Waiting for libevent to finish building"
|
||||
make install >> "${LIBEVENT_LOG}"
|
||||
}
|
||||
|
||||
function build_dependency() {
|
||||
PREFIX=$1
|
||||
LOG=$2
|
||||
BUILD=$3
|
||||
if [ ! -d "${PREFIX}" ]; then
|
||||
trap 'cleanup "${PREFIX}" "${LOG}"' INT TERM EXIT
|
||||
cd "${LBRYCRD_DEPENDENCIES}"
|
||||
rm -rf ${PREFIX}
|
||||
mkdir -p "${PREFIX}"
|
||||
"${BUILD}" "${LOG}"
|
||||
trap - INT TERM EXIT
|
||||
fi
|
||||
}
|
||||
|
||||
function build_lbrycrd() {
|
||||
if [ "$CLONE" == true ]; then
|
||||
cd "${LBRYCRD_DEPENDENCIES}"
|
||||
git clone https://github.com/lbryio/lbrycrd
|
||||
cd lbrycrd
|
||||
else
|
||||
cd "${SOURCE_DIR}"
|
||||
fi
|
||||
./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++"
|
||||
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"
|
||||
else
|
||||
OPTIONS=""
|
||||
CPPFLAGS="-I${OPENSSL_PREFIX}/include -I${BDB_PREFIX}/include -I${LIBEVENT_PREFIX}/include/ -I${ICU_PREFIX}/include -Wno-unused-local-typedefs"
|
||||
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(){
|
||||
# run a code formatting check on any commits not in master
|
||||
# requires clang-format
|
||||
if ! git config remote.origin2.url > /dev/null; then
|
||||
git remote add origin2 https://github.com/lbryio/lbrycrd.git
|
||||
fi
|
||||
git fetch origin2
|
||||
git diff -U0 origin2/master -- '*.h' '*.cpp' | ./contrib/devtools/clang-format-diff.py -p1
|
||||
}
|
||||
|
||||
# these variables are needed in both functions
|
||||
LBRYCRD_DEPENDENCIES="$(pwd)/lbrycrd-dependencies"
|
||||
OUTPUT_DIR="$(pwd)/build"
|
||||
LOG_DIR="$(pwd)/logs"
|
||||
ICU_PREFIX="${OUTPUT_DIR}/icu"
|
||||
BDB_PREFIX="${OUTPUT_DIR}/bdb"
|
||||
OPENSSL_PREFIX="${OUTPUT_DIR}/openssl"
|
||||
BOOST_PREFIX="${OUTPUT_DIR}/boost"
|
||||
LIBEVENT_PREFIX="${OUTPUT_DIR}/libevent"
|
||||
|
||||
if [ "${BUILD_DEPENDENCIES}" = true ]; then
|
||||
build_dependencies
|
||||
fi
|
||||
|
||||
if [ "${CHECK_CODE_FORMAT}" = true ]; then
|
||||
LINES_W_FORMAT_REQUIRED=$(clang_format_diff | wc -l)
|
||||
if [ ${LINES_W_FORMAT_REQUIRED} -ne 0 ]; then
|
||||
echo "Failed to pass clang format diff: See below for the diff"
|
||||
clang_format_diff
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
set +u
|
||||
export PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:${OPENSSL_PREFIX}/lib/pkgconfig/:${LIBEVENT_PREFIX}/lib/pkgconfig/"
|
||||
set -u
|
||||
|
||||
if [ "${BUILD_LBRYCRD}" = true ]; then
|
||||
LBRYCRD_LOG="${LOG_DIR}/lbrycrd_build.log"
|
||||
echo "Building lbrycrd. tail -f ${LBRYCRD_LOG} to see the details and monitor progress"
|
||||
trap 'cat_and_exit "${LBRYCRD_LOG}"' INT TERM EXIT
|
||||
build_lbrycrd
|
||||
trap - INT TERM EXIT
|
||||
fi
|
|
@ -19,7 +19,7 @@ else
|
|||
LIBUNIVALUE = $(UNIVALUE_LIBS)
|
||||
endif
|
||||
|
||||
BITCOIN_INCLUDES=-I$(builddir) $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS)
|
||||
BITCOIN_INCLUDES=-I$(builddir) $(BDB_CPPFLAGS) $(ICU_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS) $(ICU_CFLAGS)
|
||||
|
||||
BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include
|
||||
BITCOIN_INCLUDES += $(UNIVALUE_CFLAGS)
|
||||
|
@ -102,6 +102,7 @@ BITCOIN_CORE_H = \
|
|||
chainparamsseeds.h \
|
||||
checkpoints.h \
|
||||
checkqueue.h \
|
||||
claimtrie.h \
|
||||
clientversion.h \
|
||||
coins.h \
|
||||
compat.h \
|
||||
|
@ -127,12 +128,14 @@ BITCOIN_CORE_H = \
|
|||
key.h \
|
||||
key_io.h \
|
||||
keystore.h \
|
||||
lbry.h \
|
||||
dbwrapper.h \
|
||||
limitedmap.h \
|
||||
logging.h \
|
||||
memusage.h \
|
||||
merkleblock.h \
|
||||
miner.h \
|
||||
nameclaim.h \
|
||||
net.h \
|
||||
net_processing.h \
|
||||
netaddress.h \
|
||||
|
@ -178,10 +181,12 @@ BITCOIN_CORE_H = \
|
|||
txdb.h \
|
||||
txmempool.h \
|
||||
ui_interface.h \
|
||||
uint256.h \
|
||||
undo.h \
|
||||
util.h \
|
||||
utilmemory.h \
|
||||
utilmoneystr.h \
|
||||
utilstrencodings.h \
|
||||
utiltime.h \
|
||||
validation.h \
|
||||
validationinterface.h \
|
||||
|
@ -221,6 +226,7 @@ libbitcoin_server_a_SOURCES = \
|
|||
blockencodings.cpp \
|
||||
chain.cpp \
|
||||
checkpoints.cpp \
|
||||
claimtrie.cpp \
|
||||
consensus/tx_verify.cpp \
|
||||
httprpc.cpp \
|
||||
httpserver.cpp \
|
||||
|
@ -228,8 +234,10 @@ libbitcoin_server_a_SOURCES = \
|
|||
index/txindex.cpp \
|
||||
init.cpp \
|
||||
dbwrapper.cpp \
|
||||
lbry.cpp \
|
||||
merkleblock.cpp \
|
||||
miner.cpp \
|
||||
nameclaim.cpp \
|
||||
net.cpp \
|
||||
net_processing.cpp \
|
||||
noui.cpp \
|
||||
|
@ -240,6 +248,7 @@ libbitcoin_server_a_SOURCES = \
|
|||
pow.cpp \
|
||||
rest.cpp \
|
||||
rpc/blockchain.cpp \
|
||||
rpc/claimtrie.cpp \
|
||||
rpc/mining.cpp \
|
||||
rpc/misc.cpp \
|
||||
rpc/net.cpp \
|
||||
|
@ -253,6 +262,8 @@ libbitcoin_server_a_SOURCES = \
|
|||
txdb.cpp \
|
||||
txmempool.cpp \
|
||||
ui_interface.cpp \
|
||||
uint256.cpp \
|
||||
utilstrencodings.cpp \
|
||||
validation.cpp \
|
||||
validationinterface.cpp \
|
||||
versionbits.cpp \
|
||||
|
@ -416,6 +427,7 @@ libbitcoin_util_a_SOURCES = \
|
|||
support/cleanse.cpp \
|
||||
sync.cpp \
|
||||
threadinterrupt.cpp \
|
||||
uint256.cpp \
|
||||
util.cpp \
|
||||
utilmoneystr.cpp \
|
||||
utilstrencodings.cpp \
|
||||
|
@ -441,7 +453,7 @@ nodist_libbitcoin_util_a_SOURCES = $(srcdir)/obj/build.h
|
|||
bitcoind_SOURCES = bitcoind.cpp
|
||||
bitcoind_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
||||
bitcoind_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||
bitcoind_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||
bitcoind_LDFLAGS = -L$(ICU_PREFIX)/lib $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||
|
||||
if TARGET_WINDOWS
|
||||
bitcoind_SOURCES += bitcoind-res.rc
|
||||
|
@ -461,7 +473,7 @@ bitcoind_LDADD = \
|
|||
$(LIBMEMENV) \
|
||||
$(LIBSECP256K1)
|
||||
|
||||
bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS)
|
||||
bitcoind_LDADD += $(BOOST_LIBS) $(ICU_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS)
|
||||
|
||||
# bitcoin-cli binary #
|
||||
bitcoin_cli_SOURCES = bitcoin-cli.cpp
|
||||
|
|
|
@ -55,8 +55,8 @@ if ENABLE_WALLET
|
|||
bench_bench_bitcoin_SOURCES += bench/coin_selection.cpp
|
||||
endif
|
||||
|
||||
bench_bench_bitcoin_LDADD += $(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)
|
||||
bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(ICU_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)
|
||||
|
||||
CLEAN_BITCOIN_BENCH = bench/*.gcda bench/*.gcno $(GENERATED_BENCH_FILES)
|
||||
|
||||
|
|
|
@ -409,9 +409,9 @@ if ENABLE_ZMQ
|
|||
qt_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
|
||||
endif
|
||||
qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \
|
||||
$(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
|
||||
$(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_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||
qt_bitcoin_qt_LDFLAGS = -L$(ICU_PREFIX)/lib $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||
qt_bitcoin_qt_LIBTOOLFLAGS = $(AM_LIBTOOLFLAGS) --tag CXX
|
||||
|
||||
#locale/foo.ts -> locale/foo.qm
|
||||
|
|
|
@ -64,9 +64,9 @@ qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
|
|||
endif
|
||||
qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) \
|
||||
$(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \
|
||||
$(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
|
||||
$(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(ICU_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
|
||||
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
|
||||
qt_test_test_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||
qt_test_test_bitcoin_qt_LDFLAGS = -L$(ICU_PREFIX)/lib $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||
qt_test_test_bitcoin_qt_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS)
|
||||
|
||||
CLEAN_BITCOIN_QT_TEST = $(TEST_QT_MOC_CPP) qt/test/*.gcda qt/test/*.gcno
|
||||
|
|
|
@ -61,6 +61,9 @@ BITCOIN_TESTS =\
|
|||
test/miner_tests.cpp \
|
||||
test/multisig_tests.cpp \
|
||||
test/net_tests.cpp \
|
||||
test/claimtriecache_tests.cpp \
|
||||
test/claimtriebranching_tests.cpp \
|
||||
test/nameclaim_tests.cpp \
|
||||
test/netbase_tests.cpp \
|
||||
test/pmt_tests.cpp \
|
||||
test/policyestimator_tests.cpp \
|
||||
|
@ -117,8 +120,8 @@ test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_C
|
|||
$(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS)
|
||||
test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||
|
||||
test_test_bitcoin_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS)
|
||||
test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static
|
||||
test_test_bitcoin_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(ICU_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS)
|
||||
test_test_bitcoin_LDFLAGS = -L$(ICU_PREFIX)/lib $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static
|
||||
|
||||
if ENABLE_ZMQ
|
||||
test_test_bitcoin_LDADD += $(ZMQ_LIBS)
|
||||
|
@ -143,7 +146,7 @@ test_test_bitcoin_fuzzy_LDADD = \
|
|||
$(LIBBITCOIN_CRYPTO_SHANI) \
|
||||
$(LIBSECP256K1)
|
||||
|
||||
test_test_bitcoin_fuzzy_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
|
||||
test_test_bitcoin_fuzzy_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) $(ICU_LIBS)
|
||||
#
|
||||
|
||||
nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES)
|
||||
|
|
|
@ -23,7 +23,7 @@ static const CAmount CENT = 1000000;
|
|||
* critical; in unusual circumstances like a(nother) overflow bug that allowed
|
||||
* for the creation of coins out of thin air modification could lead to a fork.
|
||||
* */
|
||||
static const CAmount MAX_MONEY = 21000000 * COIN;
|
||||
static const CAmount MAX_MONEY = 21000000000 * COIN;
|
||||
inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
|
||||
|
||||
#endif // BITCOIN_AMOUNT_H
|
||||
|
|
18
src/chain.h
18
src/chain.h
|
@ -209,6 +209,7 @@ public:
|
|||
//! block header
|
||||
int32_t nVersion;
|
||||
uint256 hashMerkleRoot;
|
||||
uint256 hashClaimTrie;
|
||||
uint32_t nTime;
|
||||
uint32_t nBits;
|
||||
uint32_t nNonce;
|
||||
|
@ -237,6 +238,7 @@ public:
|
|||
|
||||
nVersion = 0;
|
||||
hashMerkleRoot = uint256();
|
||||
hashClaimTrie = uint256();
|
||||
nTime = 0;
|
||||
nBits = 0;
|
||||
nNonce = 0;
|
||||
|
@ -253,6 +255,7 @@ public:
|
|||
|
||||
nVersion = block.nVersion;
|
||||
hashMerkleRoot = block.hashMerkleRoot;
|
||||
hashClaimTrie = block.hashClaimTrie;
|
||||
nTime = block.nTime;
|
||||
nBits = block.nBits;
|
||||
nNonce = block.nNonce;
|
||||
|
@ -283,6 +286,7 @@ public:
|
|||
if (pprev)
|
||||
block.hashPrevBlock = pprev->GetBlockHash();
|
||||
block.hashMerkleRoot = hashMerkleRoot;
|
||||
block.hashClaimTrie = hashClaimTrie;
|
||||
block.nTime = nTime;
|
||||
block.nBits = nBits;
|
||||
block.nNonce = nNonce;
|
||||
|
@ -294,6 +298,11 @@ public:
|
|||
return *phashBlock;
|
||||
}
|
||||
|
||||
uint256 GetBlockPoWHash() const
|
||||
{
|
||||
return GetBlockHeader().GetPoWHash();
|
||||
}
|
||||
|
||||
int64_t GetBlockTime() const
|
||||
{
|
||||
return (int64_t)nTime;
|
||||
|
@ -322,9 +331,10 @@ public:
|
|||
|
||||
std::string ToString() const
|
||||
{
|
||||
return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
|
||||
return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, claimtrie=%s, hashBlock=%s)",
|
||||
pprev, nHeight,
|
||||
hashMerkleRoot.ToString(),
|
||||
hashClaimTrie.ToString(),
|
||||
GetBlockHash().ToString());
|
||||
}
|
||||
|
||||
|
@ -402,6 +412,7 @@ public:
|
|||
READWRITE(this->nVersion);
|
||||
READWRITE(hashPrev);
|
||||
READWRITE(hashMerkleRoot);
|
||||
READWRITE(hashClaimTrie);
|
||||
READWRITE(nTime);
|
||||
READWRITE(nBits);
|
||||
READWRITE(nNonce);
|
||||
|
@ -413,19 +424,20 @@ public:
|
|||
block.nVersion = nVersion;
|
||||
block.hashPrevBlock = hashPrev;
|
||||
block.hashMerkleRoot = hashMerkleRoot;
|
||||
block.hashClaimTrie = hashClaimTrie;
|
||||
block.nTime = nTime;
|
||||
block.nBits = nBits;
|
||||
block.nNonce = nNonce;
|
||||
return block.GetHash();
|
||||
}
|
||||
|
||||
|
||||
std::string ToString() const
|
||||
{
|
||||
std::string str = "CDiskBlockIndex(";
|
||||
str += CBlockIndex::ToString();
|
||||
str += strprintf("\n hashBlock=%s, hashPrev=%s)",
|
||||
str += strprintf("\n hashBlock=%s, hashClaimTrie=%s, hashPrev=%s)",
|
||||
GetBlockHash().ToString(),
|
||||
hashClaimTrie.ToString(),
|
||||
hashPrev.ToString());
|
||||
return str;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,38 @@
|
|||
|
||||
#include <chainparamsseeds.h>
|
||||
|
||||
//#define FIND_GENESIS
|
||||
|
||||
#define GENESIS_MERKLE_ROOT "b8211c82c3d15bcd78bba57005b86fed515149a53a425eb592c07af99fe559cc"
|
||||
|
||||
#define MAINNET_GENESIS_HASH "9c89283ba0f3227f6c03b70216b9f665f0118d5e0fa729cedf4fb34d6a34f463"
|
||||
#define MAINNET_GENESIS_NONCE 1287
|
||||
|
||||
#define TESTNET_GENESIS_HASH "9c89283ba0f3227f6c03b70216b9f665f0118d5e0fa729cedf4fb34d6a34f463"
|
||||
#define TESTNET_GENESIS_NONCE 1287
|
||||
|
||||
#define REGTEST_GENESIS_HASH "6e3fcf1299d4ec5d79c3a4c91d624a4acf9e2e173d95a1a0504f677669687556"
|
||||
#define REGTEST_GENESIS_NONCE 1
|
||||
|
||||
bool CheckProofOfWork2(uint256 hash, unsigned int nBits, const Consensus::Params& params)
|
||||
{
|
||||
bool fNegative;
|
||||
bool fOverflow;
|
||||
arith_uint256 bnTarget;
|
||||
|
||||
bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
|
||||
|
||||
// Check range
|
||||
if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit))
|
||||
return error("CheckProofOfWork(): nBits below minimum work");
|
||||
|
||||
// Check proof of work matches claimed amount
|
||||
if (UintToArith256(hash) > bnTarget)
|
||||
return error("CheckProofOfWork(): hash doesn't match nBits");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward)
|
||||
{
|
||||
CMutableTransaction txNew;
|
||||
|
@ -22,6 +54,9 @@ static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesi
|
|||
txNew.vout.resize(1);
|
||||
txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << std::vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
|
||||
txNew.vout[0].nValue = genesisReward;
|
||||
//txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
|
||||
//txNew.vout[0].scriptPubKey = CScript() << ParseHex("0425caecb9fbf6cf50979644e85c11e3ec9007fd477fab9683648c6539e59b59c3a4d9b9c0b552c37eee6476f3e0d8425ac0346fe69ad61628b8c340d42fbfa3fd") << OP_CHECKSIG;
|
||||
//txNew.vout[0].scriptPubKey = CScript() << OP_DUP << OP_HASH160 << ParseHex("e5ff2d9e3a254622ae493573169c0fa94c82fe4f") << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||
txNew.vout[0].scriptPubKey = genesisOutputScript;
|
||||
|
||||
CBlock genesis;
|
||||
|
@ -32,6 +67,21 @@ static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesi
|
|||
genesis.vtx.push_back(MakeTransactionRef(std::move(txNew)));
|
||||
genesis.hashPrevBlock.SetNull();
|
||||
genesis.hashMerkleRoot = BlockMerkleRoot(genesis);
|
||||
genesis.hashClaimTrie = uint256S("0x0000000000000000000000000000000000000000000000000000000000000001");
|
||||
|
||||
#ifdef FIND_GENESIS
|
||||
while (true)
|
||||
{
|
||||
genesis.nNonce += 1;
|
||||
if (CheckProofOfWork2(genesis.GetPoWHash(), nBits, consensus))
|
||||
{
|
||||
std::cout << "nonce: " << genesis.nNonce << std::endl;
|
||||
std::cout << "hex: " << genesis.GetHash().GetHex() << std::endl;
|
||||
std::cout << "pow hash: " << genesis.GetPoWHash().GetHex() << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return genesis;
|
||||
}
|
||||
|
||||
|
@ -48,8 +98,8 @@ static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesi
|
|||
*/
|
||||
static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward)
|
||||
{
|
||||
const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
|
||||
const CScript genesisOutputScript = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
|
||||
const char* pszTimestamp = "insert timestamp string";//"The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
|
||||
const CScript genesisOutputScript = CScript() << OP_DUP << OP_HASH160 << ParseHex("345991dbf57bfb014b87006acdfafbfc5fe8292f") << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||
return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nNonce, nBits, nVersion, genesisReward);
|
||||
}
|
||||
|
||||
|
@ -73,16 +123,23 @@ void CChainParams::UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64
|
|||
class CMainParams : public CChainParams {
|
||||
public:
|
||||
CMainParams() {
|
||||
strNetworkID = "main";
|
||||
consensus.nSubsidyHalvingInterval = 210000;
|
||||
strNetworkID = "lbrycrd";
|
||||
consensus.nSubsidyLevelInterval = 1<<5;
|
||||
consensus.nMajorityEnforceBlockUpgrade = 750;
|
||||
consensus.nMajorityRejectBlockOutdated = 950;
|
||||
consensus.nMajorityWindow = 1000;
|
||||
consensus.BIP16Exception = uint256S("0x00000000000002dc756eebf4f49723ed8d30cc28a5f108eb94b1ba88ac4f9c22");
|
||||
consensus.BIP34Height = 227931;
|
||||
consensus.BIP34Hash = uint256S("0x000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8");
|
||||
consensus.BIP65Height = 388381; // 000000000000000004c2b624ed5d7756c508d90fd0da2c7c679febfa6c4735f0
|
||||
consensus.BIP66Height = 363725; // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931
|
||||
consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
||||
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
|
||||
consensus.nPowTargetSpacing = 10 * 60;
|
||||
consensus.BIP34Height = 1;
|
||||
consensus.BIP34Hash = uint256S("0xdecb9e2cca03a419fd9cca0cb2b1d5ad11b088f22f8f38556d93ac4358b86c24");
|
||||
consensus.BIP65Height = 1;
|
||||
consensus.BIP66Height = 1;
|
||||
consensus.powLimit = uint256S("0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
||||
consensus.nPowTargetTimespan = 150; //retarget every block
|
||||
consensus.nPowTargetSpacing = 150;
|
||||
consensus.nOriginalClaimExpirationTime = 262974;
|
||||
consensus.nExtendedClaimExpirationTime = 2102400;
|
||||
consensus.nExtendedClaimExpirationForkHeight = 400155;
|
||||
consensus.nNormalizedNameForkHeight = 1000000; // FIXME: pick a real fork height
|
||||
consensus.fPowAllowMinDifficultyBlocks = false;
|
||||
consensus.fPowNoRetargeting = false;
|
||||
consensus.nRuleChangeActivationThreshold = 1916; // 95% of 2016
|
||||
|
@ -98,82 +155,77 @@ public:
|
|||
|
||||
// Deployment of SegWit (BIP141, BIP143, and BIP147)
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1479168000; // November 15th, 2016.
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1510704000; // November 15th, 2017.
|
||||
// FIXME: Update times
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1634352575; //1479168000; // November 15th, 2016.
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1634352575; //1510704000; // November 15th, 2017.
|
||||
|
||||
// The best chain should have at least this much work.
|
||||
consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000028822fef1c230963535a90d");
|
||||
consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000000607ca7e806c4c1e9"); //400000
|
||||
|
||||
// By default assume that the signatures in ancestors of this block are valid.
|
||||
consensus.defaultAssumeValid = uint256S("0x0000000000000000002e63058c023a9a1de233554f28c7b21380b6c9003f36a8"); //534292
|
||||
//consensus.defaultAssumeValid = uint256S("0xf0e56e70782af63ccb49c76e852540688755869ba59ec68cac9c04a6b4d9f5ca"); //400000
|
||||
consensus.defaultAssumeValid = uint256S("0xa6bbb48f5343eb9b0287c22f3ea8b29f36cf10794a37f8a925a894d6f4519913"); //4000
|
||||
|
||||
/**
|
||||
* The message start string is designed to be unlikely to occur in normal data.
|
||||
* The characters are rarely used upper ASCII, not valid as UTF-8, and produce
|
||||
* a large 32-bit integer with any alignment.
|
||||
*/
|
||||
pchMessageStart[0] = 0xf9;
|
||||
pchMessageStart[1] = 0xbe;
|
||||
pchMessageStart[2] = 0xb4;
|
||||
pchMessageStart[3] = 0xd9;
|
||||
nDefaultPort = 8333;
|
||||
pchMessageStart[0] = 0xfa;
|
||||
pchMessageStart[1] = 0xe4;
|
||||
pchMessageStart[2] = 0xaa;
|
||||
pchMessageStart[3] = 0xf1;
|
||||
nDefaultPort = 9246;
|
||||
nPruneAfterHeight = 100000;
|
||||
|
||||
genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, 50 * COIN);
|
||||
genesis = CreateGenesisBlock(1446058291, MAINNET_GENESIS_NONCE, 0x1f00ffff, 1, 400000000 * COIN);
|
||||
consensus.hashGenesisBlock = genesis.GetHash();
|
||||
assert(consensus.hashGenesisBlock == uint256S("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"));
|
||||
assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
|
||||
#ifdef FIND_GENESIS
|
||||
std::cout << "hex: " << consensus.hashGenesisBlock.GetHex() << std::endl;
|
||||
std::cout << "merkle root: " << genesis.hashMerkleRoot.GetHex() << std::endl;
|
||||
#else
|
||||
assert(consensus.hashGenesisBlock == uint256S(MAINNET_GENESIS_HASH));
|
||||
assert(genesis.hashMerkleRoot == uint256S(GENESIS_MERKLE_ROOT));
|
||||
#endif
|
||||
vSeeds.clear();
|
||||
vFixedSeeds.clear();
|
||||
|
||||
// Note that of those which support the service bits prefix, most only support a subset of
|
||||
// possible options.
|
||||
// This is fine at runtime as we'll fall back to using them as a oneshot if they don't support the
|
||||
// service bits we want, but we should get them updated to support all service bits wanted by any
|
||||
// release ASAP to avoid it where possible.
|
||||
vSeeds.emplace_back("seed.bitcoin.sipa.be"); // Pieter Wuille, only supports x1, x5, x9, and xd
|
||||
vSeeds.emplace_back("dnsseed.bluematt.me"); // Matt Corallo, only supports x9
|
||||
vSeeds.emplace_back("dnsseed.bitcoin.dashjr.org"); // Luke Dashjr
|
||||
vSeeds.emplace_back("seed.bitcoinstats.com"); // Christian Decker, supports x1 - xf
|
||||
vSeeds.emplace_back("seed.bitcoin.jonasschnelli.ch"); // Jonas Schnelli, only supports x1, x5, x9, and xd
|
||||
vSeeds.emplace_back("seed.btc.petertodd.org"); // Peter Todd, only supports x1, x5, x9, and xd
|
||||
vSeeds.emplace_back("seed.bitcoin.sprovoost.nl"); // Sjors Provoost
|
||||
vSeeds.emplace_back("dnsseed1.lbry.io"); // lbry.io
|
||||
vSeeds.emplace_back("dnsseed2.lbry.io"); // lbry.io
|
||||
vSeeds.emplace_back("dnsseed3.lbry.io"); // lbry.io
|
||||
|
||||
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,0);
|
||||
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,5);
|
||||
base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,128);
|
||||
base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x88, 0xB2, 0x1E};
|
||||
base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x88, 0xAD, 0xE4};
|
||||
|
||||
bech32_hrp = "bc";
|
||||
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,0x55);
|
||||
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,0x7a);
|
||||
base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,0x1c);
|
||||
base58Prefixes[EXT_PUBLIC_KEY] = {0x01, 0x9c, 0x35, 0x4F};
|
||||
base58Prefixes[EXT_SECRET_KEY] = {0x01, 0x9c, 0x31, 0x18};
|
||||
|
||||
vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main));
|
||||
|
||||
/* bech32_hrp = "bc"; */
|
||||
bech32_hrp = "lb"; // FIXME: change this?
|
||||
|
||||
vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main));
|
||||
|
||||
fMiningRequiresPeers = true;
|
||||
fDefaultConsistencyChecks = false;
|
||||
fRequireStandard = true;
|
||||
fMineBlocksOnDemand = false;
|
||||
|
||||
// FIXME: update checkpoints?
|
||||
checkpointData = {
|
||||
{
|
||||
{ 11111, uint256S("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")},
|
||||
{ 33333, uint256S("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")},
|
||||
{ 74000, uint256S("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")},
|
||||
{105000, uint256S("0x00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97")},
|
||||
{134444, uint256S("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe")},
|
||||
{168000, uint256S("0x000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763")},
|
||||
{193000, uint256S("0x000000000000059f452a5f7340de6682a977387c17010ff6e6c3bd83ca8b1317")},
|
||||
{210000, uint256S("0x000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e")},
|
||||
{216116, uint256S("0x00000000000001b4f4b433e81ee46494af945cf96014816a4e2370f11b23df4e")},
|
||||
{225430, uint256S("0x00000000000001c108384350f74090433e7fcf79a606b8e797f065b130575932")},
|
||||
{250000, uint256S("0x000000000000003887df1f29024b06fc2200b55f8af8f35453d7be294df2d214")},
|
||||
{279000, uint256S("0x0000000000000001ae8c72a0b0c301f67e3afca10e819efa9041e458e9bd7e40")},
|
||||
{295000, uint256S("0x00000000000000004d9b4ef50f0f9d686fd69db2e03af35a100370c64632a983")},
|
||||
{ 4000, uint256S("0xa6bbb48f5343eb9b0287c22f3ea8b29f36cf10794a37f8a925a894d6f4519913") },
|
||||
}
|
||||
};
|
||||
|
||||
// FIXME:
|
||||
chainTxData = ChainTxData{
|
||||
// Data from rpc: getchaintxstats 4096 0000000000000000002e63058c023a9a1de233554f28c7b21380b6c9003f36a8
|
||||
/* nTime */ 1532884444,
|
||||
/* nTxCount */ 331282217,
|
||||
/* dTxRate */ 2.4
|
||||
1467272478, 4146, 600.0
|
||||
/* // Data from rpc: getchaintxstats 4096 0000000000000000002e63058c023a9a1de233554f28c7b21380b6c9003f36a8 */
|
||||
/* /\* nTime *\/ 1532884444, */
|
||||
/* /\* nTxCount *\/ 331282217, */
|
||||
/* /\* dTxRate *\/ 2.4 */
|
||||
};
|
||||
|
||||
/* disable fallback fee on mainnet */
|
||||
|
@ -187,18 +239,26 @@ public:
|
|||
class CTestNetParams : public CChainParams {
|
||||
public:
|
||||
CTestNetParams() {
|
||||
strNetworkID = "test";
|
||||
consensus.nSubsidyHalvingInterval = 210000;
|
||||
strNetworkID = "lbrycrdtest";
|
||||
consensus.nSubsidyLevelInterval = 1 << 5;
|
||||
consensus.nMajorityEnforceBlockUpgrade = 51;
|
||||
consensus.nMajorityRejectBlockOutdated = 75;
|
||||
consensus.nMajorityWindow = 100;
|
||||
consensus.BIP16Exception = uint256S("0x00000000dd30457c001f4095d208cc1296b0eed002427aa599874af7a432b105");
|
||||
// FIXME: adjust heights
|
||||
consensus.BIP34Height = 21111;
|
||||
consensus.BIP34Hash = uint256S("0x0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8");
|
||||
consensus.BIP65Height = 581885; // 00000000007f6655f22f98e72ed80d8b06dc761d5da09df0fa1dc4be4f861eb6
|
||||
consensus.BIP66Height = 330776; // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182
|
||||
consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
||||
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
|
||||
consensus.nPowTargetSpacing = 10 * 60;
|
||||
consensus.powLimit = uint256S("0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
||||
consensus.nPowTargetTimespan = 150;
|
||||
consensus.nPowTargetSpacing = 150;
|
||||
consensus.nOriginalClaimExpirationTime = 262974;
|
||||
consensus.nExtendedClaimExpirationTime = 2102400;
|
||||
consensus.nExtendedClaimExpirationForkHeight = 278160;
|
||||
consensus.fPowAllowMinDifficultyBlocks = true;
|
||||
consensus.fPowNoRetargeting = false;
|
||||
consensus.nNormalizedNameForkHeight = 1000000; // FIXME: pick a real fork height
|
||||
consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains
|
||||
consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
|
||||
|
@ -216,30 +276,32 @@ public:
|
|||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1493596800; // May 1st 2017
|
||||
|
||||
// The best chain should have at least this much work.
|
||||
consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000007dbe94253893cbd463");
|
||||
consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000000000a0c3931735170");
|
||||
|
||||
// By default assume that the signatures in ancestors of this block are valid.
|
||||
consensus.defaultAssumeValid = uint256S("0x0000000000000037a8cd3e06cd5edbfe9dd1dbcc5dacab279376ef7cfc2b4c75"); //1354312
|
||||
|
||||
pchMessageStart[0] = 0x0b;
|
||||
pchMessageStart[1] = 0x11;
|
||||
pchMessageStart[2] = 0x09;
|
||||
pchMessageStart[3] = 0x07;
|
||||
nDefaultPort = 18333;
|
||||
pchMessageStart[0] = 0xfa;
|
||||
pchMessageStart[1] = 0xe4;
|
||||
pchMessageStart[2] = 0xaa;
|
||||
pchMessageStart[3] = 0xe1;
|
||||
nDefaultPort = 19246;
|
||||
nPruneAfterHeight = 1000;
|
||||
|
||||
genesis = CreateGenesisBlock(1296688602, 414098458, 0x1d00ffff, 1, 50 * COIN);
|
||||
genesis = CreateGenesisBlock(1446058291, TESTNET_GENESIS_NONCE, 0x1f00ffff, 1, 400000000 * COIN);
|
||||
consensus.hashGenesisBlock = genesis.GetHash();
|
||||
assert(consensus.hashGenesisBlock == uint256S("0x000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"));
|
||||
assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
|
||||
#ifdef FIND_GENESIS
|
||||
std::cout << "testnet genesis hash: " << genesis.GetHash().GetHex() << std::endl;
|
||||
std::cout << "testnet merkle hash: " << genesis.hashMerkleRoot.GetHex() << std::endl;
|
||||
#else
|
||||
assert(consensus.hashGenesisBlock == uint256S(TESTNET_GENESIS_HASH));
|
||||
assert(genesis.hashMerkleRoot == uint256S(GENESIS_MERKLE_ROOT));
|
||||
#endif
|
||||
|
||||
vFixedSeeds.clear();
|
||||
vSeeds.clear();
|
||||
// nodes with support for servicebits filtering should be at the top
|
||||
vSeeds.emplace_back("testnet-seed.bitcoin.jonasschnelli.ch");
|
||||
vSeeds.emplace_back("seed.tbtc.petertodd.org");
|
||||
vSeeds.emplace_back("seed.testnet.bitcoin.sprovoost.nl");
|
||||
vSeeds.emplace_back("testnet-seed.bluematt.me"); // Just a static list of stable node(s), only supports x9
|
||||
vSeeds.emplace_back("testdnsseed1.lbry.io");
|
||||
vSeeds.emplace_back("testdnsseed2.lbry.io");
|
||||
|
||||
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,111);
|
||||
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,196);
|
||||
|
@ -247,21 +309,24 @@ public:
|
|||
base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF};
|
||||
base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94};
|
||||
|
||||
bech32_hrp = "tb";
|
||||
/* bech32_hrp = "tb"; */
|
||||
bech32_hrp = "lt"; // FIXME: change?
|
||||
|
||||
vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_test, pnSeed6_test + ARRAYLEN(pnSeed6_test));
|
||||
|
||||
fMiningRequiresPeers = true;
|
||||
fDefaultConsistencyChecks = false;
|
||||
fRequireStandard = false;
|
||||
fMineBlocksOnDemand = false;
|
||||
|
||||
fTestnetToBeDeprecatedFieldRPC = true;
|
||||
|
||||
checkpointData = {
|
||||
{
|
||||
{546, uint256S("000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70")},
|
||||
{0, uint256S(TESTNET_GENESIS_HASH)},
|
||||
}
|
||||
};
|
||||
|
||||
// FIXME:
|
||||
chainTxData = ChainTxData{
|
||||
// Data from rpc: getchaintxstats 4096 0000000000000037a8cd3e06cd5edbfe9dd1dbcc5dacab279376ef7cfc2b4c75
|
||||
/* nTime */ 1531929919,
|
||||
|
@ -280,18 +345,23 @@ public:
|
|||
class CRegTestParams : public CChainParams {
|
||||
public:
|
||||
CRegTestParams() {
|
||||
strNetworkID = "regtest";
|
||||
consensus.nSubsidyHalvingInterval = 150;
|
||||
strNetworkID = "lbrycrdreg";
|
||||
consensus.nSubsidyLevelInterval = 1 << 5;
|
||||
consensus.BIP16Exception = uint256();
|
||||
consensus.BIP34Height = 100000000; // BIP34 has not activated on regtest (far in the future so block v1 are not rejected in tests)
|
||||
// FIXME: heights
|
||||
consensus.BIP34Height = -1; // BIP34 has not necessarily activated on regtest
|
||||
consensus.BIP34Hash = uint256();
|
||||
consensus.BIP65Height = 1351; // BIP65 activated on regtest (Used in rpc activation tests)
|
||||
consensus.BIP66Height = 1251; // BIP66 activated on regtest (Used in rpc activation tests)
|
||||
consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
||||
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
|
||||
consensus.nPowTargetSpacing = 10 * 60;
|
||||
consensus.fPowAllowMinDifficultyBlocks = true;
|
||||
consensus.fPowNoRetargeting = true;
|
||||
consensus.nPowTargetTimespan = 1;//14 * 24 * 60 * 60; // two weeks
|
||||
consensus.nPowTargetSpacing = 1;
|
||||
consensus.nOriginalClaimExpirationTime = 500;
|
||||
consensus.nExtendedClaimExpirationTime = 600;
|
||||
consensus.nExtendedClaimExpirationForkHeight = 800;
|
||||
consensus.fPowAllowMinDifficultyBlocks = false;
|
||||
consensus.fPowNoRetargeting = false;
|
||||
consensus.nNormalizedNameForkHeight = 2000; // FIXME: pick a real fork height
|
||||
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;
|
||||
|
@ -311,27 +381,34 @@ public:
|
|||
consensus.defaultAssumeValid = uint256S("0x00");
|
||||
|
||||
pchMessageStart[0] = 0xfa;
|
||||
pchMessageStart[1] = 0xbf;
|
||||
pchMessageStart[2] = 0xb5;
|
||||
pchMessageStart[3] = 0xda;
|
||||
nDefaultPort = 18444;
|
||||
pchMessageStart[1] = 0xe4;
|
||||
pchMessageStart[2] = 0xaa;
|
||||
pchMessageStart[3] = 0xd1;
|
||||
nDefaultPort = 29246;
|
||||
nPruneAfterHeight = 1000;
|
||||
|
||||
genesis = CreateGenesisBlock(1296688602, 2, 0x207fffff, 1, 50 * COIN);
|
||||
genesis = CreateGenesisBlock(1446058291, REGTEST_GENESIS_NONCE, 0x207fffff, 1, 400000000 * COIN);
|
||||
consensus.hashGenesisBlock = genesis.GetHash();
|
||||
assert(consensus.hashGenesisBlock == uint256S("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206"));
|
||||
assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
|
||||
#ifdef FIND_GENESIS
|
||||
std::cout << "regtest genensis hash: " << genesis.GetHash().GetHex() << std::endl;
|
||||
std::cout << "regtest hashmerkleroot: " << genesis.hashMerkleRoot.GetHex() << std::endl;
|
||||
#else
|
||||
assert(consensus.hashGenesisBlock == uint256S(REGTEST_GENESIS_HASH));
|
||||
assert(genesis.hashMerkleRoot == uint256S(GENESIS_MERKLE_ROOT));
|
||||
#endif
|
||||
|
||||
vFixedSeeds.clear(); //!< Regtest mode doesn't have any fixed seeds.
|
||||
vSeeds.clear(); //!< Regtest mode doesn't have any DNS seeds.
|
||||
|
||||
fMiningRequiresPeers = false;
|
||||
fDefaultConsistencyChecks = true;
|
||||
fRequireStandard = false;
|
||||
fMineBlocksOnDemand = true;
|
||||
fTestnetToBeDeprecatedFieldRPC = false;
|
||||
|
||||
checkpointData = {
|
||||
{
|
||||
{0, uint256S("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")},
|
||||
{0, uint256S(REGTEST_GENESIS_HASH)},
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#ifndef BITCOIN_CHAINPARAMS_H
|
||||
#define BITCOIN_CHAINPARAMS_H
|
||||
|
||||
#include <arith_uint256.h>
|
||||
#include <chainparamsbase.h>
|
||||
#include <consensus/params.h>
|
||||
#include <primitives/block.h>
|
||||
|
@ -94,9 +95,11 @@ protected:
|
|||
std::string strNetworkID;
|
||||
CBlock genesis;
|
||||
std::vector<SeedSpec6> vFixedSeeds;
|
||||
bool fMiningRequiresPeers;
|
||||
bool fDefaultConsistencyChecks;
|
||||
bool fRequireStandard;
|
||||
bool fMineBlocksOnDemand;
|
||||
bool fTestnetToBeDeprecatedFieldRPC;
|
||||
CCheckpointData checkpointData;
|
||||
ChainTxData chainTxData;
|
||||
bool m_fallback_fee_enabled;
|
||||
|
|
|
@ -33,11 +33,11 @@ const CBaseChainParams& BaseParams()
|
|||
std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const std::string& chain)
|
||||
{
|
||||
if (chain == CBaseChainParams::MAIN)
|
||||
return MakeUnique<CBaseChainParams>("", 8332);
|
||||
return MakeUnique<CBaseChainParams>("", 9246);
|
||||
else if (chain == CBaseChainParams::TESTNET)
|
||||
return MakeUnique<CBaseChainParams>("testnet3", 18332);
|
||||
return MakeUnique<CBaseChainParams>("testnet3", 19246);
|
||||
else if (chain == CBaseChainParams::REGTEST)
|
||||
return MakeUnique<CBaseChainParams>("regtest", 18443);
|
||||
return MakeUnique<CBaseChainParams>("regtest", 29246);
|
||||
else
|
||||
throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
|
||||
}
|
||||
|
|
|
@ -44,6 +44,12 @@ std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const std::string& chain
|
|||
*/
|
||||
void SetupChainParamsBaseOptions();
|
||||
|
||||
/**
|
||||
* Append the help messages for the chainparams options to the
|
||||
* parameter string.
|
||||
*/
|
||||
void AppendParamsHelpMessages(std::string& strUsage, bool debugHelp=true);
|
||||
|
||||
/**
|
||||
* Return the currently selected parameters. This won't change after app
|
||||
* startup, except for unit tests.
|
||||
|
@ -53,4 +59,16 @@ const CBaseChainParams& BaseParams();
|
|||
/** Sets the params returned by Params() to those for the given network. */
|
||||
void SelectBaseParams(const std::string& chain);
|
||||
|
||||
/**
|
||||
* Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
|
||||
* @return CBaseChainParams::MAX_NETWORK_TYPES if an invalid combination is given. CBaseChainParams::MAIN by default.
|
||||
*/
|
||||
std::string ChainNameFromCommandLine();
|
||||
|
||||
/**
|
||||
* Return true if SelectBaseParamsFromCommandLine() has been called to select
|
||||
* a network.
|
||||
*/
|
||||
bool AreBaseParamsConfigured();
|
||||
|
||||
#endif // BITCOIN_CHAINPARAMSBASE_H
|
||||
|
|
File diff suppressed because it is too large
Load diff
2804
src/claimtrie.cpp
Normal file
2804
src/claimtrie.cpp
Normal file
File diff suppressed because it is too large
Load diff
655
src/claimtrie.h
Normal file
655
src/claimtrie.h
Normal file
|
@ -0,0 +1,655 @@
|
|||
#ifndef BITCOIN_CLAIMTRIE_H
|
||||
#define BITCOIN_CLAIMTRIE_H
|
||||
|
||||
#include "amount.h"
|
||||
#include "serialize.h"
|
||||
#include "uint256.h"
|
||||
#include "util.h"
|
||||
#include "dbwrapper.h"
|
||||
#include "chainparams.h"
|
||||
#include "primitives/transaction.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
// leveldb keys
|
||||
#define HASH_BLOCK 'h'
|
||||
#define CURRENT_HEIGHT 't'
|
||||
#define TRIE_NODE 'n'
|
||||
#define CLAIM_BY_ID 'i'
|
||||
#define CLAIM_QUEUE_ROW 'r'
|
||||
#define CLAIM_QUEUE_NAME_ROW 'm'
|
||||
#define EXP_QUEUE_ROW 'e'
|
||||
#define SUPPORT 's'
|
||||
#define SUPPORT_QUEUE_ROW 'u'
|
||||
#define SUPPORT_QUEUE_NAME_ROW 'p'
|
||||
#define SUPPORT_EXP_QUEUE_ROW 'x'
|
||||
|
||||
uint256 getValueHash(COutPoint outPoint, int nHeightOfLastTakeover);
|
||||
|
||||
// Provides pre-C++11 copy semantics of std::swap, rather than move
|
||||
// semantics (available in C++11).
|
||||
namespace claimtrie
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
static inline void swap(T& x, T& y) {
|
||||
const auto tmp = x;
|
||||
y = x;
|
||||
x = tmp;
|
||||
}
|
||||
|
||||
} // namespace claimtrie
|
||||
|
||||
class CClaimValue
|
||||
{
|
||||
public:
|
||||
COutPoint outPoint;
|
||||
uint160 claimId;
|
||||
CAmount nAmount;
|
||||
CAmount nEffectiveAmount;
|
||||
int nHeight;
|
||||
int nValidAtHeight;
|
||||
|
||||
CClaimValue() {};
|
||||
|
||||
CClaimValue(COutPoint outPoint, uint160 claimId, CAmount nAmount, int nHeight,
|
||||
int nValidAtHeight)
|
||||
: outPoint(outPoint), claimId(claimId)
|
||||
, nAmount(nAmount), nEffectiveAmount(nAmount)
|
||||
, nHeight(nHeight), nValidAtHeight(nValidAtHeight)
|
||||
{}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(outPoint);
|
||||
READWRITE(claimId);
|
||||
READWRITE(nAmount);
|
||||
READWRITE(nHeight);
|
||||
READWRITE(nValidAtHeight);
|
||||
}
|
||||
|
||||
bool operator<(const CClaimValue& other) const
|
||||
{
|
||||
if (nEffectiveAmount < other.nEffectiveAmount)
|
||||
return true;
|
||||
else if (nEffectiveAmount == other.nEffectiveAmount)
|
||||
{
|
||||
if (nHeight > other.nHeight)
|
||||
return true;
|
||||
else if (nHeight == other.nHeight)
|
||||
{
|
||||
if (outPoint != other.outPoint && !(outPoint < other.outPoint))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator==(const CClaimValue& other) const
|
||||
{
|
||||
return outPoint == other.outPoint && claimId == other.claimId && nAmount == other.nAmount && nHeight == other.nHeight && nValidAtHeight == other.nValidAtHeight;
|
||||
}
|
||||
|
||||
bool operator!=(const CClaimValue& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
class CSupportValue
|
||||
{
|
||||
public:
|
||||
COutPoint outPoint;
|
||||
uint160 supportedClaimId;
|
||||
CAmount nAmount;
|
||||
int nHeight;
|
||||
int nValidAtHeight;
|
||||
|
||||
CSupportValue() {};
|
||||
CSupportValue(COutPoint outPoint, uint160 supportedClaimId,
|
||||
CAmount nAmount, int nHeight, int nValidAtHeight)
|
||||
: outPoint(outPoint), supportedClaimId(supportedClaimId)
|
||||
, nAmount(nAmount), nHeight(nHeight)
|
||||
, nValidAtHeight(nValidAtHeight)
|
||||
{}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(outPoint);
|
||||
READWRITE(supportedClaimId);
|
||||
READWRITE(nAmount);
|
||||
READWRITE(nHeight);
|
||||
READWRITE(nValidAtHeight);
|
||||
}
|
||||
|
||||
bool operator==(const CSupportValue& other) const
|
||||
{
|
||||
return outPoint == other.outPoint && supportedClaimId == other.supportedClaimId && nAmount == other.nAmount && nHeight == other.nHeight && nValidAtHeight == other.nValidAtHeight;
|
||||
}
|
||||
|
||||
bool operator!=(const CSupportValue& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
class CClaimTrieNode;
|
||||
class CClaimTrie;
|
||||
|
||||
typedef std::vector<CSupportValue> supportMapEntryType;
|
||||
|
||||
typedef std::map<unsigned char, CClaimTrieNode*> nodeMapType;
|
||||
|
||||
typedef std::pair<std::string, CClaimTrieNode> namedNodeType;
|
||||
|
||||
class CClaimTrieNode
|
||||
{
|
||||
public:
|
||||
CClaimTrieNode() : nHeightOfLastTakeover(0) {}
|
||||
CClaimTrieNode(uint256 hash) : hash(hash), nHeightOfLastTakeover(0) {}
|
||||
uint256 hash;
|
||||
nodeMapType children;
|
||||
int nHeightOfLastTakeover;
|
||||
std::vector<CClaimValue> claims;
|
||||
|
||||
bool insertClaim(CClaimValue claim);
|
||||
bool removeClaim(const COutPoint& outPoint, CClaimValue& claim);
|
||||
bool getBestClaim(CClaimValue& claim) const;
|
||||
bool empty() const {return children.empty() && claims.empty();}
|
||||
bool haveClaim(const COutPoint& outPoint) const;
|
||||
void reorderClaims(supportMapEntryType& supports);
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(hash);
|
||||
READWRITE(claims);
|
||||
READWRITE(nHeightOfLastTakeover);
|
||||
}
|
||||
|
||||
bool operator==(const CClaimTrieNode& other) const
|
||||
{
|
||||
return hash == other.hash && claims == other.claims;
|
||||
}
|
||||
|
||||
bool operator!=(const CClaimTrieNode& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
struct nodenamecompare
|
||||
{
|
||||
bool operator() (const std::string& i, const std::string& j) const
|
||||
{
|
||||
if (i.size() == j.size())
|
||||
return i < j;
|
||||
return i.size() < j.size();
|
||||
}
|
||||
};
|
||||
|
||||
struct outPointHeightType
|
||||
{
|
||||
COutPoint outPoint;
|
||||
int nHeight;
|
||||
|
||||
outPointHeightType() {}
|
||||
|
||||
outPointHeightType(COutPoint outPoint, int nHeight)
|
||||
: outPoint(outPoint), nHeight(nHeight) {}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
||||
{
|
||||
READWRITE(outPoint);
|
||||
READWRITE(nHeight);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct nameOutPointHeightType
|
||||
{
|
||||
std::string name;
|
||||
COutPoint outPoint;
|
||||
int nHeight;
|
||||
|
||||
nameOutPointHeightType() {}
|
||||
|
||||
nameOutPointHeightType(std::string name, COutPoint outPoint, int nHeight)
|
||||
: name(name), outPoint(outPoint), nHeight(nHeight) {}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
||||
{
|
||||
READWRITE(name);
|
||||
READWRITE(outPoint);
|
||||
READWRITE(nHeight);
|
||||
}
|
||||
};
|
||||
|
||||
struct nameOutPointType
|
||||
{
|
||||
std::string name;
|
||||
COutPoint outPoint;
|
||||
|
||||
nameOutPointType() {}
|
||||
|
||||
nameOutPointType(std::string name, COutPoint outPoint)
|
||||
: name(name), outPoint(outPoint) {}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
||||
{
|
||||
READWRITE(name);
|
||||
READWRITE(outPoint);
|
||||
}
|
||||
};
|
||||
|
||||
class CClaimIndexElement
|
||||
{
|
||||
public:
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(name);
|
||||
READWRITE(claim);
|
||||
}
|
||||
|
||||
std::string name;
|
||||
CClaimValue claim;
|
||||
};
|
||||
|
||||
typedef std::pair<std::string, CClaimValue> claimQueueEntryType;
|
||||
|
||||
typedef std::pair<std::string, CSupportValue> supportQueueEntryType;
|
||||
|
||||
typedef std::map<std::string, supportMapEntryType> supportMapType;
|
||||
|
||||
typedef std::vector<outPointHeightType> queueNameRowType;
|
||||
typedef std::map<std::string, queueNameRowType> queueNameType;
|
||||
|
||||
typedef std::vector<nameOutPointHeightType> insertUndoType;
|
||||
|
||||
typedef std::vector<nameOutPointType> expirationQueueRowType;
|
||||
typedef std::map<int, expirationQueueRowType> expirationQueueType;
|
||||
|
||||
typedef std::vector<claimQueueEntryType> claimQueueRowType;
|
||||
typedef std::map<int, claimQueueRowType> claimQueueType;
|
||||
|
||||
typedef std::vector<supportQueueEntryType> supportQueueRowType;
|
||||
typedef std::map<int, supportQueueRowType> supportQueueType;
|
||||
|
||||
typedef std::map<std::string, CClaimTrieNode*, nodenamecompare> nodeCacheType;
|
||||
|
||||
typedef std::map<std::string, uint256> hashMapType;
|
||||
|
||||
typedef std::set<CClaimValue> claimIndexClaimListType;
|
||||
typedef std::vector<CClaimIndexElement> claimIndexElementListType;
|
||||
|
||||
struct claimsForNameType
|
||||
{
|
||||
std::vector<CClaimValue> claims;
|
||||
std::vector<CSupportValue> supports;
|
||||
int nLastTakeoverHeight;
|
||||
|
||||
claimsForNameType(std::vector<CClaimValue> claims, std::vector<CSupportValue> supports, int nLastTakeoverHeight)
|
||||
: claims(claims), supports(supports), nLastTakeoverHeight(nLastTakeoverHeight) {}
|
||||
};
|
||||
|
||||
class CClaimTrieCache;
|
||||
|
||||
class CClaimTrie
|
||||
{
|
||||
public:
|
||||
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"))
|
||||
{}
|
||||
|
||||
uint256 getMerkleHash();
|
||||
|
||||
bool empty() const;
|
||||
void clear();
|
||||
|
||||
bool checkConsistency() const;
|
||||
|
||||
bool WriteToDisk();
|
||||
bool ReadFromDisk(bool check = false);
|
||||
|
||||
std::vector<namedNodeType> flattenTrie() const;
|
||||
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 = nullptr) const;
|
||||
CAmount getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector<CSupportValue>* supports = nullptr) const;
|
||||
|
||||
bool queueEmpty() const;
|
||||
bool supportEmpty() const;
|
||||
bool supportQueueEmpty() const;
|
||||
bool expirationQueueEmpty() const;
|
||||
bool supportExpirationQueueEmpty() const;
|
||||
|
||||
void setExpirationTime(int t);
|
||||
|
||||
void addToClaimIndex(const std::string& name, const CClaimValue& claim);
|
||||
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,
|
||||
int& nValidAtHeight) const;
|
||||
|
||||
bool haveSupport(const std::string& name, const COutPoint& outPoint) const;
|
||||
bool haveSupportInQueue(const std::string& name, const COutPoint& outPoint,
|
||||
int& nValidAtHeight) const;
|
||||
|
||||
unsigned int getTotalNamesInTrie() const;
|
||||
unsigned int getTotalClaimsInTrie() const;
|
||||
CAmount getTotalValueOfClaimsInTrie(bool fControllingOnly) const;
|
||||
|
||||
friend class CClaimTrieCache;
|
||||
|
||||
CDBWrapper db;
|
||||
int nCurrentHeight;
|
||||
int nExpirationTime;
|
||||
int nProportionalDelayFactor;
|
||||
private:
|
||||
void clear(CClaimTrieNode* current);
|
||||
|
||||
const CClaimTrieNode* getNodeForName(const std::string& name) const;
|
||||
|
||||
bool update(nodeCacheType& cache, hashMapType& hashes,
|
||||
std::map<std::string, int>& takeoverHeights,
|
||||
const uint256& hashBlock, claimQueueType& queueCache,
|
||||
queueNameType& queueNameCache,
|
||||
expirationQueueType& expirationQueueCache, int nNewHeight,
|
||||
supportMapType& supportCache,
|
||||
supportQueueType& supportQueueCache,
|
||||
queueNameType& supportQueueNameCache,
|
||||
expirationQueueType& supportExpirationQueueCache);
|
||||
bool updateName(const std::string& name, CClaimTrieNode* updatedNode);
|
||||
bool updateHash(const std::string& name, uint256& hash);
|
||||
bool updateTakeoverHeight(const std::string& name, int nTakeoverHeight);
|
||||
bool recursiveNullify(CClaimTrieNode* node, std::string& name);
|
||||
|
||||
bool recursiveCheckConsistency(const CClaimTrieNode* node) const;
|
||||
|
||||
bool InsertFromDisk(const std::string& name, CClaimTrieNode* node);
|
||||
|
||||
unsigned int getTotalNamesRecursive(const CClaimTrieNode* current) const;
|
||||
unsigned int getTotalClaimsRecursive(const CClaimTrieNode* current) const;
|
||||
CAmount getTotalValueOfClaimsRecursive(const CClaimTrieNode* current,
|
||||
bool fControllingOnly) const;
|
||||
bool recursiveFlattenTrie(const std::string& name,
|
||||
const CClaimTrieNode* current,
|
||||
std::vector<namedNodeType>& nodes) const;
|
||||
|
||||
void markNodeDirty(const std::string& name, CClaimTrieNode* node);
|
||||
void updateQueueRow(int nHeight, claimQueueRowType& row);
|
||||
void updateQueueNameRow(const std::string& name,
|
||||
queueNameRowType& row);
|
||||
void updateExpirationRow(int nHeight, expirationQueueRowType& row);
|
||||
void updateSupportMap(const std::string& name, supportMapEntryType& node);
|
||||
void updateSupportQueue(int nHeight, supportQueueRowType& row);
|
||||
void updateSupportNameQueue(const std::string& name,
|
||||
queueNameRowType& row);
|
||||
void updateSupportExpirationQueue(int nHeight, expirationQueueRowType& row);
|
||||
|
||||
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);
|
||||
void BatchWriteSupportNodes(CDBBatch& batch);
|
||||
void BatchWriteSupportQueueRows(CDBBatch& batch);
|
||||
void BatchWriteSupportQueueNameRows(CDBBatch& batch);
|
||||
void BatchWriteSupportExpirationQueueRows(CDBBatch& batch);
|
||||
template<typename K> bool keyTypeEmpty(char key, K& dummy) const;
|
||||
|
||||
CClaimTrieNode root;
|
||||
uint256 hashBlock;
|
||||
|
||||
claimQueueType dirtyQueueRows;
|
||||
queueNameType dirtyQueueNameRows;
|
||||
expirationQueueType dirtyExpirationQueueRows;
|
||||
|
||||
supportQueueType dirtySupportQueueRows;
|
||||
queueNameType dirtySupportQueueNameRows;
|
||||
expirationQueueType dirtySupportExpirationQueueRows;
|
||||
|
||||
nodeCacheType dirtyNodes;
|
||||
supportMapType dirtySupportNodes;
|
||||
};
|
||||
|
||||
class CClaimTrieProofNode
|
||||
{
|
||||
public:
|
||||
CClaimTrieProofNode() {};
|
||||
CClaimTrieProofNode(std::vector<std::pair<unsigned char, uint256> > children,
|
||||
bool hasValue, uint256 valHash)
|
||||
: children(children), hasValue(hasValue), valHash(valHash)
|
||||
{};
|
||||
std::vector<std::pair<unsigned char, uint256> > children;
|
||||
bool hasValue;
|
||||
uint256 valHash;
|
||||
};
|
||||
|
||||
class CClaimTrieProof
|
||||
{
|
||||
public:
|
||||
CClaimTrieProof() {};
|
||||
CClaimTrieProof(std::vector<CClaimTrieProofNode> nodes, bool hasValue, COutPoint outPoint, int nHeightOfLastTakeover) : nodes(nodes), hasValue(hasValue), outPoint(outPoint), nHeightOfLastTakeover(nHeightOfLastTakeover) {}
|
||||
std::vector<CClaimTrieProofNode> nodes;
|
||||
bool hasValue;
|
||||
COutPoint outPoint;
|
||||
int nHeightOfLastTakeover;
|
||||
};
|
||||
|
||||
class CClaimTrieCache
|
||||
{
|
||||
public:
|
||||
CClaimTrieCache(CClaimTrie* base, bool fRequireTakeoverHeights = true)
|
||||
: base(base),
|
||||
fRequireTakeoverHeights(fRequireTakeoverHeights)
|
||||
{
|
||||
assert(base);
|
||||
nCurrentHeight = base->nCurrentHeight;
|
||||
}
|
||||
|
||||
uint256 getMerkleHash() const;
|
||||
|
||||
bool empty() const;
|
||||
bool flush();
|
||||
bool dirty() const { return !dirtyHashes.empty(); }
|
||||
|
||||
CClaimTrieNode* getRoot() const
|
||||
{
|
||||
const auto iter = cache.find("");
|
||||
return iter == cache.end() ? &(base->root) : iter->second;
|
||||
}
|
||||
|
||||
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 undoSpendClaim(const std::string& name, const COutPoint& outPoint,
|
||||
uint160 claimId, CAmount nAmount, int nHeight,
|
||||
int nValidAtHeight) const;
|
||||
|
||||
bool addSupport(const std::string& name, const COutPoint& outPoint,
|
||||
CAmount nAmount, uint160 supportedClaimId,
|
||||
int nHeight) const;
|
||||
bool undoAddSupport(const std::string& name, const COutPoint& outPoint,
|
||||
int nHeight) const;
|
||||
bool spendSupport(const std::string& name, const COutPoint& outPoint,
|
||||
int nHeight, int& nValidAtHeight) const;
|
||||
bool undoSpendSupport(const std::string& name, const COutPoint& outPoint,
|
||||
uint160 supportedClaimId, CAmount nAmount,
|
||||
int nHeight, int nValidAtHeight) const;
|
||||
|
||||
uint256 getBestBlock();
|
||||
void setBestBlock(const uint256& hashBlock);
|
||||
|
||||
bool incrementBlock(insertUndoType& insertUndo,
|
||||
claimQueueRowType& expireUndo,
|
||||
insertUndoType& insertSupportUndo,
|
||||
supportQueueRowType& expireSupportUndo,
|
||||
std::vector<std::pair<std::string, int> >& takeoverHeightUndo) const;
|
||||
bool decrementBlock(insertUndoType& insertUndo,
|
||||
claimQueueRowType& expireUndo,
|
||||
insertUndoType& insertSupportUndo,
|
||||
supportQueueRowType& expireSupportUndo,
|
||||
std::vector<std::pair<std::string, int> >& takeoverHeightUndo) const;
|
||||
|
||||
~CClaimTrieCache() { 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;
|
||||
|
||||
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;
|
||||
|
||||
std::vector<namedNodeType> flattenTrie() const;
|
||||
|
||||
claimsForNameType getClaimsForName(const std::string& name) const;
|
||||
|
||||
CAmount getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector<CSupportValue>* supports = nullptr) const;
|
||||
CAmount getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector<CSupportValue>* supports = nullptr) const;
|
||||
|
||||
protected:
|
||||
CClaimTrie* base;
|
||||
|
||||
bool fRequireTakeoverHeights;
|
||||
|
||||
mutable nodeCacheType cache;
|
||||
mutable nodeCacheType block_originals;
|
||||
mutable std::set<std::string> dirtyHashes;
|
||||
mutable hashMapType cacheHashes;
|
||||
mutable claimQueueType claimQueueCache;
|
||||
mutable queueNameType claimQueueNameCache;
|
||||
mutable expirationQueueType expirationQueueCache;
|
||||
mutable supportMapType supportCache;
|
||||
mutable supportQueueType supportQueueCache;
|
||||
mutable queueNameType supportQueueNameCache;
|
||||
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 recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent,
|
||||
std::string sPos) const;
|
||||
bool recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos,
|
||||
std::string sName,
|
||||
bool* pfNullified = NULL) 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;
|
||||
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;
|
||||
queueNameType::iterator getQueueCacheNameRow(const std::string& name,
|
||||
bool createIfNotExists) const;
|
||||
expirationQueueType::iterator getExpirationQueueCacheRow(int nHeight,
|
||||
bool createIfNotExists) const;
|
||||
|
||||
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;
|
||||
queueNameType::iterator getSupportQueueCacheNameRow(const std::string& name, bool createIfNotExists) const;
|
||||
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;
|
||||
|
||||
CClaimTrieNode* addNodeToCache(const std::string& position, CClaimTrieNode* original) const;
|
||||
|
||||
bool getOriginalInfoForName(const std::string& name, CClaimValue& claim) const;
|
||||
|
||||
int getNumBlocksOfContinuousOwnership(const std::string& name) const;
|
||||
|
||||
void recursiveFlattenTrie(const std::string& name, const CClaimTrieNode* current, std::vector<namedNodeType>& nodes) const;
|
||||
|
||||
const CClaimTrieNode* getNodeForName(const std::string& name) const;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_CLAIMTRIE_H
|
|
@ -39,8 +39,8 @@ public:
|
|||
uint32_t nHeight : 31;
|
||||
|
||||
//! construct a Coin from a CTxOut and height/coinbase information.
|
||||
Coin(CTxOut&& outIn, int nHeightIn, bool fCoinBaseIn) : out(std::move(outIn)), fCoinBase(fCoinBaseIn), nHeight(nHeightIn) {}
|
||||
Coin(const CTxOut& outIn, int nHeightIn, bool fCoinBaseIn) : out(outIn), fCoinBase(fCoinBaseIn),nHeight(nHeightIn) {}
|
||||
Coin(CTxOut&& outIn, int nHeightIn, bool fCoinBaseIn) : out(std::move(outIn)), fCoinBase(fCoinBaseIn), nHeight(nHeightIn) {}
|
||||
Coin(const CTxOut& outIn, int nHeightIn, bool fCoinBaseIn) : out(outIn), fCoinBase(fCoinBaseIn), nHeight(nHeightIn) {}
|
||||
|
||||
void Clear() {
|
||||
out.SetNull();
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
#include <stdint.h>
|
||||
|
||||
/** The maximum allowed size for a serialized block, in bytes (only for buffer size limits) */
|
||||
static const unsigned int MAX_BLOCK_SERIALIZED_SIZE = 4000000;
|
||||
static const unsigned int MAX_BLOCK_SERIALIZED_SIZE = 8000000;
|
||||
/** The maximum allowed weight for a block, see BIP 141 (network rule) */
|
||||
static const unsigned int MAX_BLOCK_WEIGHT = 4000000;
|
||||
static const unsigned int MAX_BLOCK_WEIGHT = 8000000;
|
||||
/** The maximum allowed number of signature check operations in a block (network rule) */
|
||||
static const int64_t MAX_BLOCK_SIGOPS_COST = 80000;
|
||||
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */
|
||||
|
|
|
@ -48,7 +48,11 @@ struct BIP9Deployment {
|
|||
*/
|
||||
struct Params {
|
||||
uint256 hashGenesisBlock;
|
||||
int nSubsidyHalvingInterval;
|
||||
int nSubsidyLevelInterval;
|
||||
/** Used to check majorities for block version upgrade */
|
||||
int nMajorityEnforceBlockUpgrade;
|
||||
int nMajorityRejectBlockOutdated;
|
||||
int nMajorityWindow;
|
||||
/* Block hash that is excepted from BIP16 enforcement */
|
||||
uint256 BIP16Exception;
|
||||
/** Block height and hash at which BIP34 becomes active */
|
||||
|
@ -70,8 +74,17 @@ struct Params {
|
|||
uint256 powLimit;
|
||||
bool fPowAllowMinDifficultyBlocks;
|
||||
bool fPowNoRetargeting;
|
||||
int nNormalizedNameForkHeight;
|
||||
int64_t nPowTargetSpacing;
|
||||
int64_t nPowTargetTimespan;
|
||||
int64_t nOriginalClaimExpirationTime;
|
||||
int64_t nExtendedClaimExpirationTime;
|
||||
int64_t nExtendedClaimExpirationForkHeight;
|
||||
int64_t GetExpirationTime(int64_t nHeight) const {
|
||||
return nHeight < nExtendedClaimExpirationForkHeight ?
|
||||
nOriginalClaimExpirationTime :
|
||||
nExtendedClaimExpirationTime;
|
||||
}
|
||||
int64_t DifficultyAdjustmentInterval() const { return nPowTargetTimespan / nPowTargetSpacing; }
|
||||
uint256 nMinimumChainWork;
|
||||
uint256 defaultAssumeValid;
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include <script/interpreter.h>
|
||||
#include <consensus/validation.h>
|
||||
|
||||
#include <nameclaim.h>
|
||||
|
||||
// TODO remove the following dependencies
|
||||
#include <chain.h>
|
||||
#include <coins.h>
|
||||
|
@ -129,8 +131,9 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in
|
|||
const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
|
||||
assert(!coin.IsSpent());
|
||||
const CTxOut &prevout = coin.out;
|
||||
if (prevout.scriptPubKey.IsPayToScriptHash())
|
||||
nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig);
|
||||
const CScript& scriptPubKey = StripClaimScriptPrefix(prevout.scriptPubKey);
|
||||
if (scriptPubKey.IsPayToScriptHash())
|
||||
nSigOps += scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig);
|
||||
}
|
||||
return nSigOps;
|
||||
}
|
||||
|
@ -178,6 +181,12 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fChe
|
|||
nValueOut += txout.nValue;
|
||||
if (!MoneyRange(nValueOut))
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge");
|
||||
|
||||
// check claimtrie transactions
|
||||
if (ClaimScriptSize(txout.scriptPubKey) > MAX_CLAIM_SCRIPT_SIZE)
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-claimscriptsize-toolarge");
|
||||
if (ClaimNameSize(txout.scriptPubKey) > MAX_CLAIM_NAME_SIZE)
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-claimscriptname-toolarge");
|
||||
}
|
||||
|
||||
// Check for duplicate inputs - note that this check is slow so we skip it in CheckBlock
|
||||
|
|
|
@ -225,7 +225,7 @@ public:
|
|||
~CDBWrapper();
|
||||
|
||||
CDBWrapper(const CDBWrapper&) = delete;
|
||||
CDBWrapper& operator=(const CDBWrapper&) = delete;
|
||||
/* CDBWrapper& operator=(const CDBWrapper&) = delete; */
|
||||
|
||||
template <typename K, typename V>
|
||||
bool Read(const K& key, V& value) const
|
||||
|
|
37
src/hash.cpp
37
src/hash.cpp
|
@ -12,6 +12,43 @@ inline uint32_t ROTL32(uint32_t x, int8_t r)
|
|||
return (x << r) | (x >> (32 - r));
|
||||
}
|
||||
|
||||
uint256 PoWHash(const std::vector<unsigned char>& input)
|
||||
{
|
||||
CHash256 h256;
|
||||
CSHA512 h512;
|
||||
CRIPEMD160 h160;
|
||||
|
||||
std::vector<unsigned char> out;
|
||||
out.resize(h512.OUTPUT_SIZE);
|
||||
|
||||
std::vector<unsigned char> out_small;
|
||||
out_small.resize(h160.OUTPUT_SIZE);
|
||||
|
||||
h256.Write(input.data(), input.size());
|
||||
h256.Finalize(&out[0]);
|
||||
h256.Reset();
|
||||
|
||||
h512.Write(out.data(), h256.OUTPUT_SIZE);
|
||||
h512.Finalize(&out[0]);
|
||||
|
||||
h160.Write(out.data(), h512.OUTPUT_SIZE / 2);
|
||||
h160.Finalize(&out_small[0]);
|
||||
h160.Reset();
|
||||
|
||||
h256.Write(out_small.data(), h160.OUTPUT_SIZE);
|
||||
|
||||
h160.Write(out.data() + h512.OUTPUT_SIZE / 2, h512.OUTPUT_SIZE / 2);
|
||||
h160.Finalize(&out_small[0]);
|
||||
|
||||
out.resize(h256.OUTPUT_SIZE);
|
||||
h256.Write(out_small.data(), h160.OUTPUT_SIZE);
|
||||
h256.Finalize(&out[0]);
|
||||
|
||||
uint256 result(out);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char>& vDataToHash)
|
||||
{
|
||||
// The following is MurmurHash3 (x86_32), see http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
|
||||
|
|
|
@ -190,6 +190,8 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL
|
|||
return ss.GetHash();
|
||||
}
|
||||
|
||||
uint256 PoWHash(const std::vector<unsigned char>& input);
|
||||
|
||||
unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char>& vDataToHash);
|
||||
|
||||
void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]);
|
||||
|
|
|
@ -16,31 +16,6 @@ constexpr char DB_TXINDEX_BLOCK = 'T';
|
|||
|
||||
std::unique_ptr<TxIndex> g_txindex;
|
||||
|
||||
struct CDiskTxPos : public CDiskBlockPos
|
||||
{
|
||||
unsigned int nTxOffset; // after header
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITEAS(CDiskBlockPos, *this);
|
||||
READWRITE(VARINT(nTxOffset));
|
||||
}
|
||||
|
||||
CDiskTxPos(const CDiskBlockPos &blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) {
|
||||
}
|
||||
|
||||
CDiskTxPos() {
|
||||
SetNull();
|
||||
}
|
||||
|
||||
void SetNull() {
|
||||
CDiskBlockPos::SetNull();
|
||||
nTxOffset = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Access to the txindex database (indexes/txindex/)
|
||||
*
|
||||
|
|
|
@ -9,6 +9,31 @@
|
|||
#include <index/base.h>
|
||||
#include <txdb.h>
|
||||
|
||||
struct CDiskTxPos : public CDiskBlockPos
|
||||
{
|
||||
unsigned int nTxOffset; // after header
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITEAS(CDiskBlockPos, *this);
|
||||
READWRITE(VARINT(nTxOffset));
|
||||
}
|
||||
|
||||
CDiskTxPos(const CDiskBlockPos &blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) {
|
||||
}
|
||||
|
||||
CDiskTxPos() {
|
||||
SetNull();
|
||||
}
|
||||
|
||||
void SetNull() {
|
||||
CDiskBlockPos::SetNull();
|
||||
nTxOffset = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* TxIndex is used to look up transactions included in the blockchain by hash.
|
||||
* The index is written to a LevelDB database and records the filesystem
|
||||
|
|
15
src/init.cpp
15
src/init.cpp
|
@ -14,6 +14,7 @@
|
|||
#include <chain.h>
|
||||
#include <chainparams.h>
|
||||
#include <checkpoints.h>
|
||||
#include <claimtrie.h>
|
||||
#include <compat/sanity.h>
|
||||
#include <consensus/validation.h>
|
||||
#include <fs.h>
|
||||
|
@ -41,6 +42,7 @@
|
|||
#include <txmempool.h>
|
||||
#include <torcontrol.h>
|
||||
#include <ui_interface.h>
|
||||
#include <uint256.h>
|
||||
#include <util.h>
|
||||
#include <utilmoneystr.h>
|
||||
#include <validationinterface.h>
|
||||
|
@ -264,6 +266,8 @@ void Shutdown()
|
|||
pcoinscatcher.reset();
|
||||
pcoinsdbview.reset();
|
||||
pblocktree.reset();
|
||||
delete pclaimTrie;
|
||||
pclaimTrie = nullptr;
|
||||
}
|
||||
g_wallet_init_interface.Stop();
|
||||
|
||||
|
@ -1455,6 +1459,8 @@ bool AppInitMain()
|
|||
// fails if it's still open from the previous loop. Close it first:
|
||||
pblocktree.reset();
|
||||
pblocktree.reset(new CBlockTreeDB(nBlockTreeDBCache, false, fReset));
|
||||
delete pclaimTrie;
|
||||
pclaimTrie = new CClaimTrie(false, fReindex);
|
||||
|
||||
if (fReset) {
|
||||
pblocktree->WriteReindexing(true);
|
||||
|
@ -1496,6 +1502,12 @@ bool AppInitMain()
|
|||
break;
|
||||
}
|
||||
|
||||
if (!pclaimTrie->ReadFromDisk(true))
|
||||
{
|
||||
strLoadError = _("Error loading the claim trie from disk");
|
||||
break;
|
||||
}
|
||||
|
||||
// At this point we're either in reindex or we've loaded a useful
|
||||
// block tree into mapBlockIndex!
|
||||
|
||||
|
@ -1688,6 +1700,9 @@ bool AppInitMain()
|
|||
}
|
||||
LogPrintf("nBestHeight = %d\n", chain_active_height);
|
||||
|
||||
const Consensus::Params& consensusParams = Params().GetConsensus();
|
||||
pclaimTrie->setExpirationTime(consensusParams.GetExpirationTime(chain_active_height));
|
||||
|
||||
if (gArgs.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION))
|
||||
StartTorControl();
|
||||
|
||||
|
|
40
src/lbry.cpp
Normal file
40
src/lbry.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
#include <lbry.h>
|
||||
#include <uint256.h>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
unsigned int CalculateLbryNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
|
||||
{
|
||||
if (params.fPowNoRetargeting)
|
||||
return pindexLast->nBits;
|
||||
|
||||
const int64_t retargetTimespan = params.nPowTargetTimespan;
|
||||
const int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime;
|
||||
int64_t nModulatedTimespan = nActualTimespan;
|
||||
int64_t nMaxTimespan;
|
||||
int64_t nMinTimespan;
|
||||
|
||||
nModulatedTimespan = retargetTimespan + (nModulatedTimespan - retargetTimespan) / 8;
|
||||
|
||||
nMinTimespan = retargetTimespan - (retargetTimespan / 8); //(150 - 18 = 132)
|
||||
nMaxTimespan = retargetTimespan + (retargetTimespan / 2); //(150 + 75 = 225)
|
||||
|
||||
// Limit adjustment step
|
||||
if (nModulatedTimespan < nMinTimespan)
|
||||
nModulatedTimespan = nMinTimespan;
|
||||
else if (nModulatedTimespan > nMaxTimespan)
|
||||
nModulatedTimespan = nMaxTimespan;
|
||||
|
||||
// Retarget
|
||||
const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
|
||||
arith_uint256 bnNew;
|
||||
bnNew.SetCompact(pindexLast->nBits);
|
||||
bnNew *= nModulatedTimespan;
|
||||
bnNew /= retargetTimespan;
|
||||
if (bnNew > bnPowLimit)
|
||||
bnNew = bnPowLimit;
|
||||
|
||||
return bnNew.GetCompact();
|
||||
}
|
||||
|
||||
|
9
src/lbry.h
Normal file
9
src/lbry.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef LBRY_H
|
||||
#define LBRY_H
|
||||
|
||||
#include <chain.h>
|
||||
#include <chainparams.h>
|
||||
|
||||
unsigned int CalculateLbryNextWorkRequired(const CBlockIndex* pindexLast, int64_t nLastRetargetTime, const Consensus::Params& params);
|
||||
|
||||
#endif
|
129
src/miner.cpp
129
src/miner.cpp
|
@ -117,7 +117,12 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
|
|||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
assert(pindexPrev != nullptr);
|
||||
nHeight = pindexPrev->nHeight + 1;
|
||||
|
||||
if (!pclaimTrie)
|
||||
{
|
||||
LogPrintf("CreateNewBlock(): pclaimTrie is invalid");
|
||||
return NULL;
|
||||
}
|
||||
CClaimTrieCache trieCache(pclaimTrie);
|
||||
pblock->nVersion = ComputeBlockVersion(pindexPrev, chainparams.GetConsensus());
|
||||
// -regtest only: allow overriding block.nVersion with
|
||||
// -blockversion=N to test forking scenarios
|
||||
|
@ -144,7 +149,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
|
|||
|
||||
int nPackagesSelected = 0;
|
||||
int nDescendantsUpdated = 0;
|
||||
addPackageTxs(nPackagesSelected, nDescendantsUpdated);
|
||||
addPackageTxs(nPackagesSelected, nDescendantsUpdated, trieCache);
|
||||
|
||||
int64_t nTime1 = GetTimeMicros();
|
||||
|
||||
|
@ -172,6 +177,16 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
|
|||
pblock->nNonce = 0;
|
||||
pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]);
|
||||
|
||||
insertUndoType dummyInsertUndo;
|
||||
claimQueueRowType dummyExpireUndo;
|
||||
insertUndoType dummyInsertSupportUndo;
|
||||
supportQueueRowType dummyExpireSupportUndo;
|
||||
std::vector<std::pair<std::string, int> > dummyTakeoverHeightUndo;
|
||||
|
||||
trieCache.incrementBlock(dummyInsertUndo, dummyExpireUndo, dummyInsertSupportUndo, dummyExpireSupportUndo, dummyTakeoverHeightUndo);
|
||||
|
||||
pblock->hashClaimTrie = trieCache.getMerkleHash();
|
||||
|
||||
CValidationState state;
|
||||
if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) {
|
||||
throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state)));
|
||||
|
@ -303,7 +318,7 @@ void BlockAssembler::SortForBlock(const CTxMemPool::setEntries& package, std::ve
|
|||
// Each time through the loop, we compare the best transaction in
|
||||
// mapModifiedTxs with the next transaction in the mempool to decide what
|
||||
// transaction package to work on next.
|
||||
void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated)
|
||||
void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated, CClaimTrieCache& trieCache)
|
||||
{
|
||||
// mapModifiedTx will store sorted packages after they are modified
|
||||
// because some of their txs are already in the block
|
||||
|
@ -413,6 +428,114 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
|
|||
continue;
|
||||
}
|
||||
|
||||
typedef std::vector<std::pair<std::string, uint160> > spentClaimsType;
|
||||
spentClaimsType spentClaims;
|
||||
|
||||
const CTransaction& tx = iter->GetTx();
|
||||
for (const CTxIn& txin: tx.vin)
|
||||
{
|
||||
CCoinsViewCache view(pcoinsTip.get());
|
||||
const Coin& coin = view.AccessCoin(txin.prevout);
|
||||
int nTxinHeight = coin.nHeight;
|
||||
CScript scriptPubKey = coin.out.scriptPubKey;
|
||||
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
int op;
|
||||
|
||||
if (DecodeClaimScript(scriptPubKey, op, vvchParams))
|
||||
{
|
||||
if (op == OP_CLAIM_NAME || op == OP_UPDATE_CLAIM)
|
||||
{
|
||||
uint160 claimId;
|
||||
if (op == OP_CLAIM_NAME)
|
||||
{
|
||||
assert(vvchParams.size() == 2);
|
||||
claimId = ClaimIdHash(txin.prevout.hash, txin.prevout.n);
|
||||
}
|
||||
else if (op == OP_UPDATE_CLAIM)
|
||||
{
|
||||
assert(vvchParams.size() == 3);
|
||||
claimId = uint160(vvchParams[1]);
|
||||
}
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
int throwaway;
|
||||
if (trieCache.spendClaim(name, COutPoint(txin.prevout.hash, txin.prevout.n), throwaway))
|
||||
{
|
||||
std::pair<std::string, uint160> entry(name, claimId);
|
||||
spentClaims.push_back(entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrintf("%s(): The claim was not found in the trie or queue and therefore can't be updated\n", __func__);
|
||||
}
|
||||
}
|
||||
else if (op == OP_SUPPORT_CLAIM)
|
||||
{
|
||||
assert(vvchParams.size() == 2);
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
int throwaway;
|
||||
if (!trieCache.spendSupport(name, COutPoint(txin.prevout.hash, txin.prevout.n), nTxinHeight, throwaway))
|
||||
{
|
||||
LogPrintf("%s(): The support was not found in the trie or queue\n", __func__);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < tx.vout.size(); ++i)
|
||||
{
|
||||
const CTxOut& txout = tx.vout[i];
|
||||
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
int op;
|
||||
if (DecodeClaimScript(txout.scriptPubKey, op, vvchParams))
|
||||
{
|
||||
if (op == OP_CLAIM_NAME)
|
||||
{
|
||||
assert(vvchParams.size() == 2);
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
if (!trieCache.addClaim(name, COutPoint(tx.GetHash(), i), ClaimIdHash(tx.GetHash(), i), txout.nValue, nHeight))
|
||||
{
|
||||
LogPrintf("%s: Something went wrong inserting the name\n", __func__);
|
||||
}
|
||||
}
|
||||
else if (op == OP_UPDATE_CLAIM)
|
||||
{
|
||||
assert(vvchParams.size() == 3);
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
uint160 claimId(vvchParams[1]);
|
||||
spentClaimsType::iterator itSpent;
|
||||
for (itSpent = spentClaims.begin(); itSpent != spentClaims.end(); ++itSpent)
|
||||
{
|
||||
if (itSpent->first == name && itSpent->second == claimId)
|
||||
break;
|
||||
}
|
||||
if (itSpent != spentClaims.end())
|
||||
{
|
||||
spentClaims.erase(itSpent);
|
||||
if (!trieCache.addClaim(name, COutPoint(tx.GetHash(), i), claimId, txout.nValue, nHeight))
|
||||
{
|
||||
LogPrintf("%s: Something went wrong updating a claim\n", __func__);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrintf("%s(): This update refers to a claim that was not found in the trie or queue, and therefore cannot be updated. The claim may have expired or it may have never existed.\n", __func__);
|
||||
}
|
||||
}
|
||||
else if (op == OP_SUPPORT_CLAIM)
|
||||
{
|
||||
assert(vvchParams.size() == 2);
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
uint160 supportedClaimId(vvchParams[1]);
|
||||
if (!trieCache.addSupport(name, COutPoint(tx.GetHash(), i), txout.nValue, supportedClaimId, nHeight))
|
||||
{
|
||||
LogPrintf("%s: Something went wrong inserting the claim support\n", __func__);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This transaction will make it in; reset the failed counter.
|
||||
nConsecutiveFailed = 0;
|
||||
|
||||
|
|
|
@ -170,7 +170,7 @@ private:
|
|||
/** Add transactions based on feerate including unconfirmed ancestors
|
||||
* Increments nPackagesSelected / nDescendantsUpdated with corresponding
|
||||
* statistics from the package selection (for logging statistics). */
|
||||
void addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs);
|
||||
void addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated, CClaimTrieCache& trieCache) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs);
|
||||
|
||||
// helper functions for addPackageTxs()
|
||||
/** Remove confirmed (inBlock) entries from given set */
|
||||
|
|
201
src/nameclaim.cpp
Normal file
201
src/nameclaim.cpp
Normal file
|
@ -0,0 +1,201 @@
|
|||
#include <boost/foreach.hpp>
|
||||
#include "nameclaim.h"
|
||||
#include "hash.h"
|
||||
#include "util.h"
|
||||
#include "claimtrie.h"
|
||||
|
||||
|
||||
std::vector<unsigned char> uint32_t_to_vch(uint32_t n)
|
||||
{
|
||||
std::vector<unsigned char> vchN;
|
||||
vchN.resize(4);
|
||||
vchN[0] = n >> 24;
|
||||
vchN[1] = n >> 16;
|
||||
vchN[2] = n >> 8;
|
||||
vchN[3] = n;
|
||||
return vchN;
|
||||
}
|
||||
|
||||
uint32_t vch_to_uint32_t(std::vector<unsigned char>& vchN)
|
||||
{
|
||||
uint32_t n;
|
||||
static const size_t uint32Size = sizeof(uint32_t);
|
||||
if (vchN.size() != uint32Size) {
|
||||
LogPrintf("%s() : a vector<unsigned char> with size other than 4 has been given", __func__);
|
||||
return 0;
|
||||
}
|
||||
n = vchN[0] << 24 | vchN[1] << 16 | vchN[2] << 8 | vchN[3];
|
||||
return n;
|
||||
}
|
||||
|
||||
CScript ClaimNameScript(std::string name, std::string value)
|
||||
{
|
||||
std::vector<unsigned char> vchName(name.begin(), name.end());
|
||||
std::vector<unsigned char> vchValue(value.begin(), value.end());
|
||||
return CScript() << OP_CLAIM_NAME << vchName << vchValue << OP_2DROP << OP_DROP << OP_TRUE;
|
||||
}
|
||||
|
||||
CScript SupportClaimScript(std::string name, uint160 claimId)
|
||||
{
|
||||
std::vector<unsigned char> vchName(name.begin(), name.end());
|
||||
std::vector<unsigned char> vchClaimId(claimId.begin(), claimId.end());
|
||||
return CScript() << OP_SUPPORT_CLAIM << vchName << vchClaimId << OP_2DROP << OP_DROP << OP_TRUE;
|
||||
}
|
||||
|
||||
CScript UpdateClaimScript(std::string name, uint160 claimId, std::string value)
|
||||
{
|
||||
std::vector<unsigned char> vchName(name.begin(), name.end());
|
||||
std::vector<unsigned char> vchClaimId(claimId.begin(), claimId.end());
|
||||
std::vector<unsigned char> vchValue(value.begin(), value.end());
|
||||
return CScript() << OP_UPDATE_CLAIM << vchName << vchClaimId << vchValue << OP_2DROP << OP_2DROP << OP_TRUE;
|
||||
}
|
||||
|
||||
bool DecodeClaimScript(const CScript& scriptIn, int& op, std::vector<std::vector<unsigned char> >& vvchParams)
|
||||
{
|
||||
CScript::const_iterator pc = scriptIn.begin();
|
||||
return DecodeClaimScript(scriptIn, op, vvchParams, pc);
|
||||
}
|
||||
|
||||
bool DecodeClaimScript(const CScript& scriptIn, int& op, std::vector<std::vector<unsigned char> >& vvchParams, CScript::const_iterator& pc)
|
||||
{
|
||||
opcodetype opcode;
|
||||
if (!scriptIn.GetOp(pc, opcode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (opcode != OP_CLAIM_NAME && opcode != OP_SUPPORT_CLAIM && opcode != OP_UPDATE_CLAIM)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
op = opcode;
|
||||
|
||||
std::vector<unsigned char> vchParam1;
|
||||
std::vector<unsigned char> vchParam2;
|
||||
std::vector<unsigned char> vchParam3;
|
||||
// Valid formats:
|
||||
// OP_CLAIM_NAME vchName vchValue OP_2DROP OP_DROP pubkeyscript
|
||||
// OP_UPDATE_CLAIM vchName vchClaimId vchValue OP_2DROP OP_2DROP pubkeyscript
|
||||
// OP_SUPPORT_CLAIM vchName vchClaimId OP_2DROP OP_DROP pubkeyscript
|
||||
// All others are invalid.
|
||||
|
||||
if (!scriptIn.GetOp(pc, opcode, vchParam1) || opcode < 0 || opcode > OP_PUSHDATA4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!scriptIn.GetOp(pc, opcode, vchParam2) || opcode < 0 || opcode > OP_PUSHDATA4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (op == OP_UPDATE_CLAIM || op == OP_SUPPORT_CLAIM)
|
||||
{
|
||||
static const size_t claimIdHashSize = sizeof(uint160);
|
||||
if (vchParam2.size() != claimIdHashSize) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (op == OP_UPDATE_CLAIM)
|
||||
{
|
||||
if (!scriptIn.GetOp(pc, opcode, vchParam3) || opcode < 0 || opcode > OP_PUSHDATA4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!scriptIn.GetOp(pc, opcode) || opcode != OP_2DROP)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!scriptIn.GetOp(pc, opcode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ((op == OP_CLAIM_NAME || op == OP_SUPPORT_CLAIM) && opcode != OP_DROP)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if ((op == OP_UPDATE_CLAIM) && opcode != OP_2DROP)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
vvchParams.push_back(vchParam1);
|
||||
vvchParams.push_back(vchParam2);
|
||||
if (op == OP_UPDATE_CLAIM)
|
||||
{
|
||||
vvchParams.push_back(vchParam3);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint160 ClaimIdHash(const uint256& txhash, uint32_t nOut)
|
||||
{
|
||||
std::vector<unsigned char> claimToHash(txhash.begin(), txhash.end());
|
||||
std::vector<unsigned char> vchnOut = uint32_t_to_vch(nOut);
|
||||
claimToHash.insert(claimToHash.end(), vchnOut.begin(), vchnOut.end());
|
||||
return Hash160(claimToHash);
|
||||
}
|
||||
|
||||
CScript StripClaimScriptPrefix(const CScript& scriptIn)
|
||||
{
|
||||
int op;
|
||||
return StripClaimScriptPrefix(scriptIn, op);
|
||||
}
|
||||
|
||||
CScript StripClaimScriptPrefix(const CScript& scriptIn, int& op)
|
||||
{
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
CScript::const_iterator pc = scriptIn.begin();
|
||||
|
||||
if (!DecodeClaimScript(scriptIn, op, vvchParams, pc))
|
||||
{
|
||||
return scriptIn;
|
||||
}
|
||||
|
||||
return CScript(pc, scriptIn.end());
|
||||
}
|
||||
|
||||
size_t ClaimScriptSize(const CScript& scriptIn)
|
||||
{
|
||||
CScript strippedScript = StripClaimScriptPrefix(scriptIn);
|
||||
return scriptIn.size() - strippedScript.size();
|
||||
}
|
||||
|
||||
size_t ClaimNameSize(const CScript& scriptIn)
|
||||
{
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
CScript::const_iterator pc = scriptIn.begin();
|
||||
int op;
|
||||
if (!DecodeClaimScript(scriptIn, op, vvchParams, pc))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return vvchParams[0].size();
|
||||
}
|
||||
}
|
||||
|
||||
CAmount CalcMinClaimTrieFee(const CTransaction& tx, const CAmount &minFeePerNameClaimChar)
|
||||
{
|
||||
if (minFeePerNameClaimChar == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
CAmount min_fee = 0;
|
||||
BOOST_FOREACH(const CTxOut& txout, tx.vout)
|
||||
{
|
||||
int op;
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
if (DecodeClaimScript(txout.scriptPubKey, op, vvchParams))
|
||||
{
|
||||
if (op == OP_CLAIM_NAME)
|
||||
{
|
||||
int claim_name_size = vvchParams[0].size();
|
||||
min_fee += claim_name_size*minFeePerNameClaimChar;
|
||||
}
|
||||
}
|
||||
}
|
||||
return min_fee;
|
||||
}
|
45
src/nameclaim.h
Normal file
45
src/nameclaim.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
#ifndef BITCOIN_NAMECLAIM_H
|
||||
#define BITCOIN_NAMECLAIM_H
|
||||
|
||||
#include "amount.h"
|
||||
#include "script/script.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "uint256.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
// This is the minimum claim fee per character in the name of an OP_CLAIM_NAME command that must
|
||||
// be attached to transactions for it to be accepted into the memory pool.
|
||||
// Rationale: current implementation of the claim trie uses more memory for longer name claims
|
||||
// due to the fact that each chracater is assigned a trie node regardless of whether it contains
|
||||
// any claims or not. In the future, we can switch to a radix tree implementation where
|
||||
// empty nodes do not take up any memory and the minimum fee can be priced on a per claim
|
||||
// basis.
|
||||
#define MIN_FEE_PER_NAMECLAIM_CHAR 200000
|
||||
|
||||
// This is the max claim script size in bytes, not including the script pubkey part of the script.
|
||||
// Scripts exceeding this size are rejected in CheckTransaction in main.cpp
|
||||
#define MAX_CLAIM_SCRIPT_SIZE 8192
|
||||
|
||||
// This is the max claim name size in bytes, for all claim trie transactions.
|
||||
// Scripts exceeding this size are rejected in CheckTransaction in main.cpp
|
||||
#define MAX_CLAIM_NAME_SIZE 255
|
||||
|
||||
CScript ClaimNameScript(std::string name, std::string value);
|
||||
CScript SupportClaimScript(std::string name, uint160 claimId);
|
||||
CScript UpdateClaimScript(std::string name, uint160 claimId, std::string value);
|
||||
bool DecodeClaimScript(const CScript& scriptIn, int& op, std::vector<std::vector<unsigned char> >& vvchParams);
|
||||
bool DecodeClaimScript(const CScript& scriptIn, int& op, std::vector<std::vector<unsigned char> >& vvchParams, CScript::const_iterator& pc);
|
||||
CScript StripClaimScriptPrefix(const CScript& scriptIn);
|
||||
CScript StripClaimScriptPrefix(const CScript& scriptIn, int& op);
|
||||
uint160 ClaimIdHash(const uint256& txhash, uint32_t nOut);
|
||||
std::vector<unsigned char> uint32_t_to_vch(uint32_t n);
|
||||
uint32_t vch_to_uint32_t(std::vector<unsigned char>& vchN);
|
||||
// get size of the claim script, minus the script pubkey part
|
||||
size_t ClaimScriptSize(const CScript& scriptIn);
|
||||
// get size of the name in a claim script, returns 0 if scriptin is not a claimetrie transaction
|
||||
size_t ClaimNameSize(const CScript& scriptIn);
|
||||
// calculate the minimum fee (mempool rule) required for transaction
|
||||
CAmount CalcMinClaimTrieFee(const CTransaction& tx, const CAmount &minFeePerNameClaimChar);
|
||||
|
||||
#endif // BITCOIN_NAMECLAIM_H
|
|
@ -1636,6 +1636,7 @@ void CConnman::ThreadDNSAddressSeed()
|
|||
} else {
|
||||
std::vector<CNetAddr> vIPs;
|
||||
std::vector<CAddress> vAdd;
|
||||
// NOTE: After we fork, we can require additional service bits
|
||||
ServiceFlags requiredServiceBits = GetDesirableServiceFlags(NODE_NONE);
|
||||
std::string host = strprintf("x%x.%s", requiredServiceBits, seed);
|
||||
CNetAddr resolveSource;
|
||||
|
|
|
@ -1549,6 +1549,7 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::ve
|
|||
// nMinimumChainWork, even if a peer has a chain past our tip,
|
||||
// as an anti-DoS measure.
|
||||
if (IsOutboundDisconnectionCandidate(pfrom)) {
|
||||
LogPrintf("Disconnecting outbound peer %d (%s < %s) -- headers chain has insufficient work\n", pfrom->GetId(), nodestate->pindexBestKnownBlock->nChainWork.GetHex(), nMinimumChainWork.GetHex());
|
||||
LogPrintf("Disconnecting outbound peer %d -- headers chain has insufficient work\n", pfrom->GetId());
|
||||
pfrom->fDisconnect = true;
|
||||
}
|
||||
|
@ -1647,6 +1648,8 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
vRecv >> nVersion >> nServiceInt >> nTime >> addrMe;
|
||||
nSendVersion = std::min(nVersion, PROTOCOL_VERSION);
|
||||
nServices = ServiceFlags(nServiceInt);
|
||||
LogPrint(BCLog::NET, "peer=%d services (%08x offered, %08x expected);\n", pfrom->GetId(), nServices, GetDesirableServiceFlags(nServices));
|
||||
|
||||
if (!pfrom->fInbound)
|
||||
{
|
||||
connman->SetServices(pfrom->addr, nServices);
|
||||
|
@ -2014,6 +2017,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
|
||||
else if (strCommand == NetMsgType::GETBLOCKS)
|
||||
{
|
||||
LogPrintf("%s: Got GETBLOCKS message\n", __func__);
|
||||
CBlockLocator locator;
|
||||
uint256 hashStop;
|
||||
vRecv >> locator >> hashStop;
|
||||
|
@ -3516,17 +3520,24 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
|
|||
std::vector<CInv> vInv;
|
||||
{
|
||||
LOCK(pto->cs_inventory);
|
||||
vInv.reserve(std::max<size_t>(pto->vInventoryBlockToSend.size(), INVENTORY_BROADCAST_MAX));
|
||||
/* vInv.reserve(std::max<size_t>(pto->vInventoryBlockToSend.size(), INVENTORY_BROADCAST_MAX)); */
|
||||
// FIXME: Bitcoin bug?!
|
||||
vInv.reserve(std::min<size_t>(pto->vInventoryBlockToSend.size(), INVENTORY_BROADCAST_MAX));
|
||||
|
||||
// Add blocks
|
||||
size_t count = 0;
|
||||
for (const uint256& hash : pto->vInventoryBlockToSend) {
|
||||
vInv.push_back(CInv(MSG_BLOCK, hash));
|
||||
if (vInv.size() == MAX_INV_SZ) {
|
||||
connman->PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
|
||||
vInv.clear();
|
||||
}
|
||||
if (++count >= INVENTORY_BROADCAST_MAX)
|
||||
break;
|
||||
}
|
||||
pto->vInventoryBlockToSend.clear();
|
||||
pto->vInventoryBlockToSend.erase(pto->vInventoryBlockToSend.begin(),
|
||||
pto->vInventoryBlockToSend.begin() + count);
|
||||
//pto->vInventoryBlockToSend.clear();
|
||||
|
||||
// Check whether periodic sends should happen
|
||||
bool fSendTrickle = pto->fWhitelisted;
|
||||
|
|
|
@ -115,7 +115,8 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason)
|
|||
unsigned int nDataOut = 0;
|
||||
txnouttype whichType;
|
||||
for (const CTxOut& txout : tx.vout) {
|
||||
if (!::IsStandard(txout.scriptPubKey, whichType)) {
|
||||
const CScript& scriptPubKey = StripClaimScriptPrefix(txout.scriptPubKey);
|
||||
if (!::IsStandard(scriptPubKey, whichType)) {
|
||||
reason = "scriptpubkey";
|
||||
return false;
|
||||
}
|
||||
|
@ -168,7 +169,7 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
|
|||
std::vector<std::vector<unsigned char> > vSolutions;
|
||||
txnouttype whichType;
|
||||
// get the scriptPubKey corresponding to this input:
|
||||
const CScript& prevScript = prev.scriptPubKey;
|
||||
const CScript& prevScript = StripClaimScriptPrefix(prev.scriptPubKey);
|
||||
if (!Solver(prevScript, whichType, vSolutions))
|
||||
return false;
|
||||
|
||||
|
|
72
src/pow.cpp
72
src/pow.cpp
|
@ -4,6 +4,7 @@
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <pow.h>
|
||||
#include <lbry.h>
|
||||
|
||||
#include <arith_uint256.h>
|
||||
#include <chain.h>
|
||||
|
@ -12,38 +13,65 @@
|
|||
|
||||
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
|
||||
{
|
||||
assert(pindexLast != nullptr);
|
||||
unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact();
|
||||
// Genesis block
|
||||
if (pindexLast == nullptr)
|
||||
return nProofOfWorkLimit;
|
||||
|
||||
// Only change once per difficulty adjustment interval
|
||||
if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0)
|
||||
if (params.fPowAllowMinDifficultyBlocks && pindexLast->nHeight >= 277299)
|
||||
{
|
||||
if (params.fPowAllowMinDifficultyBlocks)
|
||||
{
|
||||
// Special difficulty rule for testnet:
|
||||
// If the new block's timestamp is more than 2* 10 minutes
|
||||
// then allow mining of a min-difficulty block.
|
||||
if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2)
|
||||
return nProofOfWorkLimit;
|
||||
else
|
||||
{
|
||||
// Return the last non-special-min-difficulty-rules-block
|
||||
const CBlockIndex* pindex = pindexLast;
|
||||
while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit)
|
||||
pindex = pindex->pprev;
|
||||
return pindex->nBits;
|
||||
}
|
||||
// Special difficulty rule for testnet:
|
||||
// If the new block's timestamp is twice the target block time
|
||||
// then allow mining of a min-difficulty block.
|
||||
// This is to prevent the testnet from gettig stuck when a large amount
|
||||
// of hashrate drops off the network.
|
||||
// This rule was not implemented properly until testnet block 277299.
|
||||
if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2){
|
||||
return nProofOfWorkLimit;
|
||||
}
|
||||
return pindexLast->nBits;
|
||||
}
|
||||
|
||||
// Go back by what we want to be 14 days worth of blocks
|
||||
int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1);
|
||||
/* // Only change once per difficulty adjustment interval */
|
||||
/* if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0) */
|
||||
/* { */
|
||||
/* if (params.fPowAllowMinDifficultyBlocks) */
|
||||
/* { */
|
||||
/* // Special difficulty rule for testnet: */
|
||||
/* // If the new block's timestamp is more than 2* 10 minutes */
|
||||
/* // then allow mining of a min-difficulty block. */
|
||||
/* if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2) */
|
||||
/* return nProofOfWorkLimit; */
|
||||
/* else */
|
||||
/* { */
|
||||
/* // Return the last non-special-min-difficulty-rules-block */
|
||||
/* const CBlockIndex* pindex = pindexLast; */
|
||||
/* while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit) */
|
||||
/* pindex = pindex->pprev; */
|
||||
/* return pindex->nBits; */
|
||||
/* } */
|
||||
/* } */
|
||||
/* return pindexLast->nBits; */
|
||||
/* } */
|
||||
|
||||
/* // Go back by what we want to be 14 days worth of blocks */
|
||||
/* int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1); */
|
||||
/* assert(nHeightFirst >= 0); */
|
||||
/* const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst); */
|
||||
/* assert(pindexFirst); */
|
||||
|
||||
/* return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params); */
|
||||
|
||||
// Go back the full period unless it's the first retarget after genesis.
|
||||
int blockstogoback = params.DifficultyAdjustmentInterval()-1;
|
||||
if ((pindexLast->nHeight+1) != params.DifficultyAdjustmentInterval())
|
||||
blockstogoback = params.DifficultyAdjustmentInterval();
|
||||
|
||||
int nHeightFirst = pindexLast->nHeight - blockstogoback;
|
||||
assert(nHeightFirst >= 0);
|
||||
const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst);
|
||||
assert(pindexFirst);
|
||||
|
||||
return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params);
|
||||
return CalculateLbryNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params);
|
||||
}
|
||||
|
||||
unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
|
||||
|
|
|
@ -9,20 +9,30 @@
|
|||
#include <tinyformat.h>
|
||||
#include <utilstrencodings.h>
|
||||
#include <crypto/common.h>
|
||||
#include <streams.h>
|
||||
|
||||
uint256 CBlockHeader::GetHash() const
|
||||
{
|
||||
return SerializeHash(*this);
|
||||
}
|
||||
|
||||
uint256 CBlockHeader::GetPoWHash() const
|
||||
{
|
||||
CDataStream ds(SER_GETHASH, PROTOCOL_VERSION);
|
||||
ds << *this;
|
||||
std::vector<unsigned char> input(ds.begin(), ds.end());
|
||||
return PoWHash(input);
|
||||
}
|
||||
|
||||
std::string CBlock::ToString() const
|
||||
{
|
||||
std::stringstream s;
|
||||
s << strprintf("CBlock(hash=%s, ver=0x%08x, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n",
|
||||
s << strprintf("CBlock(hash=%s, ver=0x%08x, hashPrevBlock=%s, hashMerkleRoot=%s, hashClaimTrie=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n",
|
||||
GetHash().ToString(),
|
||||
nVersion,
|
||||
hashPrevBlock.ToString(),
|
||||
hashMerkleRoot.ToString(),
|
||||
hashClaimTrie.ToString(),
|
||||
nTime, nBits, nNonce,
|
||||
vtx.size());
|
||||
for (const auto& tx : vtx) {
|
||||
|
|
|
@ -24,6 +24,7 @@ public:
|
|||
int32_t nVersion;
|
||||
uint256 hashPrevBlock;
|
||||
uint256 hashMerkleRoot;
|
||||
uint256 hashClaimTrie;
|
||||
uint32_t nTime;
|
||||
uint32_t nBits;
|
||||
uint32_t nNonce;
|
||||
|
@ -40,6 +41,7 @@ public:
|
|||
READWRITE(this->nVersion);
|
||||
READWRITE(hashPrevBlock);
|
||||
READWRITE(hashMerkleRoot);
|
||||
READWRITE(hashClaimTrie);
|
||||
READWRITE(nTime);
|
||||
READWRITE(nBits);
|
||||
READWRITE(nNonce);
|
||||
|
@ -50,6 +52,7 @@ public:
|
|||
nVersion = 0;
|
||||
hashPrevBlock.SetNull();
|
||||
hashMerkleRoot.SetNull();
|
||||
hashClaimTrie.SetNull();
|
||||
nTime = 0;
|
||||
nBits = 0;
|
||||
nNonce = 0;
|
||||
|
@ -62,6 +65,8 @@ public:
|
|||
|
||||
uint256 GetHash() const;
|
||||
|
||||
uint256 GetPoWHash() const;
|
||||
|
||||
int64_t GetBlockTime() const
|
||||
{
|
||||
return (int64_t)nTime;
|
||||
|
@ -110,6 +115,7 @@ public:
|
|||
block.nVersion = nVersion;
|
||||
block.hashPrevBlock = hashPrevBlock;
|
||||
block.hashMerkleRoot = hashMerkleRoot;
|
||||
block.hashClaimTrie = hashClaimTrie;
|
||||
block.nTime = nTime;
|
||||
block.nBits = nBits;
|
||||
block.nNonce = nNonce;
|
||||
|
|
|
@ -128,12 +128,20 @@ bool CMessageHeader::IsValid(const MessageStartChars& pchMessageStartIn) const
|
|||
return true;
|
||||
}
|
||||
|
||||
// NOTE: After we fork, we can require these service bits
|
||||
//
|
||||
/* ServiceFlags GetDesirableServiceFlags(ServiceFlags services) { */
|
||||
/* if ((services & NODE_NETWORK_LIMITED) && g_initial_block_download_completed) { */
|
||||
/* return ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS); */
|
||||
/* } */
|
||||
/* return ServiceFlags(NODE_NETWORK | NODE_WITNESS); */
|
||||
/* } */
|
||||
|
||||
ServiceFlags GetDesirableServiceFlags(ServiceFlags services) {
|
||||
if ((services & NODE_NETWORK_LIMITED) && g_initial_block_download_completed) {
|
||||
return ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS);
|
||||
if ((services & NODE_NETWORK) && g_initial_block_download_completed) {
|
||||
return ServiceFlags(NODE_NETWORK | NODE_BLOOM);
|
||||
}
|
||||
return ServiceFlags(NODE_NETWORK | NODE_WITNESS);
|
||||
return ServiceFlags(NODE_NETWORK | NODE_BLOOM);
|
||||
}
|
||||
|
||||
void SetServiceFlagsIBDCache(bool state) {
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <sync.h>
|
||||
#include <txdb.h>
|
||||
#include <txmempool.h>
|
||||
#include <uint256.h>
|
||||
#include <util.h>
|
||||
#include <utilstrencodings.h>
|
||||
#include <hash.h>
|
||||
|
@ -66,12 +67,12 @@ double GetDifficulty(const CBlockIndex* blockindex)
|
|||
double dDiff =
|
||||
(double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
|
||||
|
||||
while (nShift < 29)
|
||||
while (nShift < 31)
|
||||
{
|
||||
dDiff *= 256.0;
|
||||
nShift++;
|
||||
}
|
||||
while (nShift > 29)
|
||||
while (nShift > 31)
|
||||
{
|
||||
dDiff /= 256.0;
|
||||
nShift--;
|
||||
|
@ -94,6 +95,7 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex)
|
|||
result.pushKV("version", blockindex->nVersion);
|
||||
result.pushKV("versionHex", strprintf("%08x", blockindex->nVersion));
|
||||
result.pushKV("merkleroot", blockindex->hashMerkleRoot.GetHex());
|
||||
result.pushKV("nameclaimroot", blockindex->hashClaimTrie.GetHex());
|
||||
result.pushKV("time", (int64_t)blockindex->nTime);
|
||||
result.pushKV("mediantime", (int64_t)blockindex->GetMedianTimePast());
|
||||
result.pushKV("nonce", (uint64_t)blockindex->nNonce);
|
||||
|
@ -127,6 +129,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
|
|||
result.pushKV("version", block.nVersion);
|
||||
result.pushKV("versionHex", strprintf("%08x", block.nVersion));
|
||||
result.pushKV("merkleroot", block.hashMerkleRoot.GetHex());
|
||||
result.pushKV("nameclaimroot", block.hashClaimTrie.GetHex());
|
||||
UniValue txs(UniValue::VARR);
|
||||
for(const auto& tx : block.vtx)
|
||||
{
|
||||
|
@ -695,6 +698,7 @@ static UniValue getblockheader(const JSONRPCRequest& request)
|
|||
" \"version\" : n, (numeric) The block version\n"
|
||||
" \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n"
|
||||
" \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
|
||||
" \"nameclaimroot\" : \"xxxx\", (string) The hash of the root of the name claim trie\n"
|
||||
" \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
|
||||
" \"mediantime\" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n"
|
||||
" \"nonce\" : n, (numeric) The nonce\n"
|
||||
|
@ -780,6 +784,7 @@ static UniValue getblock(const JSONRPCRequest& request)
|
|||
" \"version\" : n, (numeric) The block version\n"
|
||||
" \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n"
|
||||
" \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
|
||||
" \"nameclaimroot\" : \"xxxx\", (string) The hash of the root of the name claim trie\n"
|
||||
" \"tx\" : [ (array of string) The transaction ids\n"
|
||||
" \"transactionid\" (string) The transaction id\n"
|
||||
" ,...\n"
|
||||
|
|
802
src/rpc/claimtrie.cpp
Normal file
802
src/rpc/claimtrie.cpp
Normal file
|
@ -0,0 +1,802 @@
|
|||
#include <claimtrie.h>
|
||||
#include <coins.h>
|
||||
#include <core_io.h>
|
||||
#include <nameclaim.h>
|
||||
#include <rpc/server.h>
|
||||
#include <txdb.h>
|
||||
#include <txmempool.h>
|
||||
#include <univalue.h>
|
||||
#include <validation.h>
|
||||
|
||||
// Maximum block decrement that is allowed from rpc calls
|
||||
const int MAX_RPC_BLOCK_DECREMENTS = 50;
|
||||
|
||||
static uint160 ParseClaimtrieId(const UniValue& v, const std::string& strName)
|
||||
{
|
||||
static constexpr size_t claimIdHexLength = 40;
|
||||
|
||||
std::string strHex;
|
||||
if (v.isStr())
|
||||
strHex = v.get_str();
|
||||
if (!IsHex(strHex)) // Note: IsHex("") is false
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strName + " must be a 20-character hexadecimal string (not '" + strHex + "')");
|
||||
if (strHex.length() != claimIdHexLength)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be of length %d (not %d)", strName, claimIdHexLength, strHex.length()));
|
||||
|
||||
uint160 result;
|
||||
result.SetHex(strHex);
|
||||
return result;
|
||||
}
|
||||
|
||||
static CBlockIndex* BlockHashIndex(const uint256& blockHash)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
|
||||
if (mapBlockIndex.count(blockHash) == 0)
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
||||
|
||||
CBlockIndex* pblockIndex = mapBlockIndex[blockHash];
|
||||
if (!chainActive.Contains(pblockIndex))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not in main chain");
|
||||
|
||||
if (chainActive.Tip()->nHeight > (pblockIndex->nHeight + MAX_RPC_BLOCK_DECREMENTS))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Block is too deep");
|
||||
|
||||
return pblockIndex;
|
||||
}
|
||||
|
||||
static std::string encodeValue(const std::string& value)
|
||||
{
|
||||
// FIXME: match old encoding??
|
||||
return SanitizeString(value);
|
||||
}
|
||||
|
||||
static UniValue getclaimsintrie(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() > 0)
|
||||
throw std::runtime_error(
|
||||
"getclaimsintrie\n"
|
||||
"Return all claims in the name trie.\n"
|
||||
"Arguments:\n"
|
||||
"None\n"
|
||||
"Result: \n"
|
||||
"[\n"
|
||||
" {\n"
|
||||
" \"name\" (string) the name claimed\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"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
"]\n"
|
||||
);
|
||||
|
||||
LOCK(cs_main);
|
||||
|
||||
CCoinsViewCache coinsCache(pcoinsTip.get());
|
||||
CClaimTrieCache trieCache(pclaimTrie);
|
||||
|
||||
if (!request.params.empty()) {
|
||||
CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(request.params[0], "blockhash (optional parameter 1)"));
|
||||
if (!RollBackTo(blockIndex, coinsCache, trieCache))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Rollback failure");
|
||||
}
|
||||
|
||||
UniValue ret(UniValue::VARR);
|
||||
std::vector<namedNodeType> nodes = pclaimTrie->flattenTrie();
|
||||
for (std::vector<namedNodeType>::iterator it = nodes.begin(); it != nodes.end(); ++it)
|
||||
{
|
||||
if (!it->second.claims.empty())
|
||||
{
|
||||
UniValue node(UniValue::VOBJ);
|
||||
node.pushKV("name", encodeValue(it->first));
|
||||
UniValue claims(UniValue::VARR);
|
||||
for (std::vector<CClaimValue>::iterator itClaims = it->second.claims.begin(); itClaims != it->second.claims.end(); ++itClaims)
|
||||
{
|
||||
UniValue claim(UniValue::VOBJ);
|
||||
claim.pushKV("claimId", itClaims->claimId.GetHex());
|
||||
claim.pushKV("txid", itClaims->outPoint.hash.GetHex());
|
||||
claim.pushKV("n", (int)itClaims->outPoint.n);
|
||||
claim.pushKV("amount", ValueFromAmount(itClaims->nAmount));
|
||||
claim.pushKV("height", itClaims->nHeight);
|
||||
const Coin& coin = coinsCache.AccessCoin(itClaims->outPoint);
|
||||
if (coin.IsSpent())
|
||||
{
|
||||
LogPrintf("%s: the specified txout of %s appears to have been spent\n", __func__, itClaims->outPoint.hash.GetHex());
|
||||
claim.pushKV("error", "Txout spent");
|
||||
}
|
||||
else
|
||||
{
|
||||
int op;
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
if (!DecodeClaimScript(coin.out.scriptPubKey, op, vvchParams))
|
||||
{
|
||||
LogPrintf("%s: the specified txout of %s does not have an claim command\n", __func__, itClaims->outPoint.hash.GetHex());
|
||||
}
|
||||
std::string sValue(vvchParams[1].begin(), vvchParams[1].end());
|
||||
claim.pushKV("value", encodeValue(sValue));
|
||||
}
|
||||
claims.push_back(claim);
|
||||
}
|
||||
node.pushKV("claims", claims);
|
||||
ret.push_back(node);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static UniValue getclaimtrie(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() > 0)
|
||||
throw std::runtime_error(
|
||||
"getclaimtrie\n"
|
||||
"Return the entire claim trie.\n"
|
||||
"Arguments:\n"
|
||||
"None\n"
|
||||
"Result: \n"
|
||||
"{\n"
|
||||
" \"name\" (string) the name of the node\n"
|
||||
" \"hash\" (string) the hash of the node\n"
|
||||
" \"txid\" (string) (if value exists) the hash of the transaction which has successfully claimed this name\n"
|
||||
" \"n\" (numeric) (if value exists) vout value\n"
|
||||
" \"value\" (numeric) (if value exists) txout value\n"
|
||||
" \"height\" (numeric) (if value exists) the height of the block in which this transaction is located\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
LOCK(cs_main);
|
||||
UniValue ret(UniValue::VARR);
|
||||
|
||||
std::vector<namedNodeType> nodes = pclaimTrie->flattenTrie();
|
||||
for (std::vector<namedNodeType>::iterator it = nodes.begin(); it != nodes.end(); ++it)
|
||||
{
|
||||
UniValue node(UniValue::VOBJ);
|
||||
node.pushKV("name", encodeValue(it->first));
|
||||
node.pushKV("hash", it->second.hash.GetHex());
|
||||
CClaimValue claim;
|
||||
if (it->second.getBestClaim(claim))
|
||||
{
|
||||
node.pushKV("txid", claim.outPoint.hash.GetHex());
|
||||
node.pushKV("n", (int)claim.outPoint.n);
|
||||
node.pushKV("value", ValueFromAmount(claim.nAmount));
|
||||
node.pushKV("height", claim.nHeight);
|
||||
}
|
||||
ret.push_back(node);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool getValueForClaim(const CCoinsViewCache& coinsCache, const COutPoint& out, std::string& sValue)
|
||||
{
|
||||
const Coin& coin = coinsCache.AccessCoin(out);
|
||||
if (coin.IsSpent())
|
||||
{
|
||||
LogPrintf("%s: the specified txout of %s appears to have been spent\n", __func__, out.hash.GetHex());
|
||||
return true;
|
||||
}
|
||||
|
||||
int op;
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
if (!DecodeClaimScript(coin.out.scriptPubKey, op, vvchParams))
|
||||
{
|
||||
LogPrintf("%s: the specified txout of %s does not have a name claim command\n", __func__, out.hash.GetHex());
|
||||
return false;
|
||||
}
|
||||
if (op == OP_CLAIM_NAME)
|
||||
{
|
||||
sValue = std::string(vvchParams[1].begin(), vvchParams[1].end());
|
||||
}
|
||||
else if (op == OP_UPDATE_CLAIM)
|
||||
{
|
||||
sValue = std::string(vvchParams[2].begin(), vvchParams[2].end());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static UniValue getvalueforname(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() != 1)
|
||||
throw std::runtime_error(
|
||||
"getvalueforname \"name\"\n"
|
||||
"Return the 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"
|
||||
" associated with the name\n"
|
||||
" at the block specified\n"
|
||||
" by this block hash.\n"
|
||||
" If none is given,\n"
|
||||
" the latest active\n"
|
||||
" block will be used.\n"
|
||||
"Result: \n"
|
||||
"\"value\" (string) the value of the name, if it exists\n"
|
||||
"\"claimId\" (string) the claimId for this name claim\n"
|
||||
"\"txid\" (string) the hash of the transaction which successfully claimed the name\n"
|
||||
"\"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");
|
||||
|
||||
LOCK(cs_main);
|
||||
|
||||
CCoinsViewCache coinsCache(pcoinsTip.get());
|
||||
CClaimTrieCache trieCache(pclaimTrie);
|
||||
|
||||
if (request.params.size() > 1) {
|
||||
CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(request.params[1], "blockhash (optional parameter 2)"));
|
||||
if (!RollBackTo(blockIndex, coinsCache, trieCache))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Rollback failure");
|
||||
}
|
||||
|
||||
const auto& name = request.params[0].get_str();
|
||||
UniValue ret(UniValue::VOBJ);
|
||||
|
||||
CClaimValue claim;
|
||||
if (!trieCache.getInfoForName(name, claim))
|
||||
return ret; // they may have asked for a name that doesn't exist (which is not an error)
|
||||
|
||||
std::string sValue;
|
||||
if (!getValueForClaim(coinsCache, claim.outPoint, sValue))
|
||||
return ret;
|
||||
|
||||
const auto nEffectiveAmount = trieCache.getEffectiveAmountForClaim(name, claim.claimId);
|
||||
|
||||
ret.pushKV("value", encodeValue(sValue));
|
||||
ret.pushKV("claimId", claim.claimId.GetHex());
|
||||
ret.pushKV("txid", claim.outPoint.hash.GetHex());
|
||||
ret.pushKV("n", (int)claim.outPoint.n);
|
||||
ret.pushKV("amount", claim.nAmount);
|
||||
ret.pushKV("effective amount", nEffectiveAmount);
|
||||
ret.pushKV("height", claim.nHeight);
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef std::pair<CClaimValue, std::vector<CSupportValue> > claimAndSupportsType;
|
||||
typedef std::map<uint160, claimAndSupportsType> claimSupportMapType;
|
||||
|
||||
UniValue supportToJSON(const CSupportValue& support)
|
||||
{
|
||||
UniValue ret(UniValue::VOBJ);
|
||||
ret.push_back(Pair("txid", support.outPoint.hash.GetHex()));
|
||||
ret.push_back(Pair("n", (int)support.outPoint.n));
|
||||
ret.push_back(Pair("nHeight", support.nHeight));
|
||||
ret.push_back(Pair("nValidAtHeight", support.nValidAtHeight));
|
||||
ret.push_back(Pair("nAmount", support.nAmount));
|
||||
return ret;
|
||||
}
|
||||
|
||||
UniValue claimAndSupportsToJSON(CAmount nEffectiveAmount, claimSupportMapType::const_iterator itClaimsAndSupports)
|
||||
{
|
||||
const CClaimValue& claim = itClaimsAndSupports->second.first;
|
||||
const std::vector<CSupportValue>& supports = itClaimsAndSupports->second.second;
|
||||
|
||||
UniValue supportObjs(UniValue::VARR);
|
||||
for (const auto& support: supports)
|
||||
supportObjs.push_back(supportToJSON(support));
|
||||
|
||||
UniValue result(UniValue::VOBJ);
|
||||
result.pushKV("claimId", itClaimsAndSupports->first.GetHex());
|
||||
result.pushKV("txid", claim.outPoint.hash.GetHex());
|
||||
result.pushKV("n", (int)claim.outPoint.n);
|
||||
result.pushKV("nHeight", claim.nHeight);
|
||||
result.pushKV("nValidAtHeight", claim.nValidAtHeight);
|
||||
result.pushKV("nAmount", claim.nAmount);
|
||||
result.pushKV("nEffectiveAmount", nEffectiveAmount);
|
||||
result.pushKV("supports", supportObjs);
|
||||
return result;
|
||||
}
|
||||
|
||||
UniValue getclaimsforname(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() != 1)
|
||||
throw std::runtime_error(
|
||||
"getclaimsforname\n"
|
||||
"Return all claims and supports for a name\n"
|
||||
"Arguments: \n"
|
||||
"1. \"name\" (string) the name for which to get claims and supports\n"
|
||||
"Result:\n"
|
||||
"{\n"
|
||||
" \"nLastTakeoverheight\" (numeric) the last height at which ownership of the name changed\n"
|
||||
" \"claims\": [ (array of object) claims for this name\n"
|
||||
" {\n"
|
||||
" \"claimId\" (string) the claimId of this claim\n"
|
||||
" \"txid\" (string) the txid of this claim\n"
|
||||
" \"n\" (numeric) the index of the claim in the transaction's list of outputs\n"
|
||||
" \"nHeight\" (numeric) the height at which the claim was included in the blockchain\n"
|
||||
" \"nValidAtHeight\" (numeric) the height at which the claim became/becomes valid\n"
|
||||
" \"nAmount\" (numeric) the amount of the claim\n"
|
||||
" \"nEffectiveAmount\" (numeric) the total effective amount of the claim, taking into effect whether the claim or support has reached its nValidAtHeight\n"
|
||||
" \"supports\" : [ (array of object) supports for this claim\n"
|
||||
" \"txid\" (string) the txid of the support\n"
|
||||
" \"n\" (numeric) the index of the support in the transaction's list of outputs\n"
|
||||
" \"nHeight\" (numeric) the height at which the support was included in the blockchain\n"
|
||||
" \"nValidAtHeight\" (numeric) the height at which the support became/becomes valid\n"
|
||||
" \"nAmount\" (numeric) the amount of the support\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
" ],\n"
|
||||
" \"unmatched supports\": [ (array of object) supports that did not match a claim for this name\n"
|
||||
" {\n"
|
||||
" \"txid\" (string) the txid of the support\n"
|
||||
" \"n\" (numeric) the index of the support in the transaction's list of outputs\n"
|
||||
" \"nHeight\" (numeric) the height at which the support was included in the blockchain\n"
|
||||
" \"nValidAtHeight\" (numeric) the height at which the support became/becomes valid\n"
|
||||
" \"nAmount\" (numeric) the amount of the support\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
LOCK(cs_main);
|
||||
|
||||
CCoinsViewCache coinsCache(pcoinsTip.get());
|
||||
CClaimTrieCache trieCache(pclaimTrie);
|
||||
|
||||
if (request.params.size() > 1) {
|
||||
CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(request.params[1], "blockhash (optional parameter 2)"));
|
||||
if (!RollBackTo(blockIndex, coinsCache, trieCache))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Rollback failure");
|
||||
}
|
||||
|
||||
std::string name = request.params[0].get_str();
|
||||
claimsForNameType claimsForName = pclaimTrie->getClaimsForName(name);
|
||||
|
||||
|
||||
UniValue claimObjs(UniValue::VARR);
|
||||
claimSupportMapType claimSupportMap;
|
||||
UniValue unmatchedSupports(UniValue::VARR);
|
||||
|
||||
for (std::vector<CClaimValue>::const_iterator itClaims = claimsForName.claims.begin(); itClaims != claimsForName.claims.end(); ++itClaims)
|
||||
{
|
||||
claimAndSupportsType claimAndSupports = std::make_pair(*itClaims, std::vector<CSupportValue>());
|
||||
claimSupportMap.insert(std::pair<uint160, claimAndSupportsType>(itClaims->claimId, claimAndSupports));
|
||||
}
|
||||
|
||||
for (std::vector<CSupportValue>::const_iterator itSupports = claimsForName.supports.begin(); itSupports != claimsForName.supports.end(); ++itSupports)
|
||||
{
|
||||
claimSupportMapType::iterator itClaimAndSupports = claimSupportMap.find(itSupports->supportedClaimId);
|
||||
if (itClaimAndSupports == claimSupportMap.end())
|
||||
unmatchedSupports.push_back(supportToJSON(*itSupports));
|
||||
else
|
||||
itClaimAndSupports->second.second.push_back(*itSupports);
|
||||
}
|
||||
|
||||
UniValue result(UniValue::VOBJ);
|
||||
result.pushKV("nLastTakeoverHeight", claimsForName.nLastTakeoverHeight);
|
||||
|
||||
for (claimSupportMapType::const_iterator itClaimsAndSupports = claimSupportMap.begin(); itClaimsAndSupports != claimSupportMap.end(); ++itClaimsAndSupports)
|
||||
{
|
||||
const auto nEffectiveAmount = trieCache.getEffectiveAmountForClaim(claimsForName, itClaimsAndSupports->first);
|
||||
claimObjs.push_back(claimAndSupportsToJSON(nEffectiveAmount, itClaimsAndSupports));
|
||||
}
|
||||
|
||||
result.pushKV("claims", claimObjs);
|
||||
result.pushKV("unmatched supports", unmatchedSupports);
|
||||
return result;
|
||||
}
|
||||
|
||||
UniValue getclaimbyid(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() != 1)
|
||||
throw std::runtime_error(
|
||||
"getclaimbyid\n"
|
||||
"Get a claim by claim id\n"
|
||||
"Arguments: \n"
|
||||
"1. \"claimId\" (string) the claimId of this claim\n"
|
||||
"Result:\n"
|
||||
"{\n"
|
||||
" \"name\" (string) the name of the claim\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"
|
||||
" \"n\" (numeric) vout value\n"
|
||||
" \"amount\" (numeric) txout value\n"
|
||||
" \"effective amount\" (numeric) txout amount plus amount from all supports associated with the claim\n"
|
||||
" \"supports\" (array of object) supports for this claim\n"
|
||||
" [\n"
|
||||
" \"txid\" (string) the txid of the support\n"
|
||||
" \"n\" (numeric) the index of the support in the transaction's list of outputs\n"
|
||||
" \"height\" (numeric) the height at which the support was included in the blockchain\n"
|
||||
" \"valid at height\" (numeric) the height at which the support is valid\n"
|
||||
" \"amount\" (numeric) the amount of the support\n"
|
||||
" ]\n"
|
||||
" \"height\" (numeric) the height of the block in which this claim transaction is located\n"
|
||||
" \"valid at height\" (numeric) the height at which the claim is valid\n"
|
||||
"}\n");
|
||||
|
||||
LOCK(cs_main);
|
||||
uint160 claimId = ParseClaimtrieId(request.params[0], "Claim-id (parameter 1)");
|
||||
UniValue claim(UniValue::VOBJ);
|
||||
std::string name;
|
||||
CClaimValue claimValue;
|
||||
pclaimTrie->getClaimById(claimId, name, claimValue);
|
||||
if (claimValue.claimId == claimId)
|
||||
{
|
||||
std::vector<CSupportValue> supports;
|
||||
CAmount effectiveAmount = pclaimTrie->getEffectiveAmountForClaim(name, claimValue.claimId, &supports);
|
||||
|
||||
std::string sValue;
|
||||
claim.pushKV("name", name);
|
||||
CCoinsViewCache coinsCache(pcoinsTip.get());
|
||||
if (getValueForClaim(coinsCache, claimValue.outPoint, sValue))
|
||||
claim.pushKV("value", encodeValue(sValue));
|
||||
claim.pushKV("claimId", claimValue.claimId.GetHex());
|
||||
claim.pushKV("txid", claimValue.outPoint.hash.GetHex());
|
||||
claim.pushKV("n", (int) claimValue.outPoint.n);
|
||||
claim.pushKV("amount", claimValue.nAmount);
|
||||
claim.pushKV("effective amount", effectiveAmount);
|
||||
UniValue supportList(UniValue::VARR);
|
||||
for(const CSupportValue& support: supports) {
|
||||
UniValue supportEntry(UniValue::VOBJ);
|
||||
supportEntry.pushKV("txid", support.outPoint.hash.GetHex());
|
||||
supportEntry.pushKV("n", (int)support.outPoint.n);
|
||||
supportEntry.pushKV("height", support.nHeight);
|
||||
supportEntry.pushKV("valid at height", support.nValidAtHeight);
|
||||
supportEntry.pushKV("amount", support.nAmount);
|
||||
supportList.pushKVs(supportEntry);
|
||||
}
|
||||
claim.pushKV("supports", supportList);
|
||||
claim.pushKV("height", claimValue.nHeight);
|
||||
claim.pushKV("valid at height", claimValue.nValidAtHeight);
|
||||
}
|
||||
return claim;
|
||||
}
|
||||
|
||||
UniValue gettotalclaimednames(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() != 0)
|
||||
throw std::runtime_error(
|
||||
"gettotalclaimednames\n"
|
||||
"Return the total number of names that have been\n"
|
||||
"successfully claimed, and therefore exist in the trie\n"
|
||||
"Arguments:\n"
|
||||
"Result:\n"
|
||||
"\"total names\" (numeric) the total number of\n"
|
||||
" names in the trie\n"
|
||||
);
|
||||
LOCK(cs_main);
|
||||
if (!pclaimTrie)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
unsigned int num_names = pclaimTrie->getTotalNamesInTrie();
|
||||
return int(num_names);
|
||||
}
|
||||
|
||||
UniValue gettotalclaims(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() != 0)
|
||||
throw std::runtime_error(
|
||||
"gettotalclaims\n"
|
||||
"Return the total number of active claims in the trie\n"
|
||||
"Arguments:\n"
|
||||
"Result:\n"
|
||||
"\"total claims\" (numeric) the total number\n"
|
||||
" of active claims\n"
|
||||
);
|
||||
LOCK(cs_main);
|
||||
if (!pclaimTrie)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
unsigned int num_claims = pclaimTrie->getTotalClaimsInTrie();
|
||||
return int(num_claims);
|
||||
}
|
||||
|
||||
UniValue gettotalvalueofclaims(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() > 1)
|
||||
throw std::runtime_error(
|
||||
"gettotalvalueofclaims\n"
|
||||
"Return the total value of the claims in the trie\n"
|
||||
"Arguments:\n"
|
||||
"1. \"controlling_only\" (boolean) only include the value\n"
|
||||
" of controlling claims\n"
|
||||
"Result:\n"
|
||||
"\"total value\" (numeric) the total value of the\n"
|
||||
" claims in the trie\n"
|
||||
);
|
||||
LOCK(cs_main);
|
||||
if (!pclaimTrie)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
bool controlling_only = false;
|
||||
if (request.params.size() == 1)
|
||||
controlling_only = request.params[0].get_bool();
|
||||
CAmount total_amount = pclaimTrie->getTotalValueOfClaimsInTrie(controlling_only);
|
||||
return ValueFromAmount(total_amount);
|
||||
}
|
||||
|
||||
UniValue getclaimsfortx(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() != 1)
|
||||
throw std::runtime_error(
|
||||
"getclaimsfortx\n"
|
||||
"Return any claims or supports found in a transaction\n"
|
||||
"Arguments:\n"
|
||||
"1. \"txid\" (string) the txid of the transaction to check for unspent claims\n"
|
||||
"Result:\n"
|
||||
"[\n"
|
||||
" {\n"
|
||||
" \"nOut\" (numeric) the index of the claim or support in the transaction's list of outputs\n"
|
||||
" \"claim type\" (string) 'claim' or 'support'\n"
|
||||
" \"name\" (string) the name claimed or supported\n"
|
||||
" \"value\" (string) if a name claim, the value of the claim\n"
|
||||
" \"supported txid\" (string) if a support, the txid of the supported claim\n"
|
||||
" \"supported nout\" (numeric) if a support, the index of the supported claim in its transaction\n"
|
||||
" \"depth\" (numeric) the depth of the transaction in the main chain\n"
|
||||
" \"in claim trie\" (boolean) if a name claim, whether the claim is active, i.e. has made it into the trie\n"
|
||||
" \"is controlling\" (boolean) if a name claim, whether the claim is the current controlling claim for the name\n"
|
||||
" \"in support map\" (boolean) if a support, whether the support is active, i.e. has made it into the support map\n"
|
||||
" \"in queue\" (boolean) whether the claim is in a queue waiting to be inserted into the trie or support map\n"
|
||||
" \"blocks to valid\" (numeric) if in a queue, the number of blocks until it's inserted into the trie or support map\n"
|
||||
" }\n"
|
||||
"]\n"
|
||||
);
|
||||
|
||||
LOCK(cs_main);
|
||||
|
||||
uint256 hash;
|
||||
hash.SetHex(request.params[0].get_str());
|
||||
|
||||
UniValue ret(UniValue::VARR);
|
||||
|
||||
int op;
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
|
||||
CCoinsViewCache &view = *pcoinsTip;
|
||||
const Coin& coin = AccessByTxid(view, hash);
|
||||
std::vector<CTxOut> txouts{ coin.out };
|
||||
int nHeight = coin.nHeight;
|
||||
|
||||
for (unsigned int i = 0; i < txouts.size(); ++i)
|
||||
{
|
||||
if (!txouts[i].IsNull())
|
||||
{
|
||||
vvchParams.clear();
|
||||
const CTxOut& txout = txouts[i];
|
||||
UniValue o(UniValue::VOBJ);
|
||||
if (DecodeClaimScript(txout.scriptPubKey, op, vvchParams))
|
||||
{
|
||||
o.pushKV("nOut", static_cast<int64_t>(i));
|
||||
std::string sName(vvchParams[0].begin(), vvchParams[0].end());
|
||||
o.pushKV("name", sName);
|
||||
if (op == OP_CLAIM_NAME)
|
||||
{
|
||||
std::string sValue(vvchParams[1].begin(), vvchParams[1].end());
|
||||
uint160 claimId = ClaimIdHash(hash, i);
|
||||
o.pushKV("claimId", claimId.GetHex());
|
||||
o.pushKV("value", encodeValue(sValue));
|
||||
}
|
||||
else if (op == OP_UPDATE_CLAIM)
|
||||
{
|
||||
uint160 claimId(vvchParams[1]);
|
||||
std::string sValue(vvchParams[2].begin(), vvchParams[2].end());
|
||||
o.pushKV("claimId", claimId.GetHex());
|
||||
o.pushKV("value", encodeValue(sValue));
|
||||
}
|
||||
else if (op == OP_SUPPORT_CLAIM)
|
||||
{
|
||||
uint160 supportedClaimId(vvchParams[1]);
|
||||
o.pushKV("supported claimId", supportedClaimId.GetHex());
|
||||
}
|
||||
if (nHeight > 0)
|
||||
{
|
||||
o.pushKV("depth", chainActive.Height() - nHeight);
|
||||
if (op == OP_CLAIM_NAME || op == OP_UPDATE_CLAIM)
|
||||
{
|
||||
bool inClaimTrie = pclaimTrie->haveClaim(sName, COutPoint(hash, i));
|
||||
o.pushKV("in claim trie", inClaimTrie);
|
||||
if (inClaimTrie)
|
||||
{
|
||||
CClaimValue claim;
|
||||
if (!pclaimTrie->getInfoForName(sName, claim))
|
||||
{
|
||||
LogPrintf("HaveClaim was true but getInfoForName returned false.");
|
||||
}
|
||||
o.pushKV("is controlling", (claim.outPoint.hash == hash && claim.outPoint.n == i));
|
||||
}
|
||||
else
|
||||
{
|
||||
int nValidAtHeight;
|
||||
if (pclaimTrie->haveClaimInQueue(sName, COutPoint(hash, i), nValidAtHeight))
|
||||
{
|
||||
o.pushKV("in queue", true);
|
||||
o.pushKV("blocks to valid", nValidAtHeight - chainActive.Height());
|
||||
}
|
||||
else
|
||||
{
|
||||
o.pushKV("in queue", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (op == OP_SUPPORT_CLAIM)
|
||||
{
|
||||
bool inSupportMap = pclaimTrie->haveSupport(sName, COutPoint(hash, i));
|
||||
o.pushKV("in support map", inSupportMap);
|
||||
if (!inSupportMap)
|
||||
{
|
||||
int nValidAtHeight;
|
||||
if (pclaimTrie->haveSupportInQueue(sName, COutPoint(hash, i), nValidAtHeight))
|
||||
{
|
||||
o.pushKV("in queue", true);
|
||||
o.pushKV("blocks to valid", nValidAtHeight - chainActive.Height());
|
||||
}
|
||||
else
|
||||
{
|
||||
o.pushKV("in queue", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
o.pushKV("depth", 0);
|
||||
if (op == OP_CLAIM_NAME || op == OP_UPDATE_CLAIM)
|
||||
{
|
||||
o.pushKV("in claim trie", false);
|
||||
}
|
||||
else if (op == OP_SUPPORT_CLAIM)
|
||||
{
|
||||
o.pushKV("in support map", false);
|
||||
}
|
||||
o.pushKV("in queue", false);
|
||||
}
|
||||
ret.push_back(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
UniValue proofToJSON(const CClaimTrieProof& proof)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ);
|
||||
UniValue nodes(UniValue::VARR);
|
||||
for (std::vector<CClaimTrieProofNode>::const_iterator itNode = proof.nodes.begin(); itNode != proof.nodes.end(); ++itNode)
|
||||
{
|
||||
UniValue node(UniValue::VOBJ);
|
||||
UniValue children(UniValue::VARR);
|
||||
for (std::vector<std::pair<unsigned char, uint256> >::const_iterator itChildren = itNode->children.begin(); itChildren != itNode->children.end(); ++itChildren)
|
||||
{
|
||||
UniValue child(UniValue::VOBJ);
|
||||
child.pushKV("character", itChildren->first);
|
||||
if (!itChildren->second.IsNull())
|
||||
{
|
||||
child.pushKV("nodeHash", itChildren->second.GetHex());
|
||||
}
|
||||
children.push_back(child);
|
||||
}
|
||||
node.pushKV("children", children);
|
||||
if (itNode->hasValue && !itNode->valHash.IsNull())
|
||||
{
|
||||
node.pushKV("valueHash", itNode->valHash.GetHex());
|
||||
}
|
||||
nodes.push_back(node);
|
||||
}
|
||||
result.pushKV("nodes", nodes);
|
||||
if (proof.hasValue)
|
||||
{
|
||||
result.pushKV("txhash", proof.outPoint.hash.GetHex());
|
||||
result.pushKV("nOut", (int)proof.outPoint.n);
|
||||
result.pushKV("last takeover height", (int)proof.nHeightOfLastTakeover);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
UniValue getnameproof(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || (request.params.size() != 1 && request.params.size() != 2))
|
||||
throw std::runtime_error(
|
||||
"getnameproof\n"
|
||||
"Return the cryptographic proof that a name maps to a value\n"
|
||||
"or doesn't.\n"
|
||||
"Arguments:\n"
|
||||
"1. \"name\" (string) the name to get a proof for\n"
|
||||
"2. \"blockhash\" (string, optional) the hash of the block\n"
|
||||
" which is the basis\n"
|
||||
" of the proof. If\n"
|
||||
" none is given, \n"
|
||||
" the latest block\n"
|
||||
" will be used.\n"
|
||||
"Result: \n"
|
||||
"{\n"
|
||||
" \"nodes\" : [ (array of object) full nodes (i.e.\n"
|
||||
" those which lead to\n"
|
||||
" the requested name)\n"
|
||||
" \"children\" : [ (array of object) the children of\n"
|
||||
" this node\n"
|
||||
" \"child\" : { (object) a child node, either leaf or\n"
|
||||
" reference to a full node\n"
|
||||
" \"character\" : \"char\" (string) the character which\n"
|
||||
" leads from the parent\n"
|
||||
" to this child node\n"
|
||||
" \"nodeHash\" : \"hash\" (string, if exists) the hash of\n"
|
||||
" the node if\n"
|
||||
" this is a \n"
|
||||
" leaf node\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
" \"valueHash\" (string, if exists) the hash of this\n"
|
||||
" node's value, if\n"
|
||||
" it has one. If \n"
|
||||
" this is the\n"
|
||||
" requested name\n"
|
||||
" this will not\n"
|
||||
" exist whether\n"
|
||||
" the node has a\n"
|
||||
" value or not\n"
|
||||
" ]\n"
|
||||
" \"txhash\" : \"hash\" (string, if exists) the txid of the\n"
|
||||
" claim which controls\n"
|
||||
" this name, if there\n"
|
||||
" is one.\n"
|
||||
" \"nOut\" : n, (numeric) the nOut of the claim which\n"
|
||||
" controls this name, if there\n"
|
||||
" is one.\n"
|
||||
" \"last takeover height\" (numeric) the most recent height at\n"
|
||||
" which the value of a name\n"
|
||||
" changed other than through\n"
|
||||
" an update to the winning\n"
|
||||
" bid\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
|
||||
LOCK(cs_main);
|
||||
std::string strName = request.params[0].get_str();
|
||||
uint256 blockHash;
|
||||
if (request.params.size() == 2)
|
||||
{
|
||||
std::string strBlockHash = request.params[1].get_str();
|
||||
blockHash = uint256S(strBlockHash);
|
||||
}
|
||||
else
|
||||
{
|
||||
blockHash = chainActive.Tip()->GetBlockHash();
|
||||
}
|
||||
|
||||
if (mapBlockIndex.count(blockHash) == 0)
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
||||
|
||||
CBlockIndex* pblockIndex = mapBlockIndex[blockHash];
|
||||
if (!chainActive.Contains(pblockIndex))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not in main chain");
|
||||
|
||||
if (chainActive.Tip()->nHeight > (pblockIndex->nHeight + MAX_RPC_BLOCK_DECREMENTS))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Block too deep to generate proof");
|
||||
|
||||
CClaimTrieProof proof;
|
||||
if (!GetProofForName(pblockIndex, strName, proof))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Failed to generate proof");
|
||||
|
||||
return proofToJSON(proof);
|
||||
}
|
||||
|
||||
static const CRPCCommand commands[] =
|
||||
{ // category name actor (function) argNames
|
||||
// --------------------- ------------------------ ----------------------- ----------
|
||||
{ "Claimtrie", "getclaimsintrie", &getclaimsintrie, { "" } },
|
||||
{ "Claimtrie", "getclaimtrie", &getclaimtrie, { "" } },
|
||||
{ "Claimtrie", "getvalueforname", &getvalueforname, { "name" } },
|
||||
{ "Claimtrie", "getclaimsforname", &getclaimsforname, { "name" } },
|
||||
{ "Claimtrie", "gettotalclaimednames", &gettotalclaimednames, { "" } },
|
||||
{ "Claimtrie", "gettotalclaims", &gettotalclaims, { "" } },
|
||||
{ "Claimtrie", "gettotalvalueofclaims", &gettotalvalueofclaims, { "controlling_only" } },
|
||||
{ "Claimtrie", "getclaimsfortx", &getclaimsfortx, { "txid" } },
|
||||
{ "Claimtrie", "getnameproof", &getnameproof, { "name","blockhash"} },
|
||||
{ "Claimtrie", "getclaimbyid", &getclaimbyid, {"claimId"} },
|
||||
};
|
||||
|
||||
void RegisterClaimTrieRPCCommands(CRPCTable &tableRPC)
|
||||
{
|
||||
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
|
||||
tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
|
||||
}
|
|
@ -19,6 +19,8 @@ void RegisterMiscRPCCommands(CRPCTable &tableRPC);
|
|||
void RegisterMiningRPCCommands(CRPCTable &tableRPC);
|
||||
/** Register raw transaction RPC commands */
|
||||
void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC);
|
||||
/** Register claim trie RPC commands */
|
||||
void RegisterClaimTrieRPCCommands(CRPCTable &tableRPC);
|
||||
|
||||
static inline void RegisterAllCoreRPCCommands(CRPCTable &t)
|
||||
{
|
||||
|
@ -27,6 +29,8 @@ static inline void RegisterAllCoreRPCCommands(CRPCTable &t)
|
|||
RegisterMiscRPCCommands(t);
|
||||
RegisterMiningRPCCommands(t);
|
||||
RegisterRawTransactionRPCCommands(t);
|
||||
RegisterRawTransactionRPCCommands(t);
|
||||
RegisterClaimTrieRPCCommands(t);
|
||||
}
|
||||
|
||||
#endif // BITCOIN_RPC_REGISTER_H
|
||||
|
|
|
@ -285,7 +285,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
|
|||
// static const CScriptNum bnFalse(0);
|
||||
// static const CScriptNum bnTrue(1);
|
||||
static const valtype vchFalse(0);
|
||||
// static const valtype vchZero(0);
|
||||
static const valtype vchZero(0);
|
||||
static const valtype vchTrue(1, 1);
|
||||
|
||||
CScript::const_iterator pc = script.begin();
|
||||
|
@ -423,6 +423,13 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
|
|||
break;
|
||||
}
|
||||
|
||||
case OP_CLAIM_NAME: case OP_SUPPORT_CLAIM: case OP_UPDATE_CLAIM:
|
||||
{
|
||||
CScriptNum n(OP_0);
|
||||
stack.push_back(vchZero);
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_CHECKSEQUENCEVERIFY:
|
||||
{
|
||||
if (!(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) {
|
||||
|
@ -458,7 +465,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
|
|||
}
|
||||
|
||||
case OP_NOP1: case OP_NOP4: case OP_NOP5:
|
||||
case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10:
|
||||
case OP_NOP9: case OP_NOP10:
|
||||
{
|
||||
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
|
||||
return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
#include <vector>
|
||||
|
||||
// Maximum number of bytes pushable to the stack
|
||||
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520;
|
||||
/* static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; */
|
||||
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 20000; // bytes
|
||||
|
||||
// Maximum number of non-push operations per script
|
||||
static const int MAX_OPS_PER_SCRIPT = 201;
|
||||
|
@ -176,8 +177,11 @@ enum opcodetype
|
|||
OP_NOP4 = 0xb3,
|
||||
OP_NOP5 = 0xb4,
|
||||
OP_NOP6 = 0xb5,
|
||||
OP_CLAIM_NAME = OP_NOP6,
|
||||
OP_NOP7 = 0xb6,
|
||||
OP_SUPPORT_CLAIM = OP_NOP7,
|
||||
OP_NOP8 = 0xb7,
|
||||
OP_UPDATE_CLAIM = OP_NOP8,
|
||||
OP_NOP9 = 0xb8,
|
||||
OP_NOP10 = 0xb9,
|
||||
|
||||
|
|
|
@ -37,56 +37,48 @@ struct TestVector {
|
|||
};
|
||||
|
||||
TestVector test1 =
|
||||
TestVector("000102030405060708090a0b0c0d0e0f")
|
||||
("xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
|
||||
"xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi",
|
||||
TestVector("000102030405060708090a0b0c0d0e0f")
|
||||
("Lpub2hkYkGHXktBhLCamCogeqGV7fQatCHyAe3LstjaUdvp6syZNaSGjdxf68TZG1hmc4Dz1dnMnZad1HHiS3DopTy4QxrMcSbiGir5nXrU2xFd",
|
||||
"LprvXPsFZUGgrX1X8fNGTeYQawgXAMnj4SeUu4SpYk4vfQ5MtF16HTUVzFEmFmfM4D4JQ66TyH2y3X1SAkMtYvV455cRn2EPLb1DyK21SWCtZac",
|
||||
0x80000000)
|
||||
("xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw",
|
||||
"xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7",
|
||||
("Lpub2k1xjyazr9JgUoiUQZZHiJbDzE9EaNTBKemmrpxbc81PFFrYzfopm71Vuj7xm1g94SGaW1uDJDh6FggZzFYCXrX9AV9sMucVEnDLqVLA3bY",
|
||||
"LprvXS8fZBa9wn8WHGVyfQR3TyndVBM5SX8VafsiWqT3dbGeFXJGhh1b7PbB331gTvSG78zALaMqRsrJtWPcCWmEs9gwqtuXaYi7gKersfwXWn8",
|
||||
1)
|
||||
("xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ",
|
||||
"xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs",
|
||||
("Lpub2nC5wm8tErBkKFkv8pTAK3Ut3c8LaQBUFyScT6jQYkobUoMgiUE8ifujKoaYAxPV29tdHSMKQpBZqzRPTai6DWM5TgziqYcksWk88PnCeej",
|
||||
"LprvXUJnky83LV1a7iYRPfJv4igHYZLBSYrnWzYZ77DraE4rV4oQRVRu4xVQT6Ck4rDJZDjr9PxGWaoj2SuqKrZDeKBPMfsFeJUyM7yEQc2m5F9",
|
||||
0x80000002)
|
||||
("xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5",
|
||||
"xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM",
|
||||
("Lpub2poMzHxjwj3ABRZ1PQrXg3X2GkzrqwmTbWgHhS2ZidB2teYoXE4Zd7TespmNcppoNfzMtpKvnkkYJKZgAgFdGxVv3axrvVgSbCfGDgJ2VpS",
|
||||
"LprvXWv4oVwu3MryytLWeFiHRiiRmiChi6SmrXnEMSX1k6SHtuzXEFGKyQ3L18RN35io4gmEjruBvzddFeeausUQmQd3iHRooEiuxPiT3AByBL9",
|
||||
2)
|
||||
("xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV",
|
||||
"xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334",
|
||||
("Lpub2s2kpj5h8Ci9Fu2j5g4cZYgLMaHbUY5f2zZaxPZ334jeFkBAazkvpgvaZ9km2cyXqz7Y2posqVeerjugFygpzYyAxNX3kgaGbta7NFjbxNP",
|
||||
"LprvXZ9Tdw4rDqXy4MpELWvNKDsjrXVSLgkyJ1fXcQ3V4XzuG1ctJ1xhAyWFgSppVk8E8UtwMn8kqp5niqZ37J1kxoD67XWuMKYd7NBcYeJ6jSm",
|
||||
1000000000)
|
||||
("xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy",
|
||||
"xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76",
|
||||
("Lpub2tkXJQgwFL6LnEpBCDdLsFgL9oruJ2tgqEx9CfwBF988xsaZ7R1b5o5eByfhst4FKgQ5YAjgNhMFTAJhMqBfqp8Hpuw8ZA9uQrC2cTHvMov",
|
||||
"LprvXasE7cg6LxvAahbgT4V6cvsjem4kABa16G45rgRdGcPPy92GpSDMS5fKKJc2QfFJjtJC997hgrcuj1ZQeN2V5krdT2H8UEJLPhjyHjdGM3u",
|
||||
0);
|
||||
|
||||
TestVector test2 =
|
||||
TestVector("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542")
|
||||
("xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB",
|
||||
"xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U",
|
||||
TestVector("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484\
|
||||
542")
|
||||
("Lpub2hkYkGHXktBhKp66JxkwHUCsubjJsvDzKd8cBgKJcJvyAxaZkb3g4rpgUZeEix8ZxnDoYT1wxf8G15SfAQiybt4MpnZ5H6Cw3DktojFA2uq",
|
||||
"LprvXPsFZUGgrX1X8GsbZoch39QHQYw9k4uJaeEYqgokdnCEBE2HTcFSR9QMbqSQEicPe8qtiZVRKd3dGH5zbLskgSwCESJdUvuxYZeEoQkoij6",
|
||||
0)
|
||||
("xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH",
|
||||
"xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt",
|
||||
("Lpub2m2J1yyVEu1mr5gPSk8pMGcQGZUZatiGsnsyMVLkginvrw2YKrPkDhPw42c8X391B6hyQg1hMjyEAEsM3ZRPwUie6qHkBSMKAhsZEyWPpRJ",
|
||||
"LprvXT8zqBxeLXqbeYTthaza6woomWgQT3Pb8oyv1VqCiC4BsCUG2sbWZyycBLiCsnTE3o5icZu9knTkcnip9dNocg6bEcigsR5hfyYoAmjDmEw",
|
||||
0xFFFFFFFF)
|
||||
("xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a",
|
||||
"xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9",
|
||||
("Lpub2nBMGb11coBt1wtZsC8TpcHxfJhU8NsxxwxWGtFXLTZKKEFzwjp4RmBXfQrFGmk6xcdX4WsJexPppujgpTuWfdBGduuoYAcL369A5mJaAUR",
|
||||
"LprvXUJ45nzAiS1hpQg582zDaHVNAFuJzXZHDy4SvtjyMvpaKVhiem1pn3mCnhCBc3Bhx2QcPb6nonxs42TaszywByY9fLx2dvoxTktKw75RfhE",
|
||||
1)
|
||||
("xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon",
|
||||
"xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef",
|
||||
("Lpub2pzKgbywnSV57ZZhvrH2nZEBzqZyEZoEHPTN7wureLukz48AFFLmKfZuWD3P4eSPYo64u9xYJ5heuhzhjNLTvxeBEC7eki3Xxrp7LFdK9GD",
|
||||
"LprvXX72Voy6t5Jtv2MDBh8nYERbVnmp6iUYYQZJmxQJfpB1zKZsxGYXfx9adVPodkPQFymK8tBBDLe5NjEjvtWKCTMSo7UqV2nLwZK4Qns6Jan",
|
||||
0xFFFFFFFE)
|
||||
("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL",
|
||||
"xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc",
|
||||
("Lpub2rAMbZvJPqSnQWoJfL6aA4vNua3LHYRjK6BFefcGV7B1SQT6LvGmrBw18sAtG1xqWEjhhf2FLh2WZMA6RFSyeKLdW6S9K18wq5tgsCMpiS8",
|
||||
"LprvXYH4QmuTVUGcCyaovAxKuk7nQXFB9h73a7HCJg6iWaSGSftp3wUYCUWgGC8CGAmgoZ41ShxAbiDfBrL7SqQotJ2cd429dEoyH9KaUbZHRAn",
|
||||
2)
|
||||
("xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt",
|
||||
"xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j",
|
||||
("Lpub2sXPZ18ov1m29mzCPQEG8pJMJdaSXsLoyFo94Sxm7u2bWbnfWZCY2kt1DGFAPbKY2HwvyaXfEQ3W3nDbFM8sxaCD9GGEFNRgWP5sXmFVSUv",
|
||||
"LprvXZe6ND7y1eaqxEmheF61tVVkoanHQ228EGu5iTTD9NHrWsEPDaQJP3TgLboCRBrkqrujjTaz3p4MEQDdB9n2wGmLRuXegewgyWf8ZANdd3A",
|
||||
0);
|
||||
|
||||
TestVector test3 =
|
||||
TestVector("4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be")
|
||||
("xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13",
|
||||
"xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6",
|
||||
0x80000000)
|
||||
("xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y",
|
||||
"xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L",
|
||||
0);
|
||||
|
||||
static void RunTest(const TestVector &test) {
|
||||
std::vector<unsigned char> seed = ParseHex(test.strHexMaster);
|
||||
CExtKey key;
|
||||
|
@ -147,8 +139,4 @@ BOOST_AUTO_TEST_CASE(bip32_test2) {
|
|||
RunTest(test2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(bip32_test3) {
|
||||
RunTest(test3);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
|
@ -24,7 +24,7 @@ static CBlockIndex* CreateBlockIndexWithNbits(uint32_t nbits)
|
|||
|
||||
static void RejectDifficultyMismatch(double difficulty, double expected_difficulty) {
|
||||
BOOST_CHECK_MESSAGE(
|
||||
DoubleEquals(difficulty, expected_difficulty, 0.00001),
|
||||
DoubleEquals(difficulty, expected_difficulty, 0.058593),
|
||||
"Difficulty was " + std::to_string(difficulty)
|
||||
+ " but was expected to be " + std::to_string(expected_difficulty));
|
||||
}
|
||||
|
@ -45,12 +45,12 @@ BOOST_FIXTURE_TEST_SUITE(blockchain_tests, BasicTestingSetup)
|
|||
|
||||
BOOST_AUTO_TEST_CASE(get_difficulty_for_very_low_target)
|
||||
{
|
||||
TestDifficulty(0x1f111111, 0.000001);
|
||||
TestDifficulty(0x1f00ffff, 0.058593);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(get_difficulty_for_low_target)
|
||||
{
|
||||
TestDifficulty(0x1ef88f6f, 0.000016);
|
||||
TestDifficulty(0x1ef88f6f, 1.029916);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(get_difficulty_for_mid_target)
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out);
|
||||
int ApplyTxInUndo(unsigned int index, const CTxUndo& txUndo, CCoinsViewCache& view, CClaimTrieCache& trieCache, const COutPoint& out);
|
||||
void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txundo, int nHeight);
|
||||
|
||||
namespace
|
||||
|
@ -407,7 +407,8 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
|
|||
if (!tx.IsCoinBase()) {
|
||||
const COutPoint &out = tx.vin[0].prevout;
|
||||
Coin coin = undo.vprevout[0];
|
||||
ApplyTxInUndo(std::move(coin), *(stack.back()), out);
|
||||
CClaimTrieCache trieCache(pclaimTrie);
|
||||
ApplyTxInUndo(0, undo, *(stack.back()), trieCache, out);
|
||||
}
|
||||
// Store as a candidate for reconnection
|
||||
disconnected_coins.insert(utxod->first);
|
||||
|
@ -740,35 +741,35 @@ static void CheckAddCoin(Args&&... args)
|
|||
CheckAddCoinBase(base_value, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ccoins_add)
|
||||
{
|
||||
/* Check AddCoin behavior, requesting a new coin from a cache view,
|
||||
* writing a modification to the coin, and then checking the resulting
|
||||
* entry in the cache after the modification. Verify behavior with the
|
||||
* with the AddCoin potential_overwrite argument set to false, and to true.
|
||||
*
|
||||
* Cache Write Result Cache Result potential_overwrite
|
||||
* Value Value Value Flags Flags
|
||||
*/
|
||||
CheckAddCoin(ABSENT, VALUE3, VALUE3, NO_ENTRY , DIRTY|FRESH, false);
|
||||
CheckAddCoin(ABSENT, VALUE3, VALUE3, NO_ENTRY , DIRTY , true );
|
||||
CheckAddCoin(PRUNED, VALUE3, VALUE3, 0 , DIRTY|FRESH, false);
|
||||
CheckAddCoin(PRUNED, VALUE3, VALUE3, 0 , DIRTY , true );
|
||||
CheckAddCoin(PRUNED, VALUE3, VALUE3, FRESH , DIRTY|FRESH, false);
|
||||
CheckAddCoin(PRUNED, VALUE3, VALUE3, FRESH , DIRTY|FRESH, true );
|
||||
CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY , DIRTY , false);
|
||||
CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY , DIRTY , true );
|
||||
CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, false);
|
||||
CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, true );
|
||||
CheckAddCoin(VALUE2, VALUE3, FAIL , 0 , NO_ENTRY , false);
|
||||
CheckAddCoin(VALUE2, VALUE3, VALUE3, 0 , DIRTY , true );
|
||||
CheckAddCoin(VALUE2, VALUE3, FAIL , FRESH , NO_ENTRY , false);
|
||||
CheckAddCoin(VALUE2, VALUE3, VALUE3, FRESH , DIRTY|FRESH, true );
|
||||
CheckAddCoin(VALUE2, VALUE3, FAIL , DIRTY , NO_ENTRY , false);
|
||||
CheckAddCoin(VALUE2, VALUE3, VALUE3, DIRTY , DIRTY , true );
|
||||
CheckAddCoin(VALUE2, VALUE3, FAIL , DIRTY|FRESH, NO_ENTRY , false);
|
||||
CheckAddCoin(VALUE2, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, true );
|
||||
}
|
||||
/* BOOST_AUTO_TEST_CASE(ccoins_add) */
|
||||
/* { */
|
||||
/* /\* Check AddCoin behavior, requesting a new coin from a cache view, */
|
||||
/* * writing a modification to the coin, and then checking the resulting */
|
||||
/* * entry in the cache after the modification. Verify behavior with the */
|
||||
/* * with the AddCoin potential_overwrite argument set to false, and to true. */
|
||||
/* * */
|
||||
/* * Cache Write Result Cache Result potential_overwrite */
|
||||
/* * Value Value Value Flags Flags */
|
||||
/* *\/ */
|
||||
/* CheckAddCoin(ABSENT, VALUE3, VALUE3, NO_ENTRY , DIRTY|FRESH, false); */
|
||||
/* CheckAddCoin(ABSENT, VALUE3, VALUE3, NO_ENTRY , DIRTY , true ); */
|
||||
/* CheckAddCoin(PRUNED, VALUE3, VALUE3, 0 , DIRTY|FRESH, false); */
|
||||
/* CheckAddCoin(PRUNED, VALUE3, VALUE3, 0 , DIRTY , true ); */
|
||||
/* CheckAddCoin(PRUNED, VALUE3, VALUE3, FRESH , DIRTY|FRESH, false); */
|
||||
/* CheckAddCoin(PRUNED, VALUE3, VALUE3, FRESH , DIRTY|FRESH, true ); */
|
||||
/* CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY , DIRTY , false); */
|
||||
/* CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY , DIRTY , true ); */
|
||||
/* CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, false); */
|
||||
/* CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, true ); */
|
||||
/* CheckAddCoin(VALUE2, VALUE3, FAIL , 0 , NO_ENTRY , false); */
|
||||
/* CheckAddCoin(VALUE2, VALUE3, VALUE3, 0 , DIRTY , true ); */
|
||||
/* CheckAddCoin(VALUE2, VALUE3, FAIL , FRESH , NO_ENTRY , false); */
|
||||
/* CheckAddCoin(VALUE2, VALUE3, VALUE3, FRESH , DIRTY|FRESH, true ); */
|
||||
/* CheckAddCoin(VALUE2, VALUE3, FAIL , DIRTY , NO_ENTRY , false); */
|
||||
/* CheckAddCoin(VALUE2, VALUE3, VALUE3, DIRTY , DIRTY , true ); */
|
||||
/* CheckAddCoin(VALUE2, VALUE3, FAIL , DIRTY|FRESH, NO_ENTRY , false); */
|
||||
/* CheckAddCoin(VALUE2, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, true ); */
|
||||
/* } */
|
||||
|
||||
void CheckWriteCoins(CAmount parent_value, CAmount child_value, CAmount expected_value, char parent_flags, char child_flags, char expected_flags)
|
||||
{
|
||||
|
|
|
@ -13,49 +13,67 @@
|
|||
|
||||
BOOST_FIXTURE_TEST_SUITE(main_tests, TestingSetup)
|
||||
|
||||
static void TestBlockSubsidyHalvings(const Consensus::Params& consensusParams)
|
||||
static void TestBlockSubsidyReductions(const Consensus::Params& consensusParams)
|
||||
{
|
||||
int maxHalvings = 64;
|
||||
CAmount nInitialSubsidy = 50 * COIN;
|
||||
int nHeight = 0;
|
||||
BOOST_CHECK_EQUAL(GetBlockSubsidy(nHeight, consensusParams), 400000000*COIN);
|
||||
|
||||
CAmount nPreviousSubsidy = nInitialSubsidy * 2; // for height == 0
|
||||
BOOST_CHECK_EQUAL(nPreviousSubsidy, nInitialSubsidy * 2);
|
||||
for (int nHalvings = 0; nHalvings < maxHalvings; nHalvings++) {
|
||||
int nHeight = nHalvings * consensusParams.nSubsidyHalvingInterval;
|
||||
CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams);
|
||||
BOOST_CHECK(nSubsidy <= nInitialSubsidy);
|
||||
BOOST_CHECK_EQUAL(nSubsidy, nPreviousSubsidy / 2);
|
||||
nPreviousSubsidy = nSubsidy;
|
||||
// Verify that block reward is 1 until block 5100
|
||||
nHeight += 25;
|
||||
for (; nHeight < 5100; nHeight += 80)
|
||||
{
|
||||
BOOST_CHECK_EQUAL(GetBlockSubsidy(nHeight, consensusParams), 1*COIN);
|
||||
}
|
||||
BOOST_CHECK_EQUAL(GetBlockSubsidy(maxHalvings * consensusParams.nSubsidyHalvingInterval, consensusParams), 0);
|
||||
nHeight = 5100;
|
||||
|
||||
// Verify it increases by 1 coin every 100 blocks
|
||||
|
||||
for (int i = 1; nHeight < 55000; nHeight += 100, i++)
|
||||
{
|
||||
BOOST_CHECK_EQUAL(GetBlockSubsidy(nHeight, consensusParams), i*COIN);
|
||||
}
|
||||
|
||||
int maxReductions = 500;
|
||||
CAmount nInitialSubsidy = 500 * COIN;
|
||||
int nReductions;
|
||||
for (nReductions = 0; nReductions < maxReductions; nReductions++)
|
||||
{
|
||||
nHeight = (((nReductions * nReductions + nReductions) >> 1) * consensusParams.nSubsidyLevelInterval) + 55001;
|
||||
CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams);
|
||||
BOOST_CHECK_EQUAL(nSubsidy, nInitialSubsidy - nReductions * COIN);
|
||||
}
|
||||
nHeight = (((nReductions * nReductions + nReductions) >> 1) * consensusParams.nSubsidyLevelInterval) + 55001;
|
||||
BOOST_CHECK_EQUAL(GetBlockSubsidy(nHeight, consensusParams), 0);
|
||||
}
|
||||
|
||||
static void TestBlockSubsidyHalvings(int nSubsidyHalvingInterval)
|
||||
static void TestBlockSubsidyReductions(int nSubsidyLevelInterval)
|
||||
{
|
||||
Consensus::Params consensusParams;
|
||||
consensusParams.nSubsidyHalvingInterval = nSubsidyHalvingInterval;
|
||||
TestBlockSubsidyHalvings(consensusParams);
|
||||
consensusParams.nSubsidyLevelInterval = nSubsidyLevelInterval;
|
||||
TestBlockSubsidyReductions(consensusParams);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(block_subsidy_test)
|
||||
{
|
||||
const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
|
||||
TestBlockSubsidyHalvings(chainParams->GetConsensus()); // As in main
|
||||
TestBlockSubsidyHalvings(150); // As in regtest
|
||||
TestBlockSubsidyHalvings(1000); // Just another interval
|
||||
TestBlockSubsidyReductions(chainParams->GetConsensus()); // As in main
|
||||
TestBlockSubsidyReductions(1); // As in regtest
|
||||
TestBlockSubsidyReductions(5); // Just another interval
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(subsidy_limit_test)
|
||||
{
|
||||
const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
|
||||
const auto& consensusParams = chainParams->GetConsensus();
|
||||
CAmount nSum = 0;
|
||||
for (int nHeight = 0; nHeight < 14000000; nHeight += 1000) {
|
||||
CAmount nSubsidy = GetBlockSubsidy(nHeight, chainParams->GetConsensus());
|
||||
BOOST_CHECK(nSubsidy <= 50 * COIN);
|
||||
nSum += GetBlockSubsidy(0, consensusParams);
|
||||
for (int nHeight = 1; nHeight < 5000001; nHeight += 1000) {
|
||||
CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams);
|
||||
BOOST_CHECK(nSubsidy <= 500 * COIN);
|
||||
nSum += nSubsidy * 1000;
|
||||
BOOST_CHECK(MoneyRange(nSum));
|
||||
}
|
||||
BOOST_CHECK_EQUAL(nSum, CAmount{2099999997690000});
|
||||
BOOST_CHECK_EQUAL(nSum, 108322100000000000LL);
|
||||
}
|
||||
|
||||
static bool ReturnFalse() { return false; }
|
||||
|
|
|
@ -335,6 +335,25 @@ BOOST_AUTO_TEST_CASE(rpc_convert_values_generatetoaddress)
|
|||
BOOST_CHECK_EQUAL(result[2].get_int(), 9);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(rpc_claimtrie_validation)
|
||||
{
|
||||
// std::runtime_error: parameter 2 must be hexadecimal string (not 'not_hex')
|
||||
BOOST_CHECK_THROW(RPCConvertValues("getnameproof", {"test", "not_hex"}), std::runtime_error);
|
||||
// std::runtime_error: Block not found
|
||||
BOOST_CHECK_THROW(RPCConvertValues("getnameproof", {"test", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}), std::runtime_error);
|
||||
// Generate a block to validate the NO_THROW case.
|
||||
UniValue result = CallRPC("generate 1");
|
||||
BOOST_CHECK_NO_THROW(result = RPCConvertValues("getnameproof", {"test", result[0].get_str()}));
|
||||
|
||||
/* BOOST_CHECK_THROW(CallRPC("getclaimsfortx not_hex"), runtime_error); */
|
||||
/* BOOST_CHECK_NO_THROW(CallRPC("getclaimsfortx aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")); */
|
||||
|
||||
/* BOOST_CHECK_THROW(CallRPC("getclaimbyid not_hex"), runtime_error); */
|
||||
/* // Wrong length. */
|
||||
/* BOOST_CHECK_THROW(CallRPC("getclaimbyid a"), runtime_error); */
|
||||
/* BOOST_CHECK_NO_THROW(CallRPC("getclaimbyid aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")); */
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(rpc_getblockstats_calculate_percentiles_by_weight)
|
||||
{
|
||||
int64_t total_weight = 200;
|
||||
|
|
|
@ -1285,6 +1285,51 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
|
|||
BOOST_CHECK(combined.scriptSig == partial3c);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(script_claimScript)
|
||||
{
|
||||
// Test the claim scripts
|
||||
// Outline:
|
||||
// Spend normal tx to make claim
|
||||
// Spend claim to update claim
|
||||
// Spend updated claim to abandon name
|
||||
CBasicKeyStore keystore;
|
||||
std::vector<CKey> keys;
|
||||
std::vector<CPubKey> pubkeys;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
CKey key;
|
||||
key.MakeNewKey(false);
|
||||
keys.push_back(key);
|
||||
pubkeys.push_back(key.GetPubKey());
|
||||
keystore.AddKey(key);
|
||||
}
|
||||
|
||||
CScriptWitness wit;
|
||||
|
||||
std::string sName = "testname";
|
||||
std::string sValue = "testvalue";
|
||||
std::vector<unsigned char> vchName(sName.begin(), sName.end());
|
||||
std::vector<unsigned char> vchValue(sValue.begin(), sValue.end());
|
||||
|
||||
CMutableTransaction txOrig = BuildCreditingTransaction(GetScriptForDestination(keys[0].GetPubKey().GetID()));
|
||||
|
||||
CMutableTransaction txClaim0 = BuildSpendingTransaction(CScript(), wit, txOrig);
|
||||
CScript txClaimOut0 = CScript() << OP_CLAIM_NAME << vchName << vchValue << OP_2DROP << OP_DROP;
|
||||
txClaimOut0 = txClaimOut0 + GetScriptForDestination(keys[1].GetPubKey().GetID());
|
||||
txClaim0.vout[0].scriptPubKey = txClaimOut0;
|
||||
SignSignature(keystore, txOrig, txClaim0, 0, SIGHASH_ALL);
|
||||
|
||||
CMutableTransaction txClaim1 = BuildSpendingTransaction(CScript(), wit, txClaim0);
|
||||
CScript txClaimOut1 = CScript() << OP_CLAIM_NAME << vchName << vchValue << OP_2DROP << OP_DROP;
|
||||
txClaimOut1 = txClaimOut1 + GetScriptForDestination(keys[2].GetPubKey().GetID());
|
||||
txClaim1.vout[0].scriptPubKey = txClaimOut1;
|
||||
SignSignature(keystore, txClaim0, txClaim1, 0, SIGHASH_ALL);
|
||||
|
||||
CMutableTransaction txFinal = BuildSpendingTransaction(CScript(), wit, txClaim1);
|
||||
txFinal.vout[0].scriptPubKey = GetScriptForDestination(keys[3].GetPubKey().GetID());
|
||||
SignSignature(keystore, txClaim1, txFinal, 0, SIGHASH_ALL);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(script_standard_push)
|
||||
{
|
||||
ScriptError err;
|
||||
|
|
|
@ -93,6 +93,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
|
|||
pblocktree.reset(new CBlockTreeDB(1 << 20, true));
|
||||
pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true));
|
||||
pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get()));
|
||||
pclaimTrie = new CClaimTrie(true, false, 1);
|
||||
if (!LoadGenesisBlock(chainparams)) {
|
||||
throw std::runtime_error("LoadGenesisBlock failed.");
|
||||
}
|
||||
|
@ -122,6 +123,7 @@ TestingSetup::~TestingSetup()
|
|||
pcoinsTip.reset();
|
||||
pcoinsdbview.reset();
|
||||
pblocktree.reset();
|
||||
delete pclaimTrie;
|
||||
}
|
||||
|
||||
TestChain100Setup::TestChain100Setup() : TestingSetup(CBaseChainParams::REGTEST)
|
||||
|
@ -175,6 +177,16 @@ TestChain100Setup::~TestChain100Setup()
|
|||
{
|
||||
}
|
||||
|
||||
RegTestingSetup::RegTestingSetup() : TestingSetup(CBaseChainParams::REGTEST)
|
||||
{
|
||||
minRelayTxFee = CFeeRate(0);
|
||||
minFeePerNameClaimChar = 0;
|
||||
}
|
||||
|
||||
RegTestingSetup::~RegTestingSetup()
|
||||
{
|
||||
minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
|
||||
}
|
||||
|
||||
CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CMutableTransaction &tx) {
|
||||
return FromTx(MakeTransactionRef(tx));
|
||||
|
|
|
@ -95,6 +95,11 @@ struct TestChain100Setup : public TestingSetup {
|
|||
CKey coinbaseKey; // private/public key needed to spend coinbase transactions
|
||||
};
|
||||
|
||||
struct RegTestingSetup: public TestingSetup {
|
||||
RegTestingSetup();
|
||||
~RegTestingSetup();
|
||||
};
|
||||
|
||||
class CTxMemPoolEntry;
|
||||
|
||||
struct TestMemPoolEntryHelper
|
||||
|
|
20
src/txdb.cpp
20
src/txdb.cpp
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <chainparams.h>
|
||||
#include <hash.h>
|
||||
#include <index/txindex.h>
|
||||
#include <random.h>
|
||||
#include <pow.h>
|
||||
#include <shutdown.h>
|
||||
|
@ -22,6 +23,7 @@ static const char DB_COIN = 'C';
|
|||
static const char DB_COINS = 'c';
|
||||
static const char DB_BLOCK_FILES = 'f';
|
||||
static const char DB_BLOCK_INDEX = 'b';
|
||||
static const char DB_TX_INDEX = 't';
|
||||
|
||||
static const char DB_BEST_BLOCK = 'B';
|
||||
static const char DB_HEAD_BLOCKS = 'H';
|
||||
|
@ -234,6 +236,17 @@ bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockF
|
|||
return WriteBatch(batch, true);
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
|
||||
return Read(std::make_pair(DB_TX_INDEX, txid), pos);
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
|
||||
CDBBatch batch(*this);
|
||||
for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
|
||||
batch.Write(std::make_pair(DB_TX_INDEX, it->first), it->second);
|
||||
return WriteBatch(batch);
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
|
||||
return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0');
|
||||
}
|
||||
|
@ -268,14 +281,19 @@ bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams,
|
|||
pindexNew->nUndoPos = diskindex.nUndoPos;
|
||||
pindexNew->nVersion = diskindex.nVersion;
|
||||
pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
|
||||
pindexNew->hashClaimTrie = diskindex.hashClaimTrie;
|
||||
pindexNew->nTime = diskindex.nTime;
|
||||
pindexNew->nBits = diskindex.nBits;
|
||||
pindexNew->nNonce = diskindex.nNonce;
|
||||
pindexNew->nStatus = diskindex.nStatus;
|
||||
pindexNew->nTx = diskindex.nTx;
|
||||
|
||||
if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, consensusParams))
|
||||
if (!CheckProofOfWork(pindexNew->GetBlockPoWHash(), pindexNew->nBits, consensusParams))
|
||||
{
|
||||
LogPrintf("%s: CheckProofOfWorkFailed: %s\n", __func__, pindexNew->ToString());
|
||||
LogPrintf("%s: CheckProofOfWorkFailed: %s (hash %s, nBits=%x, nTime=%d)\n", __func__, pindexNew->GetBlockPoWHash().GetHex(), pindexNew->GetBlockHash().GetHex(), pindexNew->nBits, pindexNew->nTime);
|
||||
return error("%s: CheckProofOfWork failed: %s", __func__, pindexNew->ToString());
|
||||
}
|
||||
|
||||
pcursor->Next();
|
||||
} else {
|
||||
|
|
|
@ -21,6 +21,8 @@ class CBlockIndex;
|
|||
class CCoinsViewDBCursor;
|
||||
class uint256;
|
||||
|
||||
struct CDiskTxPos;
|
||||
|
||||
//! No need to periodic flush if at least this much space still available.
|
||||
static constexpr int MAX_BLOCK_COINSDB_USAGE = 10;
|
||||
//! -dbcache default (MiB)
|
||||
|
@ -93,6 +95,8 @@ public:
|
|||
bool ReadLastBlockFile(int &nFile);
|
||||
bool WriteReindexing(bool fReindexing);
|
||||
void ReadReindexing(bool &fReindexing);
|
||||
bool ReadTxIndex(const uint256 &txid, CDiskTxPos &pos);
|
||||
bool WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> > &list);
|
||||
bool WriteFlag(const std::string &name, bool fValue);
|
||||
bool ReadFlag(const std::string &name, bool &fValue);
|
||||
bool LoadBlockIndexGuts(const Consensus::Params& consensusParams, std::function<CBlockIndex*(const uint256&)> insertBlockIndex);
|
||||
|
|
101
src/undo.h
101
src/undo.h
|
@ -6,6 +6,8 @@
|
|||
#ifndef BITCOIN_UNDO_H
|
||||
#define BITCOIN_UNDO_H
|
||||
|
||||
#include <unordered_map>
|
||||
#include <claimtrie.h>
|
||||
#include <compressor.h>
|
||||
#include <consensus/consensus.h>
|
||||
#include <primitives/transaction.h>
|
||||
|
@ -21,16 +23,24 @@
|
|||
class TxInUndoSerializer
|
||||
{
|
||||
const Coin* txout;
|
||||
// whether the outpoint was the last unspent
|
||||
bool fLastUnspent;
|
||||
// if the outpoint was the last unspent: its version
|
||||
unsigned int nVersion;
|
||||
// If the outpoint was a claim or support, the height at which the claim or support should be inserted into the trie
|
||||
unsigned int nClaimValidHeight;
|
||||
// if the outpoint was a claim or support
|
||||
bool fIsClaim;
|
||||
|
||||
public:
|
||||
template<typename Stream>
|
||||
void Serialize(Stream &s) const {
|
||||
::Serialize(s, VARINT(txout->nHeight * 2 + (txout->fCoinBase ? 1u : 0u)));
|
||||
if (txout->nHeight > 0) {
|
||||
// Required to maintain compatibility with older undo format.
|
||||
::Serialize(s, (unsigned char)0);
|
||||
}
|
||||
::Serialize(s, VARINT(txout->nHeight * 4 + (txout->fCoinBase ? 2u : 0u) + (fLastUnspent ? 1u : 0u)));
|
||||
if (fLastUnspent)
|
||||
::Serialize(s, VARINT(this->nVersion));
|
||||
::Serialize(s, CTxOutCompressor(REF(txout->out)));
|
||||
::Serialize(s, VARINT(nClaimValidHeight));
|
||||
::Serialize(s, fIsClaim);
|
||||
}
|
||||
|
||||
explicit TxInUndoSerializer(const Coin* coin) : txout(coin) {}
|
||||
|
@ -39,22 +49,28 @@ public:
|
|||
class TxInUndoDeserializer
|
||||
{
|
||||
Coin* txout;
|
||||
// whether the outpoint was the last unspent
|
||||
bool fLastUnspent;
|
||||
// if the outpoint was the last unspent: its version
|
||||
unsigned int nVersion;
|
||||
// If the outpoint was a claim or support, the height at which the claim or support should be inserted into the trie
|
||||
unsigned int nClaimValidHeight;
|
||||
// if the outpoint was a claim or support
|
||||
bool fIsClaim;
|
||||
|
||||
public:
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream &s) {
|
||||
unsigned int nCode = 0;
|
||||
::Unserialize(s, VARINT(nCode));
|
||||
txout->nHeight = nCode / 2;
|
||||
txout->fCoinBase = nCode & 1;
|
||||
if (txout->nHeight > 0) {
|
||||
// Old versions stored the version number for the last spend of
|
||||
// a transaction's outputs. Non-final spends were indicated with
|
||||
// height = 0.
|
||||
unsigned int nVersionDummy;
|
||||
::Unserialize(s, VARINT(nVersionDummy));
|
||||
}
|
||||
txout->nHeight = nCode / 4;
|
||||
txout->fCoinBase = nCode & 2;
|
||||
fLastUnspent = nCode & 1;
|
||||
if (fLastUnspent)
|
||||
::Unserialize(s, VARINT(this->nVersion));
|
||||
::Unserialize(s, CTxOutCompressor(REF(txout->out)));
|
||||
::Unserialize(s, VARINT(nClaimValidHeight));
|
||||
::Unserialize(s, fIsClaim);
|
||||
}
|
||||
|
||||
explicit TxInUndoDeserializer(Coin* coin) : txout(coin) {}
|
||||
|
@ -66,32 +82,39 @@ static const size_t MAX_INPUTS_PER_BLOCK = MAX_BLOCK_WEIGHT / MIN_TRANSACTION_IN
|
|||
/** Undo information for a CTransaction */
|
||||
class CTxUndo
|
||||
{
|
||||
struct claimState
|
||||
{
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(nClaimValidHeight);
|
||||
READWRITE(fIsClaim);
|
||||
};
|
||||
|
||||
// If the outpoint was a claim or support, the height at which the
|
||||
// claim or support should be inserted into the trie; indexed by Coin index
|
||||
unsigned int nClaimValidHeight;
|
||||
// if the outpoint was a claim or support; indexed by Coin index
|
||||
bool fIsClaim;
|
||||
};
|
||||
|
||||
using claimStateMap = std::map<unsigned int, claimState>;
|
||||
|
||||
public:
|
||||
// undo information for all txins
|
||||
std::vector<Coin> vprevout;
|
||||
claimStateMap claimInfo;
|
||||
|
||||
template <typename Stream>
|
||||
void Serialize(Stream& s) const {
|
||||
// TODO: avoid reimplementing vector serializer
|
||||
uint64_t count = vprevout.size();
|
||||
::Serialize(s, COMPACTSIZE(REF(count)));
|
||||
for (const auto& prevout : vprevout) {
|
||||
::Serialize(s, TxInUndoSerializer(&prevout));
|
||||
}
|
||||
CTxUndo() {
|
||||
}
|
||||
|
||||
template <typename Stream>
|
||||
void Unserialize(Stream& s) {
|
||||
// TODO: avoid reimplementing vector deserializer
|
||||
uint64_t count = 0;
|
||||
::Unserialize(s, COMPACTSIZE(count));
|
||||
if (count > MAX_INPUTS_PER_BLOCK) {
|
||||
throw std::ios_base::failure("Too many input undo records");
|
||||
}
|
||||
vprevout.resize(count);
|
||||
for (auto& prevout : vprevout) {
|
||||
::Unserialize(s, TxInUndoDeserializer(&prevout));
|
||||
}
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(vprevout);
|
||||
READWRITE(claimInfo);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -100,12 +123,22 @@ class CBlockUndo
|
|||
{
|
||||
public:
|
||||
std::vector<CTxUndo> vtxundo; // for all but the coinbase
|
||||
insertUndoType insertUndo; // any claims that went from the queue to the trie
|
||||
claimQueueRowType expireUndo; // any claims that expired
|
||||
insertUndoType insertSupportUndo; // any supports that went from the support queue to the support map
|
||||
supportQueueRowType expireSupportUndo; // any supports that expired
|
||||
std::vector<std::pair<std::string, int> > takeoverHeightUndo; // for any name that was taken over, the previous time that name was taken over
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(vtxundo);
|
||||
READWRITE(insertUndo);
|
||||
READWRITE(expireUndo);
|
||||
READWRITE(insertSupportUndo);
|
||||
READWRITE(expireSupportUndo);
|
||||
READWRITE(takeoverHeightUndo);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
12
src/util.cpp
12
src/util.cpp
|
@ -81,8 +81,8 @@
|
|||
// Application startup time (used for uptime calculation)
|
||||
const int64_t nStartupTime = GetTime();
|
||||
|
||||
const char * const BITCOIN_CONF_FILENAME = "bitcoin.conf";
|
||||
const char * const BITCOIN_PID_FILENAME = "bitcoind.pid";
|
||||
const char * const BITCOIN_CONF_FILENAME = "lbrycrd.conf";
|
||||
const char * const BITCOIN_PID_FILENAME = "lbrycrd.pid";
|
||||
|
||||
ArgsManager gArgs;
|
||||
|
||||
|
@ -713,10 +713,10 @@ fs::path GetDefaultDataDir()
|
|||
// Windows < Vista: C:\Documents and Settings\Username\Application Data\Bitcoin
|
||||
// Windows >= Vista: C:\Users\Username\AppData\Roaming\Bitcoin
|
||||
// Mac: ~/Library/Application Support/Bitcoin
|
||||
// Unix: ~/.bitcoin
|
||||
// Unix: ~/.lbrycrd
|
||||
#ifdef WIN32
|
||||
// Windows
|
||||
return GetSpecialFolderPath(CSIDL_APPDATA) / "Bitcoin";
|
||||
return GetSpecialFolderPath(CSIDL_APPDATA) / "lbrycrd";
|
||||
#else
|
||||
fs::path pathRet;
|
||||
char* pszHome = getenv("HOME");
|
||||
|
@ -726,10 +726,10 @@ fs::path GetDefaultDataDir()
|
|||
pathRet = fs::path(pszHome);
|
||||
#ifdef MAC_OSX
|
||||
// Mac
|
||||
return pathRet / "Library/Application Support/Bitcoin";
|
||||
return pathRet / "Library/Application Support/lbrycrd";
|
||||
#else
|
||||
// Unix
|
||||
return pathRet / ".bitcoin";
|
||||
return pathRet / ".lbrycrd";
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
180
src/validation.h
180
src/validation.h
|
@ -11,12 +11,16 @@
|
|||
#endif
|
||||
|
||||
#include <amount.h>
|
||||
#include <claimtrie.h>
|
||||
#include <coins.h>
|
||||
#include <fs.h>
|
||||
#include <index/txindex.h>
|
||||
#include <nameclaim.h>
|
||||
#include <protocol.h> // For CMessageHeader::MessageStartChars
|
||||
#include <policy/feerate.h>
|
||||
#include <script/script_error.h>
|
||||
#include <sync.h>
|
||||
#include <txmempool.h>
|
||||
#include <versionbits.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
@ -166,6 +170,8 @@ extern size_t nCoinCacheUsage;
|
|||
extern CFeeRate minRelayTxFee;
|
||||
/** Absolute maximum transaction fee (in satoshis) used by wallet and mempool (rejects high fee in sendrawtransaction) */
|
||||
extern CAmount maxTxFee;
|
||||
/** Used to calculate minimum fee for claim trie transactions **/
|
||||
extern CAmount minFeePerNameClaimChar;
|
||||
/** If the tip is older than this (in seconds), the node is considered to be in initial block download. */
|
||||
extern int64_t nMaxTipAge;
|
||||
extern bool fEnableReplacement;
|
||||
|
@ -249,6 +255,10 @@ bool CheckDiskSpace(uint64_t nAdditionalBytes = 0, bool blocks_dir = false);
|
|||
FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false);
|
||||
/** Translation to a filesystem path */
|
||||
fs::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix);
|
||||
/** Utility method for going back to a previous state **/
|
||||
bool RollBackTo(const CBlockIndex* targetIndex, CCoinsViewCache& coinsCache, CClaimTrieCache& trieCache);
|
||||
/** Get a cryptographic proof that a name maps to a value **/
|
||||
bool GetProofForName(const CBlockIndex* pindexProof, const std::string& name, CClaimTrieProof& proof);
|
||||
/** Import blocks from an external file */
|
||||
bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp = nullptr);
|
||||
/** Ensures we have a genesis block in the block tree, possibly writing one to disk. */
|
||||
|
@ -349,6 +359,172 @@ bool TestLockPointValidity(const LockPoints* lp);
|
|||
*/
|
||||
bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp = nullptr, bool useExistingLockPoints = false);
|
||||
|
||||
/************************************************************
|
||||
* LBRY moved these from validation.cpp, for testcase usage
|
||||
* BEGIN
|
||||
************************************************************/
|
||||
|
||||
/**
|
||||
* Global state
|
||||
*/
|
||||
namespace {
|
||||
struct CBlockIndexWorkComparator
|
||||
{
|
||||
bool operator()(const CBlockIndex *pa, const CBlockIndex *pb) const {
|
||||
// First sort by most total work, ...
|
||||
if (pa->nChainWork > pb->nChainWork) return false;
|
||||
if (pa->nChainWork < pb->nChainWork) return true;
|
||||
|
||||
// ... then by earliest time received, ...
|
||||
if (pa->nSequenceId < pb->nSequenceId) return false;
|
||||
if (pa->nSequenceId > pb->nSequenceId) return true;
|
||||
|
||||
// Use pointer address as tie breaker (should only happen with blocks
|
||||
// loaded from disk, as those all have id 0).
|
||||
if (pa < pb) return false;
|
||||
if (pa > pb) return true;
|
||||
|
||||
// Identical blocks.
|
||||
return false;
|
||||
}
|
||||
};
|
||||
} // anon namespace
|
||||
|
||||
class ConnectTrace;
|
||||
|
||||
enum DisconnectResult
|
||||
{
|
||||
DISCONNECT_OK, // All good.
|
||||
DISCONNECT_UNCLEAN, // Rolled back, but UTXO set was inconsistent with block.
|
||||
DISCONNECT_FAILED // Something else went wrong.
|
||||
};
|
||||
|
||||
/**
|
||||
* CChainState stores and provides an API to update our local knowledge of the
|
||||
* current best chain and header tree.
|
||||
*
|
||||
* It generally provides access to the current block tree, as well as functions
|
||||
* to provide new data, which it will appropriately validate and incorporate in
|
||||
* its state as necessary.
|
||||
*
|
||||
* Eventually, the API here is targeted at being exposed externally as a
|
||||
* consumable libconsensus library, so any functions added must only call
|
||||
* other class member functions, pure functions in other parts of the consensus
|
||||
* library, callbacks via the validation interface, or read/write-to-disk
|
||||
* functions (eventually this will also be via callbacks).
|
||||
*/
|
||||
class CChainState {
|
||||
private:
|
||||
/**
|
||||
* The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS (for itself and all ancestors) and
|
||||
* as good as our current tip or better. Entries may be failed, though, and pruning nodes may be
|
||||
* missing the data for the block.
|
||||
*/
|
||||
std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates;
|
||||
|
||||
/**
|
||||
* Every received block is assigned a unique and increasing identifier, so we
|
||||
* know which one to give priority in case of a fork.
|
||||
*/
|
||||
CCriticalSection cs_nBlockSequenceId;
|
||||
/** Blocks loaded from disk are assigned id 0, so start the counter at 1. */
|
||||
int32_t nBlockSequenceId = 1;
|
||||
/** Decreasing counter (used by subsequent preciousblock calls). */
|
||||
int32_t nBlockReverseSequenceId = -1;
|
||||
/** chainwork for the last block that preciousblock has been applied to. */
|
||||
arith_uint256 nLastPreciousChainwork = 0;
|
||||
|
||||
/** In order to efficiently track invalidity of headers, we keep the set of
|
||||
* blocks which we tried to connect and found to be invalid here (ie which
|
||||
* were set to BLOCK_FAILED_VALID since the last restart). We can then
|
||||
* walk this set and check if a new header is a descendant of something in
|
||||
* this set, preventing us from having to walk mapBlockIndex when we try
|
||||
* to connect a bad block and fail.
|
||||
*
|
||||
* While this is more complicated than marking everything which descends
|
||||
* from an invalid block as invalid at the time we discover it to be
|
||||
* invalid, doing so would require walking all of mapBlockIndex to find all
|
||||
* descendants. Since this case should be very rare, keeping track of all
|
||||
* BLOCK_FAILED_VALID blocks in a set should be just fine and work just as
|
||||
* well.
|
||||
*
|
||||
* Because we already walk mapBlockIndex in height-order at startup, we go
|
||||
* ahead and mark descendants of invalid blocks as FAILED_CHILD at that time,
|
||||
* instead of putting things in this set.
|
||||
*/
|
||||
std::set<CBlockIndex*> m_failed_blocks;
|
||||
|
||||
/**
|
||||
* the ChainState CriticalSection
|
||||
* A lock that must be held when modifying this ChainState - held in ActivateBestChain()
|
||||
*/
|
||||
CCriticalSection m_cs_chainstate;
|
||||
|
||||
public:
|
||||
CChain chainActive;
|
||||
BlockMap mapBlockIndex;
|
||||
std::multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked;
|
||||
CBlockIndex *pindexBestInvalid = nullptr;
|
||||
|
||||
bool LoadBlockIndex(const Consensus::Params& consensus_params, CBlockTreeDB& blocktree) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock);
|
||||
|
||||
/**
|
||||
* If a block header hasn't already been seen, call CheckBlockHeader on it, ensure
|
||||
* that it doesn't descend from an invalid block, and then add it to mapBlockIndex.
|
||||
*/
|
||||
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
// Block (dis)connection on a given view:
|
||||
DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view, CClaimTrieCache& trieCache);
|
||||
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex,
|
||||
CCoinsViewCache& view, CClaimTrieCache& trieCache, const CChainParams& chainparams, bool fJustCheck = false);
|
||||
|
||||
// Block disconnection on our pcoinsTip:
|
||||
bool DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions *disconnectpool);
|
||||
|
||||
// Manual block validity manipulation:
|
||||
bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
|
||||
bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
bool ReplayBlocks(const CChainParams& params, CCoinsView* view);
|
||||
bool RewindBlockIndex(const CChainParams& params);
|
||||
bool LoadGenesisBlock(const CChainParams& chainparams);
|
||||
|
||||
void PruneBlockIndexCandidates();
|
||||
|
||||
void UnloadBlockIndex();
|
||||
|
||||
private:
|
||||
bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace);
|
||||
bool ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool);
|
||||
|
||||
CBlockIndex* AddToBlockIndex(const CBlockHeader& block) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
/** Create a new block index entry for a given block hash */
|
||||
CBlockIndex* InsertBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
/**
|
||||
* Make various assertions about the state of the block index.
|
||||
*
|
||||
* By default this only executes fully when using the Regtest chain; see: fCheckBlockIndex.
|
||||
*/
|
||||
void CheckBlockIndex(const Consensus::Params& consensusParams);
|
||||
|
||||
void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state);
|
||||
CBlockIndex* FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
|
||||
bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
};
|
||||
|
||||
/************************************************************
|
||||
* LBRY moved these from validation.cpp, for testcase usage
|
||||
* END
|
||||
************************************************************/
|
||||
|
||||
/**
|
||||
* Closure representing one script verification
|
||||
* Note that this stores references to the spending transaction
|
||||
|
@ -460,9 +636,13 @@ extern std::unique_ptr<CCoinsViewDB> pcoinsdbview;
|
|||
/** Global variable that points to the active CCoinsView (protected by cs_main) */
|
||||
extern std::unique_ptr<CCoinsViewCache> pcoinsTip;
|
||||
|
||||
/** Global variable that points to the active CClaimTrie (protected by cs_main) */
|
||||
extern CClaimTrie *pclaimTrie;
|
||||
|
||||
/** Global variable that points to the active block tree (protected by cs_main) */
|
||||
extern std::unique_ptr<CBlockTreeDB> pblocktree;
|
||||
|
||||
|
||||
/**
|
||||
* Return the spend height, which is one more than the inputs.GetBestBlock().
|
||||
* While checking, GetBestBlock() refers to the parent block. (protected by cs_main)
|
||||
|
|
Loading…
Add table
Reference in a new issue