DO NOT MERGE: Updated rebase 0.17 for early review only #257
89 changed files with 11331 additions and 2147 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -61,7 +61,6 @@ src/qt/bitcoin-qt.includes
|
|||
*.pyc
|
||||
*.o
|
||||
*.o-*
|
||||
*.patch
|
||||
*.a
|
||||
*.pb.cc
|
||||
*.pb.h
|
||||
|
@ -116,3 +115,6 @@ test/cache/*
|
|||
|
||||
libbitcoinconsensus.pc
|
||||
contrib/devtools/split-debug.sh
|
||||
|
||||
.idea
|
||||
cmake-build-*/
|
||||
|
|
222
.travis.yml
222
.travis.yml
|
@ -1,164 +1,70 @@
|
|||
dist: trusty
|
||||
os: linux
|
||||
language: minimal
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
sudo: required
|
||||
dist: xenial
|
||||
language: c
|
||||
env: TARGET=linux
|
||||
- os: linux
|
||||
sudo: required
|
||||
dist: xenial
|
||||
language: c
|
||||
env: TARGET=windows
|
||||
- os: osx
|
||||
language: c
|
||||
osx_image: xcode8.3
|
||||
env: TARGET=osx
|
||||
cache:
|
||||
apt: true
|
||||
ccache: true
|
||||
directories:
|
||||
- build
|
||||
- depends/built
|
||||
- depends/sdk-sources
|
||||
- $HOME/.ccache
|
||||
stages:
|
||||
- lint
|
||||
- test
|
||||
env:
|
||||
global:
|
||||
- MAKEJOBS=-j3
|
||||
- RUN_TESTS=false
|
||||
- RUN_BENCH=false # Set to true for any one job that has debug enabled, to quickly check bench is not crashing or hitting assertions
|
||||
- DOCKER_NAME_TAG=ubuntu:18.04
|
||||
- LC_ALL=C.UTF-8
|
||||
- BOOST_TEST_RANDOM=1$TRAVIS_BUILD_ID
|
||||
- CCACHE_SIZE=100M
|
||||
- CCACHE_TEMPDIR=/tmp/.ccache-temp
|
||||
- CCACHE_COMPRESS=1
|
||||
- CCACHE_DIR=$HOME/.ccache
|
||||
- BASE_OUTDIR=$TRAVIS_BUILD_DIR/out
|
||||
- SDK_URL=https://bitcoincore.org/depends-sources/sdks
|
||||
- WINEDEBUG=fixme-all
|
||||
- DOCKER_PACKAGES="build-essential libtool autotools-dev automake pkg-config bsdmainutils curl git ca-certificates ccache"
|
||||
git:
|
||||
depth: false
|
||||
before_install:
|
||||
- export PATH=$(echo $PATH | tr ':' "\n" | sed '/\/opt\/python/d' | tr "\n" ":" | sed "s|::|:|g")
|
||||
- BEGIN_FOLD () { echo ""; CURRENT_FOLD_NAME=$1; echo "travis_fold:start:${CURRENT_FOLD_NAME}"; }
|
||||
- END_FOLD () { RET=$?; echo "travis_fold:end:${CURRENT_FOLD_NAME}"; return $RET; }
|
||||
install:
|
||||
- travis_retry docker pull $DOCKER_NAME_TAG
|
||||
- env | grep -E '^(CCACHE_|WINEDEBUG|LC_ALL|BOOST_TEST_RANDOM|CONFIG_SHELL)' | tee /tmp/env
|
||||
- if [[ $HOST = *-mingw32 ]]; then DOCKER_ADMIN="--cap-add SYS_ADMIN"; fi
|
||||
- DOCKER_ID=$(docker run $DOCKER_ADMIN -idt --mount type=bind,src=$TRAVIS_BUILD_DIR,dst=$TRAVIS_BUILD_DIR --mount type=bind,src=$CCACHE_DIR,dst=$CCACHE_DIR -w $TRAVIS_BUILD_DIR --env-file /tmp/env $DOCKER_NAME_TAG)
|
||||
- DOCKER_EXEC () { docker exec $DOCKER_ID bash -c "cd $PWD && $*"; }
|
||||
- if [ -n "$DPKG_ADD_ARCH" ]; then DOCKER_EXEC dpkg --add-architecture "$DPKG_ADD_ARCH" ; fi
|
||||
- travis_retry DOCKER_EXEC apt-get update
|
||||
- travis_retry DOCKER_EXEC apt-get install --no-install-recommends --no-upgrade -qq $PACKAGES $DOCKER_PACKAGES
|
||||
before_script:
|
||||
- DOCKER_EXEC echo \> \$HOME/.bitcoin # Make sure default datadir does not exist and is never read by creating a dummy file
|
||||
- mkdir -p depends/SDKs depends/sdk-sources
|
||||
- if [ -n "$OSX_SDK" -a ! -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then curl --location --fail $SDK_URL/MacOSX${OSX_SDK}.sdk.tar.gz -o depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi
|
||||
- if [ -n "$OSX_SDK" -a -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then tar -C depends/SDKs -xf depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi
|
||||
- if [[ $HOST = *-mingw32 ]]; then DOCKER_EXEC update-alternatives --set $HOST-g++ \$\(which $HOST-g++-posix\); fi
|
||||
- if [ -z "$NO_DEPENDS" ]; then DOCKER_EXEC CONFIG_SHELL= make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS; fi
|
||||
- date +%s > "${TRAVIS_BUILD_DIR}/start_time"
|
||||
- ls -lh build
|
||||
- du -h -d 2 build
|
||||
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install ccache; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then export PATH="/usr/local/opt/ccache/libexec:$PATH"; fi
|
||||
install: true
|
||||
script:
|
||||
- export TRAVIS_COMMIT_LOG=`git log --format=fuller -1`
|
||||
- OUTDIR=$BASE_OUTDIR/$TRAVIS_PULL_REQUEST/$TRAVIS_JOB_NUMBER-$HOST
|
||||
- BITCOIN_CONFIG_ALL="--disable-dependency-tracking --prefix=$TRAVIS_BUILD_DIR/depends/$HOST --bindir=$OUTDIR/bin --libdir=$OUTDIR/lib"
|
||||
- if [ -z "$NO_DEPENDS" ]; then DOCKER_EXEC ccache --max-size=$CCACHE_SIZE; fi
|
||||
- BEGIN_FOLD autogen; test -n "$CONFIG_SHELL" && DOCKER_EXEC "$CONFIG_SHELL" -c "./autogen.sh" || DOCKER_EXEC ./autogen.sh; END_FOLD
|
||||
- mkdir build && cd build
|
||||
- BEGIN_FOLD configure; DOCKER_EXEC ../configure --cache-file=config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false); END_FOLD
|
||||
- BEGIN_FOLD distdir; DOCKER_EXEC make distdir VERSION=$HOST; END_FOLD
|
||||
- cd bitcoin-$HOST
|
||||
- BEGIN_FOLD configure; DOCKER_EXEC ./configure --cache-file=../config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false); END_FOLD
|
||||
- BEGIN_FOLD build; DOCKER_EXEC make $MAKEJOBS $GOAL || ( echo "Build failure. Verbose build follows." && DOCKER_EXEC make $GOAL V=1 ; false ); END_FOLD
|
||||
- if [ "$RUN_TESTS" = "true" ]; then BEGIN_FOLD unit-tests; DOCKER_EXEC LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/depends/$HOST/lib make $MAKEJOBS check VERBOSE=1; END_FOLD; fi
|
||||
- if [ "$RUN_BENCH" = "true" ]; then BEGIN_FOLD bench; DOCKER_EXEC LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/depends/$HOST/lib $OUTDIR/bin/bench_bitcoin -scaling=0.001 ; END_FOLD; fi
|
||||
- if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then extended="--extended --exclude feature_pruning,feature_dbcrash"; fi
|
||||
- if [ "$RUN_TESTS" = "true" ]; then BEGIN_FOLD functional-tests; DOCKER_EXEC test/functional/test_runner.py --combinedlogslen=4000 --coverage --quiet --failfast ${extended}; END_FOLD; fi
|
||||
after_script:
|
||||
- echo $TRAVIS_COMMIT_RANGE
|
||||
- echo $TRAVIS_COMMIT_LOG
|
||||
jobs:
|
||||
include:
|
||||
# ARM
|
||||
- stage: test
|
||||
env: >-
|
||||
HOST=arm-linux-gnueabihf
|
||||
PACKAGES="g++-arm-linux-gnueabihf"
|
||||
DEP_OPTS="NO_QT=1"
|
||||
GOAL="install"
|
||||
BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports"
|
||||
# Win32
|
||||
- stage: test
|
||||
env: >-
|
||||
HOST=i686-w64-mingw32
|
||||
DPKG_ADD_ARCH="i386"
|
||||
DEP_OPTS="NO_QT=1"
|
||||
PACKAGES="python3 nsis g++-mingw-w64-i686 wine-binfmt wine32"
|
||||
RUN_TESTS=true
|
||||
GOAL="install"
|
||||
BITCOIN_CONFIG="--enable-reduce-exports"
|
||||
# Win64
|
||||
- stage: test
|
||||
env: >-
|
||||
HOST=x86_64-w64-mingw32
|
||||
DEP_OPTS="NO_QT=1"
|
||||
PACKAGES="python3 nsis g++-mingw-w64-x86-64 wine-binfmt wine64"
|
||||
RUN_TESTS=true
|
||||
GOAL="install"
|
||||
BITCOIN_CONFIG="--enable-reduce-exports"
|
||||
# 32-bit + dash
|
||||
- stage: test
|
||||
env: >-
|
||||
HOST=i686-pc-linux-gnu
|
||||
PACKAGES="g++-multilib python3-zmq"
|
||||
DEP_OPTS="NO_QT=1"
|
||||
RUN_TESTS=true
|
||||
GOAL="install"
|
||||
BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++"
|
||||
CONFIG_SHELL="/bin/dash"
|
||||
# x86_64 Linux (uses qt5 dev package instead of depends Qt to speed up build and avoid timeout)
|
||||
- stage: test
|
||||
env: >-
|
||||
HOST=x86_64-unknown-linux-gnu
|
||||
PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools protobuf-compiler libdbus-1-dev libharfbuzz-dev libprotobuf-dev"
|
||||
DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1"
|
||||
RUN_TESTS=true
|
||||
RUN_BENCH=true
|
||||
GOAL="install"
|
||||
BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports --enable-debug CXXFLAGS=\"-g0 -O2\""
|
||||
# x86_64 Linux (Qt5 & system libs)
|
||||
- stage: test
|
||||
env: >-
|
||||
HOST=x86_64-unknown-linux-gnu
|
||||
PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libssl1.0-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libprotobuf-dev protobuf-compiler libqrencode-dev"
|
||||
NO_DEPENDS=1
|
||||
RUN_TESTS=true
|
||||
GOAL="install"
|
||||
BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --enable-glibc-back-compat --enable-reduce-exports --with-gui=qt5 CPPFLAGS=-DDEBUG_LOCKORDER"
|
||||
# x86_64 Linux, No wallet
|
||||
- stage: test
|
||||
env: >-
|
||||
HOST=x86_64-unknown-linux-gnu
|
||||
PACKAGES="python3"
|
||||
DEP_OPTS="NO_WALLET=1"
|
||||
RUN_TESTS=true
|
||||
GOAL="install"
|
||||
BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports"
|
||||
# Cross-Mac
|
||||
- stage: test
|
||||
env: >-
|
||||
HOST=x86_64-apple-darwin14
|
||||
PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev python3-setuptools-git"
|
||||
OSX_SDK=10.11
|
||||
GOAL="all deploy"
|
||||
BITCOIN_CONFIG="--enable-gui --enable-reduce-exports --enable-werror"
|
||||
- stage: lint
|
||||
env:
|
||||
cache: false
|
||||
language: python
|
||||
python: '3.6'
|
||||
install:
|
||||
- travis_retry pip install flake8==3.5.0
|
||||
before_script:
|
||||
- git fetch --unshallow
|
||||
script:
|
||||
- if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then test/lint/commit-script-check.sh $TRAVIS_COMMIT_RANGE; fi
|
||||
- test/lint/git-subtree-check.sh src/crypto/ctaes
|
||||
- test/lint/git-subtree-check.sh src/secp256k1
|
||||
- test/lint/git-subtree-check.sh src/univalue
|
||||
- test/lint/git-subtree-check.sh src/leveldb
|
||||
- test/lint/check-doc.py
|
||||
- test/lint/check-rpc-mappings.py .
|
||||
- test/lint/lint-all.sh
|
||||
- if [ "$TRAVIS_REPO_SLUG" = "bitcoin/bitcoin" -a "$TRAVIS_EVENT_TYPE" = "cron" ]; then
|
||||
while read LINE; do travis_retry gpg --keyserver hkp://subset.pool.sks-keyservers.net --recv-keys $LINE; done < contrib/verify-commits/trusted-keys &&
|
||||
travis_wait 50 contrib/verify-commits/verify-commits.py;
|
||||
fi
|
||||
- mkdir -p "dist/${TRAVIS_BRANCH}"
|
||||
- if [[ "${TARGET}" == "osx" ]]; then ./reproducible_build.sh -t -o -c; fi
|
||||
- if [[ "${TARGET}" == "linux" ]]; then ./reproducible_build.sh -t -o -c -f; fi
|
||||
- if [[ "${TARGET}" == "windows" ]]; then ./packaging/build_windows.sh; fi
|
||||
- if [[ "${TARGET}" == "osx" ]]; then zip -j "dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip" src/lbrycrdd src/lbrycrd-cli src/lbrycrd-tx; fi
|
||||
- if [[ "${TARGET}" == "linux" ]]; then zip -j "dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip" src/lbrycrdd src/lbrycrd-cli src/lbrycrd-tx; fi
|
||||
- if [[ "${TARGET}" == "windows" ]]; then zip -j "dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip" src/lbrycrdd.exe src/lbrycrd-cli.exe src/lbrycrd-tx.exe; fi
|
||||
- if [[ "${TARGET}" == "osx" ]]; then shasum -a 256 dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip > dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}-sha256.txt; fi
|
||||
- if [[ "${TARGET}" == "linux" ]]; then sha256sum -b dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip > dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}-sha256.txt; fi
|
||||
- if [[ "${TARGET}" == "windows" ]]; then sha256sum -b dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip > dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}-sha256.txt; fi
|
||||
- cat dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}-sha256.txt
|
||||
before_cache:
|
||||
- ls -lh build
|
||||
- du -h -d 2 build
|
||||
deploy:
|
||||
- provider: releases
|
||||
draft: true
|
||||
file: "dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip"
|
||||
name: "${TRAVIS_BRANCH}"
|
||||
skip_cleanup: true
|
||||
target_commitish: $TRAVIS_COMMIT
|
||||
tag_name: $TRAVIS_TAG
|
||||
on:
|
||||
tags: true
|
||||
api_key:
|
||||
secure: "Ni5WZNR5CefWXpyDUQLMQbQ2LH4Iot+0SqIoM9c4maW06al1M8vu57vWuj2cESsW7JsaBehCE45Cwmo5kWyEjAiZY8sIMmvixkMP/8uPWuLgNmnIbm7U+d0j652DmZshDYtt8EomqV2RhAx/rmBnzGkruLOw9WTp9ZdBN3WbTt/IpZ2gMgVbGWYGOx+uRw7/yGw8m4gShQheto/dycbyyR3XV2WP9wuLmNYkcQ6JumSoQdDWXcvVfbCwylGq2sLDKwhvfTr4iwYyYsWdmhfdEQl0WcIv5C8xgdiY2vzhi2LmLqFbS/fvKNC26Tfo4bOHFG/eOnvqc+yyEB8B/xqW9Gs+A0TUh/3N30vHYZGcpiDU35DwAN5bZ1+s+mr/ZrNzBJ5BgT8io3g0Ko8gykbDvFQVpg7kxFsqA1YCikEpG86lVGk6clTa5guJvAHse+DfnbWO1nfDxYQXW0md861m0txk8RpTC/TVNyH/lL/vsS7LB67EHhRdZY+O1+5sUGMdtvvhMoxJYCwQGpLkh43KRsKynkMUR94w2O9hc8cknXdV3wrndVz00XNdcur6y4D7HTll1tBrF68CA2yKUSY5hsjtPmdlN+DW8ou/rJiKOpQZ/Xzp69AQEheOFfDPItxQRYxWj0dMOk8eszf0wFvi1N7J/hT/IHnuX5ITfa/T4NE="
|
||||
- provider: s3
|
||||
access_key_id: AKIAICKFHNTR5RITASAQ
|
||||
secret_access_key:
|
||||
secure: Qfgs8vGnEUvgiZNP2S9zY8qHEzaDOceF/XTv32jRBOISWfTqOTE56DZbOp8WKHPAqn0dx04jKA1NfV9f06sXU1NVbiJ2VYISo6XAk0n3RBJL3/mhNxvut/zM2DHkFPljWTkWEColS0ZyA3m4eUyJvAw/i+mOBT/zDD/oIlS5Uo5l/x3LmF9fYBuei0ucwSQeNOr2wCMIl+pXrIU7B3lEzXh1asayW6A9y7DOqMLnrSQ7TLlSssbnhuhDVpFx0xxX/U2NPraotbGKdo3wwMbms/lluBe60I/LsDNp9/SZXMDXh2YLGUImr97octwpdzIMjF+kU7QAZJzM7grz8PU9+MQh2V5sn6Xsww2x4PdkmHGz/2FMzhrCrlPf5JCaPBH49G+w4/29HYmMrlimOOVx4qXCpQ/XtWWne/d6MF0qqT6JhdPuD9ohmTpxcHRkCe2fxUw6Yn3dj+/+YoCywAcwcBm5jLpAotmWoCmmcnm9rvB7bIuPPZAjJUZViCnyvwY4Tj3Fb+sOuK4b/O5D2+cuS+WgQRkN/RspYlXrXTIh8Efv/yhW5L9WdzG1OExJDw2hX5VTccRRgIKZxZp80U2eYqn2M07+1nU+ShX4kgiSon46k5cfacLgzLKWEyCxWSSTbsYcwRxvDEjtYy4wxAYx8+J3dgQPs/opDXoQTJMjud0=
|
||||
bucket: build.lbry.io
|
||||
upload-dir: lbrycrd
|
||||
acl: public_read
|
||||
local_dir: dist
|
||||
skip_cleanup: true
|
||||
on:
|
||||
repo: lbryio/lbrycrd
|
||||
all_branches: true
|
||||
|
|
57
CMakeLists.txt
Normal file
57
CMakeLists.txt
Normal file
|
@ -0,0 +1,57 @@
|
|||
cmake_minimum_required(VERSION 3.7)
|
||||
project(lbrycrd_clion) # Do not use for full compile. This is for CLion syntax checking only.
|
||||
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
|
||||
if(EXISTS "build/boost")
|
||||
set(BOOST_ROOT "build/boost" CACHE PATH "Boost library path")
|
||||
set(Boost_NO_SYSTEM_PATHS on CACHE BOOL "Do not search system for Boost")
|
||||
endif()
|
||||
find_package(Boost REQUIRED COMPONENTS filesystem program_options thread chrono locale)
|
||||
|
||||
file(GLOB sources
|
||||
src/*.h src/*.cpp
|
||||
src/wallet/*.h src/wallet/*.cpp
|
||||
src/support/*.h src/support/*.cpp src/support/allocators/*.h
|
||||
src/script/*.h src/script/*.cpp
|
||||
src/rpc/*.h src/rpc/*.cpp
|
||||
src/primitives/*.h src/primitives/*.cpp
|
||||
src/policy/*.h src/policy/*.cpp
|
||||
src/crypto/*.h src/crypto/*.cpp
|
||||
src/consensus/*.h src/consensus/*.cpp
|
||||
src/compat/*.h src/compat/*.cpp
|
||||
)
|
||||
list(FILTER sources EXCLUDE REGEX "src/bitcoin*.cpp$")
|
||||
|
||||
include_directories(${Boost_INCLUDE_DIRS}
|
||||
build/bdb/include
|
||||
build/libevent/include
|
||||
build/openssl/include
|
||||
src/support/allocators
|
||||
src/support
|
||||
src/rpc
|
||||
src/policy
|
||||
src/wallet src/script
|
||||
src/leveldb/helpers/memenv
|
||||
src/leveldb/include
|
||||
src/config
|
||||
src/crypto
|
||||
src/compat
|
||||
src/obj
|
||||
src/univalue/include
|
||||
src/secp256k1/include
|
||||
src/
|
||||
)
|
||||
|
||||
add_compile_definitions(HAVE_CONFIG_H)
|
||||
|
||||
add_executable(lbrycrd-cli src/bitcoin-cli.cpp ${sources})
|
||||
add_executable(lbrycrd-tx src/bitcoin-tx.cpp ${sources})
|
||||
add_executable(lbrycrdd src/bitcoind.cpp ${sources})
|
||||
|
||||
file(GLOB tests src/test/*.cpp)
|
||||
foreach(test ${tests})
|
||||
get_filename_component(filename ${test} NAME_WE)
|
||||
add_executable(${filename} ${test} ${sources})
|
||||
target_include_directories(${filename} PRIVATE src/test)
|
||||
endforeach(test)
|
|
@ -640,6 +640,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])
|
||||
|
@ -961,7 +962,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"
|
||||
|
||||
|
||||
dnl If boost (prior to 1.57) was built without c++11, it emulated scoped enums
|
||||
|
@ -1431,7 +1432,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
|
||||
|
|
18
packaging/build_windows.sh
Executable file
18
packaging/build_windows.sh
Executable file
|
@ -0,0 +1,18 @@
|
|||
#! /bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
g++-mingw-w64-i686 mingw-w64-i686-dev g++-mingw-w64-x86-64 \
|
||||
mingw-w64-x86-64-dev build-essential libtool autotools-dev automake pkg-config \
|
||||
libssl-dev libevent-dev bsdmainutils curl ca-certificates
|
||||
|
||||
cd depends
|
||||
make HOST=i686-w64-mingw32 NO_QT=1
|
||||
cd ..
|
||||
patch -p1 < packaging/remove_consensus.patch
|
||||
./autogen.sh
|
||||
./configure --prefix=`pwd`/depends/i686-w64-mingw32 --without-gui
|
||||
make
|
||||
|
23
packaging/remove_consensus.patch
Normal file
23
packaging/remove_consensus.patch
Normal file
|
@ -0,0 +1,23 @@
|
|||
diff --git a/src/Makefile.am b/src/Makefile.am
|
||||
index a9f0a94..d71bfeb 100644
|
||||
--- a/src/Makefile.am
|
||||
+++ b/src/Makefile.am
|
||||
@@ -64,12 +64,12 @@ if ENABLE_ZMQ
|
||||
EXTRA_LIBRARIES += libbitcoin_zmq.a
|
||||
endif
|
||||
|
||||
-if BUILD_BITCOIN_LIBS
|
||||
-lib_LTLIBRARIES = libbitcoinconsensus.la
|
||||
-LIBBITCOINCONSENSUS=libbitcoinconsensus.la
|
||||
-else
|
||||
-LIBBITCOINCONSENSUS=
|
||||
-endif
|
||||
+# if BUILD_BITCOIN_LIBS
|
||||
+# lib_LTLIBRARIES = libbitcoinconsensus.la
|
||||
+# LIBBITCOINCONSENSUS=libbitcoinconsensus.la
|
||||
+# else
|
||||
+# LIBBITCOINCONSENSUS=
|
||||
+# endif
|
||||
|
||||
bin_PROGRAMS =
|
||||
TESTS =
|
410
reproducible_build.sh
Executable file
410
reproducible_build.sh
Executable file
|
@ -0,0 +1,410 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -euo 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
|
||||
if [ ! -f "${START_TIME_FILE}" ]; then
|
||||
date +%s > "${START_TIME_FILE}"
|
||||
fi
|
||||
|
||||
|
||||
NEXT_TIME=60
|
||||
function exit_at_40() {
|
||||
if [ -f "${START_TIME_FILE}" ]; then
|
||||
NOW=$(date +%s)
|
||||
START=$(cat "${START_TIME_FILE}")
|
||||
TIMEOUT_SECS=2400 # 40 * 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 40 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_40 "$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.9
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
function build_dependencies() {
|
||||
if [ "${OS_NAME}" = "osx" ]; then
|
||||
install_brew_packages
|
||||
else
|
||||
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/lbryio/lbrycrd-dependencies.git "${LBRYCRD_DEPENDENCIES}"
|
||||
fi
|
||||
# TODO: if the repo exists, make sure its clean: revert to head.
|
||||
mkdir -p "${LOG_DIR}"
|
||||
|
||||
build_dependency "${BDB_PREFIX}" "${LOG_DIR}/bdb_build.log" build_bdb
|
||||
build_dependency "${OPENSSL_PREFIX}" "${LOG_DIR}/openssl_build.log" build_openssl
|
||||
|
||||
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 "${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 "${OPENSSL_LOG}" "Waiting for openssl to finish building"
|
||||
make install >> "${OPENSSL_LOG}" 2>&1
|
||||
}
|
||||
|
||||
function build_boost() {
|
||||
BOOST_LOG="$1"
|
||||
cd boost_1_59_0
|
||||
echo "Building Boost. tail -f ${BOOST_LOG} to see the details and monitor progress"
|
||||
./bootstrap.sh --prefix="${BOOST_PREFIX}" > "${BOOST_LOG}" 2>&1
|
||||
background "./b2 link=static cxxflags=-fPIC install" \
|
||||
"${BOOST_LOG}" \
|
||||
"Waiting for boost to finish building"
|
||||
}
|
||||
|
||||
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 "${LIBEVENT_LOG}" "Waiting for libevent to finish building"
|
||||
make install >> "${LIBEVENT_LOG}"
|
||||
}
|
||||
|
||||
function build_dependency() {
|
||||
pushd .
|
||||
PREFIX=$1
|
||||
LOG=$2
|
||||
BUILD=$3
|
||||
if [ ! -d "${PREFIX}" ]; then
|
||||
trap 'cleanup "${PREFIX}" "${LOG}"' INT TERM EXIT
|
||||
cd "${LBRYCRD_DEPENDENCIES}"
|
||||
mkdir -p "${PREFIX}"
|
||||
"${BUILD}" "${LOG}"
|
||||
trap - INT TERM EXIT
|
||||
fi
|
||||
popd
|
||||
}
|
||||
|
||||
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/ -static-libstdc++"
|
||||
CPPFLAGS="-I${OPENSSL_PREFIX}/include -I${BDB_PREFIX}/include -I${LIBEVENT_PREFIX}/include/"
|
||||
if [ "${OS_NAME}" = "osx" ]; then
|
||||
OPTIONS="--enable-cxx --enable-static --disable-shared --with-pic"
|
||||
else
|
||||
OPTIONS=""
|
||||
fi
|
||||
./configure --without-gui ${OPTIONS} \
|
||||
--with-boost="${BOOST_PREFIX}" \
|
||||
LDFLAGS="${LDFLAGS}" \
|
||||
CPPFLAGS="${CPPFLAGS}" >> "${LBRYCRD_LOG}" 2>&1
|
||||
background make "${LBRYCRD_LOG}" "Waiting for lbrycrd to finish building"
|
||||
src/test/test_lbrycrd
|
||||
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
|
||||
git diff -U0 origin/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"
|
||||
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 \
|
||||
|
@ -383,6 +394,7 @@ libbitcoin_common_a_SOURCES = \
|
|||
key.cpp \
|
||||
key_io.cpp \
|
||||
keystore.cpp \
|
||||
nameclaim.cpp \
|
||||
netaddress.cpp \
|
||||
netbase.cpp \
|
||||
policy/feerate.cpp \
|
||||
|
@ -416,6 +428,7 @@ libbitcoin_util_a_SOURCES = \
|
|||
support/cleanse.cpp \
|
||||
sync.cpp \
|
||||
threadinterrupt.cpp \
|
||||
uint256.cpp \
|
||||
util.cpp \
|
||||
utilmoneystr.cpp \
|
||||
utilstrencodings.cpp \
|
||||
|
@ -441,7 +454,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 +474,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
|
||||
|
|
|
@ -2,13 +2,14 @@
|
|||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
bin_PROGRAMS += test/test_bitcoin
|
||||
noinst_PROGRAMS += test/test_bitcoin_fuzzy
|
||||
bin_PROGRAMS += test/test_lbrycrd
|
||||
noinst_PROGRAMS += test/test_lbrycrd_fuzzy
|
||||
TEST_SRCDIR = test
|
||||
TEST_BINARY=test/test_bitcoin$(EXEEXT)
|
||||
TEST_BINARY=test/test_lbrycrd$(EXEEXT)
|
||||
|
||||
JSON_TEST_FILES = \
|
||||
test/data/base58_encode_decode.json \
|
||||
test/data/base58_keys_valid.json \
|
||||
test/data/key_io_valid.json \
|
||||
test/data/key_io_invalid.json \
|
||||
test/data/script_tests.json \
|
||||
|
@ -40,6 +41,7 @@ BITCOIN_TESTS =\
|
|||
test/blockchain_tests.cpp \
|
||||
test/blockencodings_tests.cpp \
|
||||
test/bloom_tests.cpp \
|
||||
test/Checkpoints_tests.cpp \
|
||||
test/bswap_tests.cpp \
|
||||
test/checkqueue_tests.cpp \
|
||||
test/coins_tests.cpp \
|
||||
|
@ -61,6 +63,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 \
|
||||
|
@ -105,32 +110,32 @@ BITCOIN_TEST_SUITE += \
|
|||
wallet/test/wallet_test_fixture.h
|
||||
endif
|
||||
|
||||
test_test_bitcoin_SOURCES = $(BITCOIN_TEST_SUITE) $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES)
|
||||
test_test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(TESTDEFS) $(EVENT_CFLAGS)
|
||||
test_test_bitcoin_LDADD =
|
||||
test_test_lbrycrd_SOURCES = $(BITCOIN_TEST_SUITE) $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES)
|
||||
test_test_lbrycrd_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(TESTDEFS) $(EVENT_CFLAGS)
|
||||
test_test_lbrycrd_LDADD =
|
||||
if ENABLE_WALLET
|
||||
test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET)
|
||||
test_test_lbrycrd_LDADD += $(LIBBITCOIN_WALLET)
|
||||
endif
|
||||
|
||||
test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) \
|
||||
test_test_lbrycrd_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) \
|
||||
$(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS)
|
||||
test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||
test_test_lbrycrd_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_lbrycrd_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS)
|
||||
test_test_lbrycrd_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static
|
||||
|
||||
if ENABLE_ZMQ
|
||||
test_test_bitcoin_LDADD += $(ZMQ_LIBS)
|
||||
test_test_lbrycrd_LDADD += $(ZMQ_LIBS)
|
||||
endif
|
||||
#
|
||||
|
||||
# test_bitcoin_fuzzy binary #
|
||||
test_test_bitcoin_fuzzy_SOURCES = test/test_bitcoin_fuzzy.cpp
|
||||
test_test_bitcoin_fuzzy_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
||||
test_test_bitcoin_fuzzy_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||
test_test_bitcoin_fuzzy_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||
test_test_lbrycrd_fuzzy_SOURCES = test/test_bitcoin_fuzzy.cpp
|
||||
test_test_lbrycrd_fuzzy_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
||||
test_test_lbrycrd_fuzzy_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||
test_test_lbrycrd_fuzzy_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||
|
||||
test_test_bitcoin_fuzzy_LDADD = \
|
||||
test_test_lbrycrd_fuzzy_LDADD = \
|
||||
$(LIBUNIVALUE) \
|
||||
$(LIBBITCOIN_SERVER) \
|
||||
$(LIBBITCOIN_COMMON) \
|
||||
|
@ -142,10 +147,10 @@ test_test_bitcoin_fuzzy_LDADD = \
|
|||
$(LIBBITCOIN_CRYPTO_SHANI) \
|
||||
$(LIBSECP256K1)
|
||||
|
||||
test_test_bitcoin_fuzzy_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
|
||||
test_test_lbrycrd_fuzzy_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
|
||||
#
|
||||
|
||||
nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES)
|
||||
nodist_test_test_lbrycrd_SOURCES = $(GENERATED_TEST_FILES)
|
||||
|
||||
$(BITCOIN_TESTS): $(GENERATED_TEST_FILES)
|
||||
|
||||
|
@ -153,13 +158,13 @@ CLEAN_BITCOIN_TEST = test/*.gcda test/*.gcno $(GENERATED_TEST_FILES)
|
|||
|
||||
CLEANFILES += $(CLEAN_BITCOIN_TEST)
|
||||
|
||||
bitcoin_test: $(TEST_BINARY)
|
||||
lbrycrd_test: $(TEST_BINARY)
|
||||
|
||||
bitcoin_test_check: $(TEST_BINARY) FORCE
|
||||
lbrycrd_test_check: $(TEST_BINARY) FORCE
|
||||
$(MAKE) check-TESTS TESTS=$^
|
||||
|
||||
bitcoin_test_clean : FORCE
|
||||
rm -f $(CLEAN_BITCOIN_TEST) $(test_test_bitcoin_OBJECTS) $(TEST_BINARY)
|
||||
lbrycrd_test_clean : FORCE
|
||||
rm -f $(CLEAN_BITCOIN_TEST) $(test_test_lbrycrd_OBJECTS) $(TEST_BINARY)
|
||||
|
||||
check-local: $(BITCOIN_TESTS:.cpp=.cpp.test)
|
||||
@echo "Running test/util/bitcoin-util-test.py..."
|
||||
|
@ -184,3 +189,12 @@ endif
|
|||
echo "};};"; \
|
||||
} > "$@.new" && mv -f "$@.new" "$@"
|
||||
@echo "Generated $@"
|
||||
|
||||
%.raw.h: %.raw
|
||||
@$(MKDIR_P) $(@D)
|
||||
@echo "namespace alert_tests{" > $@
|
||||
@echo "static unsigned const char $(*F)[] = {" >> $@
|
||||
@$(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' >> $@
|
||||
@echo "};};" >> $@
|
||||
@echo "Generated $@"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -41,7 +41,8 @@ static CTxIn MineBlock(const CScript& coinbase_scriptPubKey)
|
|||
auto block = PrepareBlock(coinbase_scriptPubKey);
|
||||
|
||||
while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) {
|
||||
assert(++block->nNonce);
|
||||
++block->nNonce;
|
||||
assert(block->nNonce);
|
||||
}
|
||||
|
||||
bool processed{ProcessNewBlock(Params(), block, true, nullptr)};
|
||||
|
|
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,24 @@ 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");
|
||||
// FIXME: adjust heights
|
||||
consensus.BIP65Height = 600000;
|
||||
consensus.BIP66Height = 600000;
|
||||
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,44 +156,43 @@ 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.
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1547942400; // Jan 20, 2019
|
||||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1548288000; // Jan 24, 2019
|
||||
|
||||
// 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;
|
||||
![]() This was before either of our times ... and it can't be changed now without a re-org down to genesis, destroying the entire ecosystem in the process :-P This was before either of our times ... and it can't be changed now without a re-org down to genesis, destroying the entire ecosystem in the process :-P
|
||||
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);
|
||||
|
@ -143,37 +200,31 @@ public:
|
|||
base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x88, 0xB2, 0x1E};
|
||||
base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x88, 0xAD, 0xE4};
|
||||
|
||||
vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main));
|
||||
|
||||
bech32_hrp = "bc";
|
||||
|
||||
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 +238,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");
|
||||
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;
|
||||
// FIXME: adjust heights
|
||||
consensus.BIP65Height = 1000000;
|
||||
consensus.BIP66Height = 1000000;
|
||||
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 +275,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);
|
||||
|
@ -251,17 +312,19 @@ public:
|
|||
|
||||
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 +343,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)
|
||||
consensus.BIP34Height = 1000; // BIP34 is needed for validation_block_tests
|
||||
consensus.BIP34Hash = uint256();
|
||||
// FIXME: update heights and add activation tests
|
||||
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 +379,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;
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
|
||||
#include <assert.h>
|
||||
|
||||
const std::string CBaseChainParams::MAIN = "main";
|
||||
const std::string CBaseChainParams::TESTNET = "test";
|
||||
const std::string CBaseChainParams::MAIN = "lbrycrd";
|
||||
const std::string CBaseChainParams::TESTNET = "lbrycrdtest";
|
||||
const std::string CBaseChainParams::REGTEST = "regtest";
|
||||
|
||||
void SetupChainParamsBaseOptions()
|
||||
|
@ -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
2782
src/claimtrie.cpp
Normal file
2782
src/claimtrie.cpp
Normal file
File diff suppressed because it is too large
Load diff
738
src/claimtrie.h
Normal file
738
src/claimtrie.h
Normal file
|
@ -0,0 +1,738 @@
|
|||
#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);
|
||||
|
||||
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)
|
||||
{}
|
||||
|
||||
CClaimValue(CClaimValue&&) = default;
|
||||
CClaimValue(const CClaimValue&) = default;
|
||||
CClaimValue& operator=(CClaimValue&&) = default;
|
||||
CClaimValue& operator=(const CClaimValue&) = default;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(outPoint);
|
||||
READWRITE(claimId);
|
||||
READWRITE(nAmount);
|
||||
READWRITE(nHeight);
|
||||
READWRITE(nValidAtHeight);
|
||||
}
|
||||
|
||||
bool operator<(const CClaimValue& other) const
|
||||
{
|
||||
if (nEffectiveAmount < other.nEffectiveAmount)
|
||||
return true;
|
||||
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)
|
||||
{}
|
||||
|
||||
CSupportValue(CSupportValue&&) = default;
|
||||
CSupportValue(const CSupportValue&) = default;
|
||||
CSupportValue& operator=(CSupportValue&&) = default;
|
||||
CSupportValue& operator=(const CSupportValue&) = default;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(outPoint);
|
||||
READWRITE(supportedClaimId);
|
||||
READWRITE(nAmount);
|
||||
READWRITE(nHeight);
|
||||
READWRITE(nValidAtHeight);
|
||||
}
|
||||
|
||||
bool operator==(const CSupportValue& other) const
|
||||
{
|
||||
return outPoint == other.outPoint && supportedClaimId == other.supportedClaimId && nAmount == other.nAmount && nHeight == other.nHeight && nValidAtHeight == other.nValidAtHeight;
|
||||
}
|
||||
|
||||
bool operator!=(const CSupportValue& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
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) {}
|
||||
CClaimTrieNode(const CClaimTrieNode&) = default;
|
||||
CClaimTrieNode(CClaimTrieNode&& other)
|
||||
{
|
||||
hash = other.hash;
|
||||
claims = std::move(other.claims);
|
||||
children = std::move(other.children);
|
||||
nHeightOfLastTakeover = other.nHeightOfLastTakeover;
|
||||
}
|
||||
CClaimTrieNode& operator=(const CClaimTrieNode&) = default;
|
||||
CClaimTrieNode& operator=(CClaimTrieNode&& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
hash = other.hash;
|
||||
claims = std::move(other.claims);
|
||||
children = std::move(other.children);
|
||||
nHeightOfLastTakeover = other.nHeightOfLastTakeover;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
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(std::move(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(std::move(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(std::move(claims)), supports(std::move(supports)), nLastTakeoverHeight(nLastTakeoverHeight) {}
|
||||
|
||||
claimsForNameType(const claimsForNameType&) = default;
|
||||
claimsForNameType(claimsForNameType&& other)
|
||||
{
|
||||
claims = std::move(other.claims);
|
||||
supports = std::move(other.supports);
|
||||
nLastTakeoverHeight = other.nLastTakeoverHeight;
|
||||
}
|
||||
claimsForNameType& operator=(const claimsForNameType&) = default;
|
||||
claimsForNameType& operator=(claimsForNameType&& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
claims = std::move(other.claims);
|
||||
supports = std::move(other.supports);
|
||||
nLastTakeoverHeight = other.nLastTakeoverHeight;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
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(std::move(children)), hasValue(hasValue), valHash(valHash)
|
||||
{};
|
||||
CClaimTrieProofNode(const CClaimTrieProofNode&) = default;
|
||||
CClaimTrieProofNode(CClaimTrieProofNode&& other)
|
||||
{
|
||||
hasValue = other.hasValue;
|
||||
valHash = other.valHash;
|
||||
children = std::move(other.children);
|
||||
}
|
||||
CClaimTrieProofNode& operator=(const CClaimTrieProofNode&) = default;
|
||||
CClaimTrieProofNode& operator=(CClaimTrieProofNode&& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
hasValue = other.hasValue;
|
||||
valHash = other.valHash;
|
||||
children = std::move(other.children);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
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(std::move(nodes)), hasValue(hasValue), outPoint(outPoint), nHeightOfLastTakeover(nHeightOfLastTakeover) {}
|
||||
CClaimTrieProof(const CClaimTrieProof&) = default;
|
||||
CClaimTrieProof(CClaimTrieProof&& other)
|
||||
{
|
||||
hasValue = other.hasValue;
|
||||
outPoint = other.outPoint;
|
||||
nodes = std::move(other.nodes);
|
||||
nHeightOfLastTakeover = other.nHeightOfLastTakeover;
|
||||
}
|
||||
CClaimTrieProof& operator=(const CClaimTrieProof&) = default;
|
||||
CClaimTrieProof& operator=(CClaimTrieProof&& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
hasValue = other.hasValue;
|
||||
outPoint = other.outPoint;
|
||||
nodes = std::move(other.nodes);
|
||||
nHeightOfLastTakeover = other.nHeightOfLastTakeover;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
std::vector<CClaimTrieProofNode> nodes;
|
||||
bool hasValue;
|
||||
COutPoint outPoint;
|
||||
int nHeightOfLastTakeover;
|
||||
};
|
||||
|
||||
struct CNodeCallback {
|
||||
struct CRecursionInterruptionException : public std::exception {
|
||||
const bool success;
|
||||
explicit CRecursionInterruptionException(bool success) : success(success) {}
|
||||
};
|
||||
|
||||
virtual ~CNodeCallback()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to be called on every trie node
|
||||
* @param[in] name full name of the node
|
||||
* @param[in] node pointer to node itself
|
||||
*
|
||||
* To breakout early throw an exception.
|
||||
* Throwing CRecursionInterruptionException will allow you to set the return value of iterateTrie.
|
||||
*/
|
||||
virtual void visit(const std::string& name, const CClaimTrieNode* node) = 0;
|
||||
};
|
||||
|
||||
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) const;
|
||||
bool spendSupport(const std::string& name, const COutPoint& outPoint, 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;
|
||||
|
||||
bool iterateTrie(CNodeCallback& callback) 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& 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 recursiveIterateTrie(std::string& name, const CClaimTrieNode* current, CNodeCallback& callback) 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
|
||||
|
|
|
@ -18,7 +18,7 @@ static const unsigned char REJECT_INVALID = 0x10;
|
|||
static const unsigned char REJECT_OBSOLETE = 0x11;
|
||||
static const unsigned char REJECT_DUPLICATE = 0x12;
|
||||
static const unsigned char REJECT_NONSTANDARD = 0x40;
|
||||
// static const unsigned char REJECT_DUST = 0x41; // part of BIP 61
|
||||
static const unsigned char REJECT_DUST = 0x41; // part of BIP 61
|
||||
static const unsigned char REJECT_INSUFFICIENTFEE = 0x42;
|
||||
static const unsigned char REJECT_CHECKPOINT = 0x43;
|
||||
|
||||
|
|
|
@ -225,7 +225,7 @@ public:
|
|||
~CDBWrapper();
|
||||
|
||||
CDBWrapper(const CDBWrapper&) = delete;
|
||||
CDBWrapper& operator=(const CDBWrapper&) = delete;
|
||||
/* CDBWrapper& operator=(const CDBWrapper&) = delete; */
|
||||
|
||||
![]() why remove this line? why remove this line?
|
||||
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]);
|
||||
|
|
|
@ -218,7 +218,7 @@ static bool InitRPCAuthentication()
|
|||
LogPrintf("No rpcpassword set - using random cookie authentication.\n");
|
||||
if (!GenerateAuthCookie(&strRPCUserColonPass)) {
|
||||
uiInterface.ThreadSafeMessageBox(
|
||||
_("Error: A fatal internal error occurred, see debug.log for details"), // Same message as AbortNode
|
||||
_("Error: A fatal internal error occurred generating the cookie, see debug.log for details"), // Same message as AbortNode
|
||||
"", CClientUIInterface::MSG_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -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
|
141
src/miner.cpp
141
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
|
||||
|
@ -323,6 +338,7 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
|
|||
// mempool has a lot of entries.
|
||||
const int64_t MAX_CONSECUTIVE_FAILURES = 1000;
|
||||
int64_t nConsecutiveFailed = 0;
|
||||
std::vector<CTransactionRef> txs;
|
||||
|
||||
while (mi != mempool.mapTx.get<ancestor_score>().end() || !mapModifiedTx.empty())
|
||||
{
|
||||
|
@ -413,6 +429,125 @@ 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);
|
||||
CScript scriptPubKey;
|
||||
if (coin.out.IsNull()) {
|
||||
auto it = std::find_if(txs.begin(), txs.end(), [&txin](const CTransactionRef& tx) {
|
||||
return tx->GetHash() == txin.prevout.hash;
|
||||
});
|
||||
if (it == txs.end() || txin.prevout.n >= (*it)->vout.size())
|
||||
continue;
|
||||
scriptPubKey = (*it)->vout[txin.prevout.n].scriptPubKey;
|
||||
} else {
|
||||
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), 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__);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
txs.emplace_back(MakeTransactionRef(tx));
|
||||
|
||||
// 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;
|
||||
|
@ -3519,14 +3523,19 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
|
|||
vInv.reserve(std::max<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;
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include <util.h>
|
||||
#include <utilstrencodings.h>
|
||||
|
||||
#include "nameclaim.h"
|
||||
|
||||
|
||||
CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
|
||||
{
|
||||
|
@ -115,7 +117,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 +171,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;
|
||||
|
||||
|
|
42
src/pow.cpp
42
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,35 @@
|
|||
|
||||
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;
|
||||
}
|
||||
![]() differs from current master differs from current master
![]() The changes from master are not in ... The changes from master are not in ...
|
||||
|
||||
// Go back by what we want to be 14 days worth of blocks
|
||||
int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1);
|
||||
// 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
|
||||
![]() we just need to pick a fork height for this? (or we could tie it in with the upcoming hash computation fork -- PR #209 ). we just need to pick a fork height for this? (or we could tie it in with the upcoming hash computation fork -- PR #209 ).
|
||||
//
|
||||
/* 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) {
|
||||
|
|
|
@ -15,8 +15,8 @@ static const struct {
|
|||
const int iconColorSaturationReduction;
|
||||
const char *titleAddText;
|
||||
} network_styles[] = {
|
||||
{"main", QAPP_APP_NAME_DEFAULT, 0, 0, ""},
|
||||
{"test", QAPP_APP_NAME_TESTNET, 70, 30, QT_TRANSLATE_NOOP("SplashScreen", "[testnet]")},
|
||||
{"lbrycrd", QAPP_APP_NAME_DEFAULT, 0, 0, ""},
|
||||
{"lbrycrdtest", QAPP_APP_NAME_TESTNET, 70, 30, QT_TRANSLATE_NOOP("SplashScreen", "[testnet]")},
|
||||
{"regtest", QAPP_APP_NAME_REGTEST, 160, 30, "[regtest]"}
|
||||
};
|
||||
static const unsigned network_styles_count = sizeof(network_styles)/sizeof(*network_styles);
|
||||
|
|
|
@ -18,7 +18,7 @@ message Output {
|
|||
required bytes script = 2; // usually one of the standard Script forms
|
||||
}
|
||||
message PaymentDetails {
|
||||
optional string network = 1 [default = "main"]; // "main" or "test"
|
||||
optional string network = 1 [default = "lbrycrd"]; // "lbrycrd" or "lbrycrdtest"
|
||||
repeated Output outputs = 2; // Where payment should be sent
|
||||
required uint64 time = 3; // Timestamp; when payment request created
|
||||
optional uint64 expires = 4; // Timestamp; when this request should be considered invalid
|
||||
|
|
|
@ -228,11 +228,11 @@ void PaymentServer::ipcParseCommandLine(interfaces::Node& node, int argc, char*
|
|||
PaymentRequestPlus request;
|
||||
if (readPaymentRequestFromFile(arg, request))
|
||||
{
|
||||
if (request.getDetails().network() == "main")
|
||||
if (request.getDetails().network() == "lbrycrd")
|
||||
{
|
||||
node.selectParams(CBaseChainParams::MAIN);
|
||||
}
|
||||
else if (request.getDetails().network() == "test")
|
||||
else if (request.getDetails().network() == "lbrycrdtest")
|
||||
{
|
||||
node.selectParams(CBaseChainParams::TESTNET);
|
||||
}
|
||||
|
|
|
@ -202,7 +202,9 @@ void PaymentServerTests::paymentServerTests()
|
|||
for (const std::pair<CScript, CAmount>& sendingTo : sendingTos) {
|
||||
CTxDestination dest;
|
||||
if (ExtractDestination(sendingTo.first, dest))
|
||||
QCOMPARE(PaymentServer::verifyAmount(sendingTo.second), false);
|
||||
// LBRY has a max money defined as 1000x bitcoin's, so we
|
||||
// modify the value here to fail this test properly.
|
||||
QCOMPARE(PaymentServer::verifyAmount(sendingTo.second * 1000), false);
|
||||
}
|
||||
|
||||
delete server;
|
||||
|
|
|
@ -48,7 +48,7 @@ void RPCNestedTests::rpcNestedTests()
|
|||
std::string filtered;
|
||||
auto node = interfaces::MakeNode();
|
||||
RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo()[chain]", &filtered); //simple result filtering with path
|
||||
QVERIFY(result=="main");
|
||||
QVERIFY(result=="lbrycrd");
|
||||
QVERIFY(filtered == "getblockchaininfo()[chain]");
|
||||
|
||||
RPCConsole::RPCExecuteCommandLine(*node, result, "getblock(getbestblockhash())"); //simple 2 level nesting
|
||||
|
@ -75,7 +75,7 @@ void RPCNestedTests::rpcNestedTests()
|
|||
QVERIFY(result == result2);
|
||||
|
||||
RPCConsole::RPCExecuteCommandLine(*node, result, "getblock(getbestblockhash())[tx][0]", &filtered);
|
||||
QVERIFY(result == "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
|
||||
QVERIFY(result == "b8211c82c3d15bcd78bba57005b86fed515149a53a425eb592c07af99fe559cc");
|
||||
QVERIFY(filtered == "getblock(getbestblockhash())[tx][0]");
|
||||
|
||||
RPCConsole::RPCParseCommandLine(nullptr, result, "importprivkey", false, &filtered);
|
||||
|
|
|
@ -254,5 +254,7 @@ void WalletTests::walletTests()
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
TestGUI();
|
||||
//TestGUI();
|
||||
QWARN("Skipping WalletTests with 'minimal' platform set due to Qt bugs. To run AppTests, invoke "
|
||||
"with 'test_bitcoin-qt -platform cocoa' on mac, or else use a linux or windows build.");
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
871
src/rpc/claimtrie.cpp
Normal file
871
src/rpc/claimtrie.cpp
Normal file
|
@ -0,0 +1,871 @@
|
|||
#include <claimtrie.h>
|
||||
#include <coins.h>
|
||||
#include <core_io.h>
|
||||
#include <nameclaim.h>
|
||||
#include <rpc/server.h>
|
||||
#include <shutdown.h>
|
||||
#include <txdb.h>
|
||||
#include <txmempool.h>
|
||||
#include <univalue.h>
|
||||
#include <validation.h>
|
||||
|
||||
#include <boost/thread.hpp>
|
||||
#include <cmath>
|
||||
|
||||
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");
|
||||
|
||||
return pblockIndex;
|
||||
}
|
||||
|
||||
#define MAX_RPC_BLOCK_DECREMENTS 500
|
||||
|
||||
extern CChainState g_chainstate;
|
||||
void RollBackTo(const CBlockIndex* targetIndex, CCoinsViewCache& coinsCache, CClaimTrieCache& trieCache)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
|
||||
const CBlockIndex* activeIndex = chainActive.Tip();
|
||||
|
||||
if (activeIndex->nHeight > (targetIndex->nHeight + MAX_RPC_BLOCK_DECREMENTS))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Block is too deep");
|
||||
|
||||
const size_t currentMemoryUsage = pcoinsTip->DynamicMemoryUsage();
|
||||
|
||||
for (; activeIndex && activeIndex != targetIndex; activeIndex = activeIndex->pprev) {
|
||||
boost::this_thread::interruption_point();
|
||||
|
||||
CBlock block;
|
||||
if (!ReadBlockFromDisk(block, activeIndex, Params().GetConsensus()))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("Failed to read %s", activeIndex->ToString()));
|
||||
|
||||
if (coinsCache.DynamicMemoryUsage() + currentMemoryUsage > nCoinCacheUsage)
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Out of memory, you may want to increase dbcache size");
|
||||
|
||||
if (ShutdownRequested())
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Shutdown requested");
|
||||
|
||||
if (g_chainstate.DisconnectBlock(block, activeIndex, coinsCache, trieCache) != DisconnectResult::DISCONNECT_OK)
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("Failed to disconnect %s", block.ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
static UniValue getclaimsintrie(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() > 1)
|
||||
throw std::runtime_error(
|
||||
"getclaimsintrie\n"
|
||||
"Return all claims in the name trie.\n"
|
||||
"Arguments:\n"
|
||||
"1. \"blockhash\" (string, optional) get claims in the trie\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"
|
||||
"[\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)"));
|
||||
RollBackTo(blockIndex, coinsCache, trieCache);
|
||||
}
|
||||
|
||||
class CClaimsCallback : public CNodeCallback
|
||||
{
|
||||
public:
|
||||
CClaimsCallback(UniValue& ret, const CCoinsViewCache& coinsCache) : nodes(ret), coinsCache(coinsCache)
|
||||
{
|
||||
}
|
||||
|
||||
void visit(const std::string& name, const CClaimTrieNode* node)
|
||||
{
|
||||
if (ShutdownRequested())
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Shutdown requested");
|
||||
|
||||
boost::this_thread::interruption_point();
|
||||
|
||||
if (node->claims.empty())
|
||||
return;
|
||||
|
||||
UniValue claims(UniValue::VARR);
|
||||
for (std::vector<CClaimValue>::const_iterator itClaims = node->claims.begin(); itClaims != node->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", sValue);
|
||||
}
|
||||
claims.push_back(claim);
|
||||
}
|
||||
|
||||
UniValue nodeObj(UniValue::VOBJ);
|
||||
nodeObj.pushKV("name", name);
|
||||
nodeObj.pushKV("claims", claims);
|
||||
nodes.push_back(nodeObj);
|
||||
}
|
||||
|
||||
private:
|
||||
UniValue& nodes;
|
||||
const CCoinsViewCache& coinsCache;
|
||||
};
|
||||
|
||||
UniValue ret(UniValue::VARR);
|
||||
CClaimsCallback claimsCallback(ret, coinsCache);
|
||||
trieCache.iterateTrie(claimsCallback);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static UniValue getclaimtrie(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() > 1)
|
||||
throw std::runtime_error(
|
||||
"getclaimtrie\n"
|
||||
"DEPRECATED. Return the entire claim trie.\n"
|
||||
"Arguments:\n"
|
||||
"1. \"blockhash\" (string, optional) get claim in the trie\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"
|
||||
"[\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"
|
||||
"]\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)"));
|
||||
RollBackTo(blockIndex, coinsCache, trieCache);
|
||||
}
|
||||
|
||||
class CClaimCallback : public CNodeCallback
|
||||
{
|
||||
public:
|
||||
CClaimCallback(UniValue& ret) : nodes(ret)
|
||||
{
|
||||
}
|
||||
|
||||
void visit(const std::string& name, const CClaimTrieNode* node)
|
||||
{
|
||||
if (ShutdownRequested())
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Shutdown requested");
|
||||
|
||||
boost::this_thread::interruption_point();
|
||||
|
||||
UniValue nodeObj(UniValue::VOBJ);
|
||||
nodeObj.pushKV("name", name);
|
||||
nodeObj.pushKV("hash", node->hash.GetHex());
|
||||
CClaimValue claim;
|
||||
if (node->getBestClaim(claim)) {
|
||||
nodeObj.pushKV("txid", claim.outPoint.hash.GetHex());
|
||||
nodeObj.pushKV("n", (int)claim.outPoint.n);
|
||||
nodeObj.pushKV("value", ::ValueFromAmount(claim.nAmount));
|
||||
nodeObj.pushKV("height", claim.nHeight);
|
||||
}
|
||||
nodes.push_back(nodeObj);
|
||||
}
|
||||
|
||||
private:
|
||||
UniValue& nodes;
|
||||
};
|
||||
|
||||
UniValue ret(UniValue::VARR);
|
||||
CClaimCallback claimCallback(ret);
|
||||
trieCache.iterateTrie(claimCallback);
|
||||
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() > 2)
|
||||
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)"));
|
||||
RollBackTo(blockIndex, coinsCache, trieCache);
|
||||
}
|
||||
|
||||
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", 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(const CCoinsViewCache& coinsCache, 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);
|
||||
std::string sValue;
|
||||
if (getValueForClaim(coinsCache, claim.outPoint, sValue))
|
||||
result.pushKV("value", sValue);
|
||||
result.pushKV("nEffectiveAmount", nEffectiveAmount);
|
||||
result.pushKV("supports", supportObjs);
|
||||
return result;
|
||||
}
|
||||
|
||||
UniValue getclaimsforname(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() > 2)
|
||||
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"
|
||||
"2. \"blockhash\" (string, optional) get claims for 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"
|
||||
"{\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"
|
||||
" \"value\" (string) the value of the name, if it exists\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"
|
||||
" \"supports without claims\": [ (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)"));
|
||||
RollBackTo(blockIndex, coinsCache, trieCache);
|
||||
}
|
||||
|
||||
std::string name = request.params[0].get_str();
|
||||
claimsForNameType claimsForName = trieCache.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);
|
||||
UniValue claimObj = claimAndSupportsToJSON(coinsCache, nEffectiveAmount, itClaimsAndSupports);
|
||||
claimObjs.push_back(claimObj);
|
||||
}
|
||||
|
||||
result.pushKV("claims", claimObjs);
|
||||
result.pushKV("supports without claims", 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", 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 = ParseHashV(request.params[0], "txid (parameter 1)");
|
||||
UniValue ret(UniValue::VARR);
|
||||
|
||||
int op;
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
|
||||
CCoinsViewCache view(pcoinsTip.get());
|
||||
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", 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", 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);
|
||||
|
||||
CCoinsViewCache coinsCache(pcoinsTip.get());
|
||||
CClaimTrieCache trieCache(pclaimTrie);
|
||||
|
||||
if (request.params.size() == 2) {
|
||||
CBlockIndex* pblockIndex = BlockHashIndex(ParseHashV(request.params[1], "blockhash (optional parameter 2)"));
|
||||
RollBackTo(pblockIndex, coinsCache, trieCache);
|
||||
}
|
||||
|
||||
CClaimTrieProof proof;
|
||||
std::string name = request.params[0].get_str();
|
||||
if (!trieCache.getProofForName(name, 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, { "blockhash" } },
|
||||
{ "Claimtrie", "getclaimtrie", &getclaimtrie, { "blockhash" } },
|
||||
{ "Claimtrie", "getvalueforname", &getvalueforname, { "name","blockhash" } },
|
||||
{ "Claimtrie", "getclaimsforname", &getclaimsforname, { "name","blockhash" } },
|
||||
{ "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]);
|
||||
}
|
|
@ -126,7 +126,7 @@ UniValue generateBlocks(std::shared_ptr<CReserveScript> coinbaseScript, int nGen
|
|||
LOCK(cs_main);
|
||||
IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);
|
||||
}
|
||||
while (nMaxTries > 0 && pblock->nNonce < nInnerLoopCount && !CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus())) {
|
||||
while (nMaxTries > 0 && pblock->nNonce < nInnerLoopCount && !CheckProofOfWork(pblock->GetPoWHash(), pblock->nBits, Params().GetConsensus())) {
|
||||
++pblock->nNonce;
|
||||
--nMaxTries;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -29,7 +30,7 @@ static const int MAX_OPS_PER_SCRIPT = 201;
|
|||
static const int MAX_PUBKEYS_PER_MULTISIG = 20;
|
||||
|
||||
// Maximum script length in bytes
|
||||
static const int MAX_SCRIPT_SIZE = 10000;
|
||||
static const int MAX_SCRIPT_SIZE = 20005;
|
||||
|
||||
// Maximum number of values on script interpreter stack
|
||||
static const int MAX_STACK_SIZE = 1000;
|
||||
|
@ -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,
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include <script/standard.h>
|
||||
#include <uint256.h>
|
||||
|
||||
#include "nameclaim.h"
|
||||
|
||||
typedef std::vector<unsigned char> valtype;
|
||||
|
||||
MutableTransactionSignatureCreator::MutableTransactionSignatureCreator(const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {}
|
||||
|
@ -100,8 +102,10 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
|
|||
ret.clear();
|
||||
std::vector<unsigned char> sig;
|
||||
|
||||
const CScript& strippedScriptPubKey = StripClaimScriptPrefix(scriptPubKey);
|
||||
|
||||
std::vector<valtype> vSolutions;
|
||||
if (!Solver(scriptPubKey, whichTypeRet, vSolutions))
|
||||
if (!Solver(strippedScriptPubKey, whichTypeRet, vSolutions))
|
||||
return false;
|
||||
|
||||
switch (whichTypeRet)
|
||||
|
|
27
src/test/Checkpoints_tests.cpp
Normal file
27
src/test/Checkpoints_tests.cpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) 2011-2015 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
//
|
||||
// Unit tests for block-chain checkpoints
|
||||
//
|
||||
|
||||
#include "checkpoints.h"
|
||||
|
||||
#include "uint256.h"
|
||||
#include "test/test_bitcoin.h"
|
||||
#include "chainparams.h"
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(Checkpoints_tests, BasicTestingSetup)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(sanity)
|
||||
{
|
||||
//const CCheckpointData& checkpoints = Params(CBaseChainParams::MAIN).Checkpoints();
|
||||
//BOOST_CHECK(Checkpoints::GetTotalBlocksEstimate(checkpoints) >= 134444);
|
||||
}
|
||||
![]() looks like we don't need this file. looks like we don't need this file.
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
|
@ -1,6 +1,6 @@
|
|||
all:
|
||||
$(MAKE) -C .. bitcoin_test
|
||||
$(MAKE) -C .. lbrycrd_test
|
||||
clean:
|
||||
$(MAKE) -C .. bitcoin_test_clean
|
||||
$(MAKE) -C .. lbrycrd_test_clean
|
||||
check:
|
||||
$(MAKE) -C .. bitcoin_test_check
|
||||
$(MAKE) -C .. lbrycrd_test_check
|
||||
|
|
|
@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(GetFeeTest)
|
|||
BOOST_CHECK(CFeeRate(CAmount(26), 789) == CFeeRate(32));
|
||||
BOOST_CHECK(CFeeRate(CAmount(27), 789) == CFeeRate(34));
|
||||
// Maximum size in bytes, should not crash
|
||||
CFeeRate(MAX_MONEY, std::numeric_limits<size_t>::max() >> 1).GetFeePerK();
|
||||
CFeeRate(MAX_MONEY / 1000, std::numeric_limits<size_t>::max() >> 1).GetFeePerK();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(BinaryOperatorTest)
|
||||
|
|
|
@ -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,27 +45,27 @@ BOOST_FIXTURE_TEST_SUITE(blockchain_tests, BasicTestingSetup)
|
|||
|
||||
BOOST_AUTO_TEST_CASE(get_difficulty_for_very_low_target)
|
||||
{
|
||||
TestDifficulty(0x1f111111, 0.000001);
|
||||
TestDifficulty(0x1f00ffff, 1.000000);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
TestDifficulty(0x1df88f6f, 0.004023);
|
||||
TestDifficulty(0x1df88f6f, 263.658369);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(get_difficulty_for_high_target)
|
||||
{
|
||||
TestDifficulty(0x1cf88f6f, 1.029916);
|
||||
TestDifficulty(0x1cf88f6f, 67496.542470);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(get_difficulty_for_very_high_target)
|
||||
{
|
||||
TestDifficulty(0x12345678, 5913134931067755359633408.0);
|
||||
TestDifficulty(0x12345678, 387523210842456415248935026688.000000);
|
||||
}
|
||||
|
||||
// Verify that difficulty is 1.0 for an empty chain.
|
||||
|
|
|
@ -48,7 +48,7 @@ static CBlock BuildBlockTestCase() {
|
|||
bool mutated;
|
||||
block.hashMerkleRoot = BlockMerkleRoot(block, &mutated);
|
||||
assert(!mutated);
|
||||
while (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) ++block.nNonce;
|
||||
while (!CheckProofOfWork(block.GetPoWHash(), block.nBits, Params().GetConsensus())) ++block.nNonce;
|
||||
return block;
|
||||
}
|
||||
|
||||
|
@ -296,7 +296,7 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest)
|
|||
bool mutated;
|
||||
block.hashMerkleRoot = BlockMerkleRoot(block, &mutated);
|
||||
assert(!mutated);
|
||||
while (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) ++block.nNonce;
|
||||
while (!CheckProofOfWork(block.GetPoWHash(), block.nBits, Params().GetConsensus())) ++block.nNonce;
|
||||
|
||||
// Test simple header round-trip with only coinbase
|
||||
{
|
||||
|
|
File diff suppressed because one or more lines are too long
3448
src/test/claimtriebranching_tests.cpp
Normal file
3448
src/test/claimtriebranching_tests.cpp
Normal file
File diff suppressed because it is too large
Load diff
330
src/test/claimtriecache_tests.cpp
Normal file
330
src/test/claimtriecache_tests.cpp
Normal file
|
@ -0,0 +1,330 @@
|
|||
#include "claimtrie.h"
|
||||
#include "nameclaim.h"
|
||||
#include "uint256.h"
|
||||
#include "validation.h"
|
||||
|
||||
#include "test/test_bitcoin.h"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
using namespace std;
|
||||
|
||||
class CClaimTrieCacheTest : public CClaimTrieCache {
|
||||
public:
|
||||
CClaimTrieCacheTest(CClaimTrie* base):
|
||||
CClaimTrieCache(base, false){}
|
||||
|
||||
bool recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent,
|
||||
std::string sPos) const
|
||||
{
|
||||
return CClaimTrieCache::recursiveComputeMerkleHash(tnCurrent, sPos);
|
||||
}
|
||||
|
||||
bool recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, std::string sName, bool* pfNullified) const
|
||||
{
|
||||
return CClaimTrieCache::recursivePruneName(tnCurrent,nPos,sName, pfNullified);
|
||||
}
|
||||
|
||||
bool insertSupportIntoMap(const std::string& name, CSupportValue support, bool fCheckTakeover) const
|
||||
{
|
||||
return CClaimTrieCache::insertSupportIntoMap(name, support, fCheckTakeover);
|
||||
}
|
||||
|
||||
int cacheSize()
|
||||
{
|
||||
return cache.size();
|
||||
}
|
||||
|
||||
nodeCacheType::iterator getCache(std::string key)
|
||||
{
|
||||
return cache.find(key);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CMutableTransaction BuildTransaction(const uint256& prevhash)
|
||||
{
|
||||
CMutableTransaction tx;
|
||||
tx.nVersion = 1;
|
||||
tx.nLockTime = 0;
|
||||
tx.vin.resize(1);
|
||||
tx.vout.resize(1);
|
||||
tx.vin[0].prevout.hash = prevhash;
|
||||
tx.vin[0].prevout.n = 0;
|
||||
tx.vin[0].scriptSig = CScript();
|
||||
tx.vin[0].nSequence = std::numeric_limits<unsigned int>::max();
|
||||
tx.vout[0].scriptPubKey = CScript();
|
||||
tx.vout[0].nValue = 0;
|
||||
|
||||
return tx;
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(claimtriecache_tests, RegTestingSetup)
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(merkle_hash_single_test)
|
||||
{
|
||||
// check empty trie
|
||||
uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
|
||||
CClaimTrieCacheTest cc(pclaimTrie);
|
||||
BOOST_CHECK_EQUAL(one, cc.getMerkleHash());
|
||||
|
||||
// check trie with only root node
|
||||
CClaimTrieNode base_node;
|
||||
cc.recursiveComputeMerkleHash(&base_node, "");
|
||||
BOOST_CHECK_EQUAL(one, cc.getMerkleHash());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
|
||||
{
|
||||
CClaimValue unused;
|
||||
uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
|
||||
uint160 hash160;
|
||||
CMutableTransaction tx1 = BuildTransaction(hash0);
|
||||
COutPoint tx1OutPoint(tx1.GetHash(), 0);
|
||||
CMutableTransaction tx2 = BuildTransaction(tx1.GetHash());
|
||||
COutPoint tx2OutPoint(tx2.GetHash(), 0);
|
||||
CMutableTransaction tx3 = BuildTransaction(tx2.GetHash());
|
||||
COutPoint tx3OutPoint(tx3.GetHash(), 0);
|
||||
CMutableTransaction tx4 = BuildTransaction(tx3.GetHash());
|
||||
COutPoint tx4OutPoint(tx4.GetHash(), 0);
|
||||
CMutableTransaction tx5 = BuildTransaction(tx4.GetHash());
|
||||
COutPoint tx5OutPoint(tx5.GetHash(), 0);
|
||||
CMutableTransaction tx6 = BuildTransaction(tx5.GetHash());
|
||||
COutPoint tx6OutPoint(tx6.GetHash(), 0);
|
||||
|
||||
uint256 hash1;
|
||||
hash1.SetHex("71c7b8d35b9a3d7ad9a1272b68972979bbd18589f1efe6f27b0bf260a6ba78fa");
|
||||
|
||||
uint256 hash2;
|
||||
hash2.SetHex("c4fc0e2ad56562a636a0a237a96a5f250ef53495c2cb5edd531f087a8de83722");
|
||||
|
||||
uint256 hash3;
|
||||
hash3.SetHex("baf52472bd7da19fe1e35116cfb3bd180d8770ffbe3ae9243df1fb58a14b0975");
|
||||
|
||||
uint256 hash4;
|
||||
hash4.SetHex("c73232a755bf015f22eaa611b283ff38100f2a23fb6222e86eca363452ba0c51");
|
||||
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
|
||||
CClaimTrieCache ntState(pclaimTrie, false);
|
||||
ntState.insertClaimIntoTrie(std::string("test"), CClaimValue(tx1OutPoint, hash160, 50, 100, 200));
|
||||
ntState.insertClaimIntoTrie(std::string("test2"), CClaimValue(tx2OutPoint, hash160, 50, 100, 200));
|
||||
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
BOOST_CHECK(!ntState.empty());
|
||||
BOOST_CHECK_EQUAL(ntState.getMerkleHash(), hash1);
|
||||
|
||||
ntState.insertClaimIntoTrie(std::string("test"), CClaimValue(tx3OutPoint, hash160, 50, 101, 201));
|
||||
BOOST_CHECK_EQUAL(ntState.getMerkleHash(), hash1);
|
||||
ntState.insertClaimIntoTrie(std::string("tes"), CClaimValue(tx4OutPoint, hash160, 50, 100, 200));
|
||||
BOOST_CHECK_EQUAL(ntState.getMerkleHash(), hash2);
|
||||
ntState.insertClaimIntoTrie(std::string("testtesttesttest"), CClaimValue(tx5OutPoint, hash160, 50, 100, 200));
|
||||
ntState.removeClaimFromTrie(std::string("testtesttesttest"), tx5OutPoint, unused);
|
||||
BOOST_CHECK_EQUAL(ntState.getMerkleHash(), hash2);
|
||||
ntState.flush();
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash2);
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency());
|
||||
|
||||
CClaimTrieCache ntState1(pclaimTrie, false);
|
||||
ntState1.removeClaimFromTrie(std::string("test"), tx1OutPoint, unused);
|
||||
ntState1.removeClaimFromTrie(std::string("test2"), tx2OutPoint, unused);
|
||||
ntState1.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused);
|
||||
ntState1.removeClaimFromTrie(std::string("tes"), tx4OutPoint, unused);
|
||||
|
||||
BOOST_CHECK_EQUAL(ntState1.getMerkleHash(), hash0);
|
||||
|
||||
CClaimTrieCache ntState2(pclaimTrie, false);
|
||||
ntState2.insertClaimIntoTrie(std::string("abab"), CClaimValue(tx6OutPoint, hash160, 50, 100, 200));
|
||||
ntState2.removeClaimFromTrie(std::string("test"), tx1OutPoint, unused);
|
||||
|
||||
BOOST_CHECK_EQUAL(ntState2.getMerkleHash(), hash3);
|
||||
|
||||
ntState2.flush();
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash3);
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency());
|
||||
|
||||
CClaimTrieCache ntState3(pclaimTrie, false);
|
||||
ntState3.insertClaimIntoTrie(std::string("test"), CClaimValue(tx1OutPoint, hash160, 50, 100, 200));
|
||||
BOOST_CHECK_EQUAL(ntState3.getMerkleHash(), hash4);
|
||||
ntState3.flush();
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash4);
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency());
|
||||
|
||||
CClaimTrieCache ntState4(pclaimTrie, false);
|
||||
ntState4.removeClaimFromTrie(std::string("abab"), tx6OutPoint, unused);
|
||||
BOOST_CHECK_EQUAL(ntState4.getMerkleHash(), hash2);
|
||||
ntState4.flush();
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash2);
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency());
|
||||
|
||||
CClaimTrieCache ntState5(pclaimTrie, false);
|
||||
ntState5.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused);
|
||||
|
||||
BOOST_CHECK_EQUAL(ntState5.getMerkleHash(), hash2);
|
||||
ntState5.flush();
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash2);
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency());
|
||||
|
||||
CClaimTrieCache ntState6(pclaimTrie, false);
|
||||
ntState6.insertClaimIntoTrie(std::string("test"), CClaimValue(tx3OutPoint, hash160, 50, 101, 201));
|
||||
|
||||
BOOST_CHECK_EQUAL(ntState6.getMerkleHash(), hash2);
|
||||
ntState6.flush();
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash2);
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency());
|
||||
|
||||
CClaimTrieCache ntState7(pclaimTrie, false);
|
||||
ntState7.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused);
|
||||
ntState7.removeClaimFromTrie(std::string("test"), tx1OutPoint, unused);
|
||||
ntState7.removeClaimFromTrie(std::string("tes"), tx4OutPoint, unused);
|
||||
ntState7.removeClaimFromTrie(std::string("test2"), tx2OutPoint, unused);
|
||||
|
||||
BOOST_CHECK_EQUAL(ntState7.getMerkleHash(), hash0);
|
||||
ntState7.flush();
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
BOOST_CHECK_EQUAL(pclaimTrie->getMerkleHash(), hash0);
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(basic_insertion_info_test)
|
||||
{
|
||||
// test basic claim insertions and that get methods retreives information properly
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
CClaimTrieCacheTest ctc(pclaimTrie);
|
||||
|
||||
// create and insert claim
|
||||
CClaimValue unused;
|
||||
uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
|
||||
CMutableTransaction tx1 = BuildTransaction(hash0);
|
||||
uint160 claimId = ClaimIdHash(tx1.GetHash(), 0);
|
||||
COutPoint claimOutPoint(tx1.GetHash(), 0);
|
||||
CAmount amount(10);
|
||||
int height = 0;
|
||||
int validHeight = 0;
|
||||
CClaimValue claimVal(claimOutPoint, claimId, amount, height, validHeight);
|
||||
ctc.insertClaimIntoTrie("test", claimVal);
|
||||
|
||||
// try getClaimsForName, getEffectiveAmountForClaim, getInfoForName
|
||||
claimsForNameType res = ctc.getClaimsForName("test");
|
||||
BOOST_CHECK_EQUAL(res.claims.size(), 1);
|
||||
BOOST_CHECK_EQUAL(res.claims[0], claimVal);
|
||||
|
||||
BOOST_CHECK_EQUAL(10, ctc.getEffectiveAmountForClaim("test", claimId));
|
||||
|
||||
CClaimValue claim;
|
||||
BOOST_CHECK(ctc.getInfoForName("test", claim));
|
||||
BOOST_CHECK_EQUAL(claim, claimVal);
|
||||
|
||||
// insert a support
|
||||
CAmount supportAmount(10);
|
||||
uint256 hash1(uint256S("0000000000000000000000000000000000000000000000000000000000000002"));
|
||||
CMutableTransaction tx2 = BuildTransaction(hash1);
|
||||
COutPoint supportOutPoint(tx2.GetHash(), 0);
|
||||
|
||||
CSupportValue support(supportOutPoint, claimId, supportAmount, height, validHeight);
|
||||
ctc.insertSupportIntoMap("test", support, false);
|
||||
|
||||
// try getEffectiveAmount
|
||||
BOOST_CHECK_EQUAL(20, ctc.getEffectiveAmountForClaim("test", claimId));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(recursive_prune_test)
|
||||
{
|
||||
CClaimTrieCacheTest cc(pclaimTrie);
|
||||
BOOST_CHECK_EQUAL(0, cc.cacheSize());
|
||||
|
||||
COutPoint outpoint;
|
||||
uint160 claimId;
|
||||
CAmount amount(20);
|
||||
int height = 0;
|
||||
int validAtHeight = 0;
|
||||
CClaimValue test_claim(outpoint, claimId, amount, height, validAtHeight);
|
||||
|
||||
CClaimTrieNode base_node;
|
||||
// base node has a claim, so it should not be pruned
|
||||
base_node.insertClaim(test_claim);
|
||||
|
||||
// node 1 has a claim so it should not be pruned
|
||||
CClaimTrieNode node_1;
|
||||
const char c = 't';
|
||||
base_node.children[c] = &node_1;
|
||||
node_1.insertClaim(test_claim);
|
||||
// set this just to make sure we get the right CClaimTrieNode back
|
||||
node_1.nHeightOfLastTakeover = 10;
|
||||
|
||||
//node 2 does not have a claim so it should be pruned
|
||||
// thus we should find pruned node 1 in cache
|
||||
CClaimTrieNode node_2;
|
||||
const char c_2 = 'e';
|
||||
node_1.children[c_2] = &node_2;
|
||||
|
||||
cc.recursivePruneName(&base_node, 0, std::string("te"), NULL);
|
||||
BOOST_CHECK_EQUAL(1, cc.cacheSize());
|
||||
nodeCacheType::iterator it = cc.getCache(std::string("t"));
|
||||
BOOST_CHECK_EQUAL(10, it->second->nHeightOfLastTakeover);
|
||||
BOOST_CHECK_EQUAL(1, it->second->claims.size());
|
||||
BOOST_CHECK_EQUAL(0, it->second->children.size());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(iteratetrie_test)
|
||||
{
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
CClaimTrieCacheTest ctc(pclaimTrie);
|
||||
|
||||
uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
|
||||
CMutableTransaction tx1 = BuildTransaction(hash0);
|
||||
|
||||
const uint256 txhash = tx1.GetHash();
|
||||
CClaimValue claimVal(COutPoint(txhash, 0), ClaimIdHash(txhash, 0), CAmount(10), 0, 0);
|
||||
ctc.insertClaimIntoTrie("test", claimVal);
|
||||
|
||||
|
||||
int count = 0;
|
||||
|
||||
struct TestCallBack : public CNodeCallback {
|
||||
TestCallBack(int& count) : count(count)
|
||||
{
|
||||
}
|
||||
|
||||
void visit(const std::string& name, const CClaimTrieNode* node)
|
||||
{
|
||||
count++;
|
||||
if (name == "test") {
|
||||
BOOST_CHECK_EQUAL(node->claims.size(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
int& count;
|
||||
} testCallback(count);
|
||||
|
||||
BOOST_CHECK(ctc.iterateTrie(testCallback));
|
||||
BOOST_CHECK_EQUAL(count, 5);
|
||||
|
||||
count = 3;
|
||||
|
||||
struct TestCallBack2 : public CNodeCallback {
|
||||
TestCallBack2(int& count) : count(count)
|
||||
{
|
||||
}
|
||||
|
||||
void visit(const std::string& name, const CClaimTrieNode* node)
|
||||
{
|
||||
if (--count <= 0)
|
||||
throw CRecursionInterruptionException(false);
|
||||
}
|
||||
|
||||
int& count;
|
||||
} testCallback2(count);
|
||||
|
||||
BOOST_CHECK(!ctc.iterateTrie(testCallback2));
|
||||
BOOST_CHECK_EQUAL(count, 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out);
|
||||
int ApplyTxInUndo(unsigned int index, CTxUndo& txUndo, CCoinsViewCache& view, CClaimTrieCache& trieCache, const COutPoint& out);
|
||||
void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txundo, int nHeight);
|
||||
|
||||
namespace
|
||||
|
@ -95,7 +95,7 @@ public:
|
|||
|
||||
} // namespace
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(coins_tests, BasicTestingSetup)
|
||||
BOOST_FIXTURE_TEST_SUITE(coins_tests, TestingSetup)
|
||||
|
||||
static const unsigned int NUM_SIMULATION_ITERATIONS = 40000;
|
||||
|
||||
|
@ -407,7 +407,10 @@ 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);
|
||||
// return coin
|
||||
undo.vprevout[0] = coin;
|
||||
}
|
||||
// Store as a candidate for reconnection
|
||||
disconnected_coins.insert(utxod->first);
|
||||
|
@ -706,7 +709,7 @@ BOOST_AUTO_TEST_CASE(ccoins_spend)
|
|||
CheckSpendCoins(VALUE1, VALUE2, PRUNED, DIRTY , DIRTY );
|
||||
CheckSpendCoins(VALUE1, VALUE2, ABSENT, DIRTY|FRESH, NO_ENTRY );
|
||||
}
|
||||
|
||||
/*
|
||||
static void CheckAddCoinBase(CAmount base_value, CAmount cache_value, CAmount modify_value, CAmount expected_value, char cache_flags, char expected_flags, bool coinbase)
|
||||
{
|
||||
SingleEntryCacheTest test(base_value, cache_value, cache_flags);
|
||||
|
@ -742,14 +745,14 @@ static void CheckAddCoin(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
|
||||
*/
|
||||
// * 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);
|
||||
|
@ -768,7 +771,7 @@ BOOST_AUTO_TEST_CASE(ccoins_add)
|
|||
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)
|
||||
{
|
||||
|
|
452
src/test/data/base58_keys_valid.json
Normal file
452
src/test/data/base58_keys_valid.json
Normal file
|
@ -0,0 +1,452 @@
|
|||
[
|
||||
[
|
||||
"bMzeGER3krZ2zX75uxLoLDA5tLvUX9w4QP",
|
||||
"65a16059864a2fdbc7c99a4723a8395bc6f188eb",
|
||||
{
|
||||
"addrType": "pubkey",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"rGtwTfEisPQ7k8KNggmT4kq2vHpbEV6evU",
|
||||
"74f209f6ea907e2ea48f74fae05782ae8a665257",
|
||||
{
|
||||
"addrType": "script",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs",
|
||||
"53c0307d6851aa0ce7825ba883c6bd9ad242b486",
|
||||
{
|
||||
"addrType": "pubkey",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br",
|
||||
"6349a418fc4578d10a372b54b45c280cc8c4382f",
|
||||
{
|
||||
"addrType": "script",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"yEbizayQwA4VxYFayRRb5rjkYs8XVxaZSKD25ggAQ9rk8onJSj",
|
||||
"eddbdc1168f1daeadbd3e44c1e3f8f5a284c2029f78ad26af98583a499de5b19",
|
||||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"5C7R8dNCgw9bSq5umaZzZHBMs3N8vHZueMcueLZG1kWQRW1Mz8v6",
|
||||
"55c9bccb9ed68446d1b75273bbce89d7fe013a8acd1625514420fb2aca1a21c4",
|
||||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"9213qJab2HNEpMpYNBa7wHGFKKbkDn24jpANDs2huN3yi4J11ko",
|
||||
"36cb93b9ab1bdabf7fb9f2c04f1b9cc879933530ae7842398eef5a63a56800c2",
|
||||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"cTpB4YiyKiBcPxnefsDpbnDxFDffjqJob8wGCEDXxgQ7zQoMXJdH",
|
||||
"b9f4892c9e8282028fea1d2667c4dc5213564d41fc5783896a0d843fc15089f3",
|
||||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"bNgLNoE5U1ZCPsK61bxpmwgksFEdSLDin3",
|
||||
"6d23156cbbdcc82a5a47eee4c2c7c583c18b6bf4",
|
||||
{
|
||||
"addrType": "pubkey",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"rVH7jQLU11weX6tf9YRoKknnAinEWYU5ev",
|
||||
"fcc5460dd6e2487c7d75b1963625da0e8f4c5975",
|
||||
{
|
||||
"addrType": "script",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"n3ZddxzLvAY9o7184TB4c6FJasAybsw4HZ",
|
||||
"f1d470f9b02370fdec2e6b708b08ac431bf7a5f7",
|
||||
{
|
||||
"addrType": "pubkey",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"2NBFNJTktNa7GZusGbDbGKRZTxdK9VVez3n",
|
||||
"c579342c2c4c9220205e2cdc285617040c924a0a",
|
||||
{
|
||||
"addrType": "script",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"xfhRLgkcKPwnwXoT3kbLZ7MEJrZ9cM6WoX6XSjCCkn3YhuSnEY",
|
||||
"a326b95ebae30164217d7a7f57d72ab2b54e3be64928a19da0210b9568d4015e",
|
||||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"5DSogeVo6xJ8dTuYeJkb6LUij1NhkMvQcXgJ3o18PzxjnpvtS5sN",
|
||||
"7d998b45c219a1e38e99e7cbd312ef67f77a455a9b50c730c27f02c6f730dfb4",
|
||||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"93DVKyFYwSN6wEo3E2fCrFPUp17FtrtNi2Lf7n4G3garFb16CRj",
|
||||
"d6bca256b5abc5602ec2e1c121a08b0da2556587430bcf7e1898af2224885203",
|
||||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"cTDVKtMGVYWTHCb1AFjmVbEbWjvKpKqKgMaR3QJxToMSQAhmCeTN",
|
||||
"a81ca4e8f90181ec4b61b6a7eb998af17b2cb04de8a03b504b9e34c4c61db7d9",
|
||||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"bPos8xMCabs9xJTMoe5MKrusd7GbNLFpt7",
|
||||
"7987ccaa53d02c8873487ef919677cd3db7a6912",
|
||||
{
|
||||
"addrType": "pubkey",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"rFKxAHUFLugUERmNS2DXXKhXSfPtXqN8b6",
|
||||
"63bcc565f9e68ee0189dd5cc67f1b0e5f02f45cb",
|
||||
{
|
||||
"addrType": "script",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"n3LnJXCqbPjghuVs8ph9CYsAe4Sh4j97wk",
|
||||
"ef66444b5b17f14e8fae6e7e19b045a78c54fd79",
|
||||
{
|
||||
"addrType": "pubkey",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"2NB72XtkjpnATMggui83aEtPawyyKvnbX2o",
|
||||
"c3e55fceceaa4391ed2a9677f4a4d34eacd021a0",
|
||||
{
|
||||
"addrType": "script",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"yBjry3Bfxk481Sha1JHLTNx45oUCJUsGX6kYWMjTHfZDwJMQAY",
|
||||
"e75d936d56377f432f404aabb406601f892fd49da90eb6ac558a733c93b47252",
|
||||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"5DbupTR2UQkniPSNs8Xf9KMcsDCeggRYnN7kk1g9EdmNN4JEp3zv",
|
||||
"8248bd0375f2f75d7e274ae544fb920f51784480866b102384190b1addfbaa5c",
|
||||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"927CnUkUbasYtDwYwVn2j8GdTuACNnKkjZ1rpZd2yBB1CLcnXpo",
|
||||
"44c4f6a096eac5238291a94cc24c01e3b19b8d8cef72874a079e00a242237a52",
|
||||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"cUcfCMRjiQf85YMzzQEk9d1s5A4K7xL5SmBCLrezqXFuTVefyhY7",
|
||||
"d1de707020a9059d6d3abaf85e17967c6555151143db13dbb06db78df0f15c69",
|
||||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"bUa1khFbViXUiSroY5CZGX9Nau1HktvTNW",
|
||||
"adc1cc2081a27206fae25792f28bbc55b831549d",
|
||||
{
|
||||
"addrType": "pubkey",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"r8UTLCaz9r6MgiPJ8qUPLucHdAWC7EDDBJ",
|
||||
"188f91a931947eddd7432d6e614387e32b244709",
|
||||
{
|
||||
"addrType": "script",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"mhaMcBxNh5cqXm4aTQ6EcVbKtfL6LGyK2H",
|
||||
"1694f5bc1a7295b600f40018a618a6ea48eeb498",
|
||||
{
|
||||
"addrType": "pubkey",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"2MxgPqX1iThW3oZVk9KoFcE5M4JpiETssVN",
|
||||
"3b9b3fd7a50d4f08d1a5b0f62f644fa7115ae2f3",
|
||||
{
|
||||
"addrType": "script",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"wVqT5kRiefWaeZyaMwFfg2jc4bKGySd2EMRD6uWJXqxi96CuDZ",
|
||||
"091035445ef105fa1bb125eccfb1882f3fe69592265956ade751fd095033d8d0",
|
||||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"5EyPNdKgzRRpCzikAJSrM5Ppbigd37BSCPmayiBHZk3XT8RsfbhV",
|
||||
"ab2b4bcdfc91d34dee0ae2a8c6b6668dadaeb3a88b9859743156f462325187af",
|
||||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"92xFEve1Z9N8Z641KQQS7ByCSb8kGjsDzw6fAmjHN1LZGKQXyMq",
|
||||
"b4204389cef18bbe2b353623cbf93e8678fbc92a475b664ae98ed594e6cf0856",
|
||||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"cVM65tdYu1YK37tNoAyGoJTR13VBYFva1vg9FLuPAsJijGvG6NEA",
|
||||
"e7b230133f1b5489843260236b06edca25f66adb1be455fbd38d4010d48faeef",
|
||||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"bWfdCQpqF4ENPTSwVwtoHUyAJdbRcvo1w1",
|
||||
"c4c1b72491ede1eedaca00618407ee0b772cad0d",
|
||||
{
|
||||
"addrType": "pubkey",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"rUka8NCmdY9Gyy2eNGUEhLUd1CbVSzFEqA",
|
||||
"f6fe69bcb548a829cce4c57bf6fff8af3a5981f9",
|
||||
{
|
||||
"addrType": "script",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"mizXiucXRCsEriQCHUkCqef9ph9qtPbZZ6",
|
||||
"261f83568a098a8638844bd7aeca039d5f2352c0",
|
||||
{
|
||||
"addrType": "pubkey",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"2NEWDzHWwY5ZZp8CQWbB7ouNMLqCia6YRda",
|
||||
"e930e1834a4d234702773951d627cce82fbb5d2e",
|
||||
{
|
||||
"addrType": "script",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"y2Kag6A9fz5PRsuA5vKT5gd1XqxJRxvn6eKXGdovHkbCBsiKmW",
|
||||
"d1fab7ab7385ad26872237f1eb9789aa25cc986bacc695e07ac571d6cdac8bc0",
|
||||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"5FACny8EWv5yhLMsjy7iZ4cqQEvXvb3bQe5h1W7Z1ySYqWKWLfxV",
|
||||
"b0bbede33ef254e8376aceb1510253fc3550efd0fcf84dcd0c9998b288f166b3",
|
||||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"91cTVUcgydqyZLgaANpf1fvL55FH53QMm4BsnCADVNYuWuqdVys",
|
||||
"037f4192c630f399d9271e26c575269b1d15be553ea1a7217f0cb8513cef41cb",
|
||||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"cQspfSzsgLeiJGB2u8vrAiWpCU4MxUT6JseWo2SjXy4Qbzn2fwDw",
|
||||
"6251e205e8ad508bab5596bee086ef16cd4b239e0cc0c5d7c4e6035441e7d5de",
|
||||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"bMMtHB8oxu1tVswSbUqbaMexu5Nzkzo7s4",
|
||||
"5eadaf9bb7121f0f192561a5a62f5e5f54210292",
|
||||
{
|
||||
"addrType": "pubkey",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"rBzPJ8nm3Ay1Jj6XsPTNZLgaFdRkFcYQhW",
|
||||
"3f210e7277c899c3a155cc1c90f4106cbddeec6e",
|
||||
{
|
||||
"addrType": "script",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"myoqcgYiehufrsnnkqdqbp69dddVDMopJu",
|
||||
"c8a3c2a09a298592c3e180f02487cd91ba3400b5",
|
||||
{
|
||||
"addrType": "pubkey",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"2N7FuwuUuoTBrDFdrAZ9KxBmtqMLxce9i1C",
|
||||
"99b31df7c9068d1481b596578ddbb4d3bd90baeb",
|
||||
{
|
||||
"addrType": "script",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"xwfM3hAfqnt5HgUwdHujEGJAPRnJV94BmFGekrQQ1U869kQ814",
|
||||
"c7666842503db6dc6ea061f092cfb9c388448629a6fe868d068c42a488b478ae",
|
||||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"59W692dz6aGKaBKkCoQJp4Bryh76LxdHcq4qSMvrMPiapzHJ8xU3",
|
||||
"07f0803fc5399e773555ab1e8939907e9badacc17ca129e67a2f5f2ff84351dd",
|
||||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"93N87D6uxSBzwXvpokpzg8FFmfQPmvX4xHoWQe3pLdYpbiwT5YV",
|
||||
"ea577acfb5d1d14d3b7b195c321566f12f87d2b77ea3a53f68df7ebf8604a801",
|
||||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"cMxXusSihaX58wpJ3tNuuUcZEQGt6DKJ1wEpxys88FFaQCYjku9h",
|
||||
"0b3b34f0958d8a268193a9814da92c3e8b58b4a4378a542863e34ac289cd830c",
|
||||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"isTestnet": true
|
||||
}
|
||||
],
|
||||
[
|
||||
"bFYHQxgSE8F6RpgyYaccyVA2wWS24vAK55",
|
||||
"1ed467017f043e91ed4c44b4e8dd674db211c4e6",
|
||||
{
|
||||
"addrType": "pubkey",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": false
|
||||
}
|
||||
],
|
||||
[
|
||||
"rEssUrQr97hhxKohQFc6tiAfLpXWTVyZcA",
|
||||
"5ece0cadddc415b1980f001785947120acdb36fc",
|
||||
{
|
||||
"addrType": "script",
|
||||
"isPrivkey": false,
|
||||
"isTestnet": false
|
||||
}
|
||||
]
|
||||
]
|
|
@ -4,7 +4,7 @@
|
|||
"76a91465a16059864a2fdbc7c99a4723a8395bc6f188eb88ac",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -12,7 +12,7 @@
|
|||
"a91474f209f6ea907e2ea48f74fae05782ae8a66525787",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -20,7 +20,7 @@
|
|||
"76a91453c0307d6851aa0ce7825ba883c6bd9ad242b48688ac",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -36,7 +36,7 @@
|
|||
"a9146349a418fc4578d10a372b54b45c280cc8c4382f87",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -45,7 +45,7 @@
|
|||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -54,7 +54,7 @@
|
|||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -63,7 +63,7 @@
|
|||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -81,7 +81,7 @@
|
|||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -98,7 +98,7 @@
|
|||
"76a9146d23156cbbdcc82a5a47eee4c2c7c583c18b6bf488ac",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -106,7 +106,7 @@
|
|||
"a914fcc5460dd6e2487c7d75b1963625da0e8f4c597587",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -114,7 +114,7 @@
|
|||
"76a914f1d470f9b02370fdec2e6b708b08ac431bf7a5f788ac",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -122,7 +122,7 @@
|
|||
"a914c579342c2c4c9220205e2cdc285617040c924a0a87",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -131,7 +131,7 @@
|
|||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -140,7 +140,7 @@
|
|||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -149,7 +149,7 @@
|
|||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -158,7 +158,7 @@
|
|||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -166,7 +166,7 @@
|
|||
"76a9147987ccaa53d02c8873487ef919677cd3db7a691288ac",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -174,7 +174,7 @@
|
|||
"a91463bcc565f9e68ee0189dd5cc67f1b0e5f02f45cb87",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -182,7 +182,7 @@
|
|||
"76a914ef66444b5b17f14e8fae6e7e19b045a78c54fd7988ac",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -190,7 +190,7 @@
|
|||
"a914c3e55fceceaa4391ed2a9677f4a4d34eacd021a087",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -199,7 +199,7 @@
|
|||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -208,7 +208,7 @@
|
|||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -217,7 +217,7 @@
|
|||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -226,7 +226,7 @@
|
|||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -234,7 +234,7 @@
|
|||
"76a914adc1cc2081a27206fae25792f28bbc55b831549d88ac",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -242,7 +242,7 @@
|
|||
"a914188f91a931947eddd7432d6e614387e32b24470987",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -250,7 +250,7 @@
|
|||
"76a9141694f5bc1a7295b600f40018a618a6ea48eeb49888ac",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -258,7 +258,7 @@
|
|||
"a9143b9b3fd7a50d4f08d1a5b0f62f644fa7115ae2f387",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -267,7 +267,7 @@
|
|||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -276,7 +276,7 @@
|
|||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -285,7 +285,7 @@
|
|||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -303,7 +303,7 @@
|
|||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -311,7 +311,7 @@
|
|||
"76a914c4c1b72491ede1eedaca00618407ee0b772cad0d88ac",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -319,7 +319,7 @@
|
|||
"a914f6fe69bcb548a829cce4c57bf6fff8af3a5981f987",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -327,7 +327,7 @@
|
|||
"76a914261f83568a098a8638844bd7aeca039d5f2352c088ac",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -335,7 +335,7 @@
|
|||
"a914e930e1834a4d234702773951d627cce82fbb5d2e87",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -344,7 +344,7 @@
|
|||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -353,7 +353,7 @@
|
|||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -362,7 +362,7 @@
|
|||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -371,7 +371,7 @@
|
|||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -379,7 +379,7 @@
|
|||
"76a9145eadaf9bb7121f0f192561a5a62f5e5f5421029288ac",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -387,7 +387,7 @@
|
|||
"a9143f210e7277c899c3a155cc1c90f4106cbddeec6e87",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -395,7 +395,7 @@
|
|||
"76a914c8a3c2a09a298592c3e180f02487cd91ba3400b588ac",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -403,7 +403,7 @@
|
|||
"a91499b31df7c9068d1481b596578ddbb4d3bd90baeb87",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -412,7 +412,7 @@
|
|||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -421,7 +421,7 @@
|
|||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -430,7 +430,7 @@
|
|||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -439,7 +439,7 @@
|
|||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"chain": "test"
|
||||
"chain": "lbrycrdtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -447,7 +447,7 @@
|
|||
"76a9141ed467017f043e91ed4c44b4e8dd674db211c4e688ac",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -455,7 +455,7 @@
|
|||
"a9145ece0cadddc415b1980f001785947120acdb36fc87",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "main"
|
||||
"chain": "lbrycrd"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -463,7 +463,7 @@
|
|||
"0014751e76e8199196d454941c45d1b3a323f1433bd6",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "main",
|
||||
"chain": "lbrycrd",
|
||||
"tryCaseFlip": true
|
||||
}
|
||||
],
|
||||
|
@ -481,7 +481,7 @@
|
|||
"00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "test",
|
||||
"chain": "lbrycrdtest",
|
||||
"tryCaseFlip": true
|
||||
}
|
||||
],
|
||||
|
@ -490,7 +490,7 @@
|
|||
"5128751e76e8199196d454941c45d1b3a323f1433bd6751e76e8199196d454941c45d1b3a323f1433bd6",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "main",
|
||||
"chain": "lbrycrd",
|
||||
"tryCaseFlip": true
|
||||
}
|
||||
],
|
||||
|
@ -499,7 +499,7 @@
|
|||
"6002751e",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "main",
|
||||
"chain": "lbrycrd",
|
||||
"tryCaseFlip": true
|
||||
}
|
||||
],
|
||||
|
@ -508,7 +508,7 @@
|
|||
"5210751e76e8199196d454941c45d1b3a323",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "main",
|
||||
"chain": "lbrycrd",
|
||||
"tryCaseFlip": true
|
||||
}
|
||||
],
|
||||
|
@ -517,7 +517,7 @@
|
|||
"0020000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "test",
|
||||
"chain": "lbrycrdtest",
|
||||
"tryCaseFlip": true
|
||||
}
|
||||
],
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -281,10 +281,6 @@
|
|||
["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
|
||||
"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151540b00000000000001510002483045022100a3cec69b52cba2d2de623eeef89e0ba1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
|
||||
|
||||
["Witness with a push of 521 bytes"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0x33198a9bfef674ebddb9ffaa52928017b8472791e54c609cb95f278ac6b1e349", 1000]],
|
||||
"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff010000000000000000015102fd0902000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002755100000000", "P2SH,WITNESS"],
|
||||
|
||||
["Witness with unknown version which push false on the stack should be invalid (even without DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)"],
|
||||
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x02 0x0000", 2000]],
|
||||
"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff010000000000000000015101010100000000", "P2SH,WITNESS"],
|
||||
|
|
|
@ -146,7 +146,14 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
|
|||
BOOST_CHECK(node->fDisconnect == false);
|
||||
}
|
||||
|
||||
SetMockTime(GetTime() + 3*consensusParams.nPowTargetSpacing + 1);
|
||||
// STALE_CHECK_INTERVAL is used in PeerLogicValidation::CheckForStaleTipAndEvictPeers
|
||||
// as minimal time to check tip stale i.e. 10 minutes
|
||||
// we use maximum value of STALE_CHECK_INTERVAL and nPowTargetSpacing
|
||||
// NOTE: STALE_CHECK_INTERVAL is static that why we use raw value 10 * 60, sync may need in future
|
||||
|
||||
auto time = std::max(long(10) * 60, 3 * consensusParams.nPowTargetSpacing);
|
||||
|
||||
SetMockTime(GetTime() + time + 1);
|
||||
|
||||
// Now tip should definitely be stale, and we should look for an extra
|
||||
// outbound peer
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -17,15 +17,15 @@ BOOST_FIXTURE_TEST_SUITE(merkleblock_tests, BasicTestingSetup)
|
|||
*/
|
||||
BOOST_AUTO_TEST_CASE(merkleblock_construct_from_txids_found)
|
||||
{
|
||||
CBlock block = getBlock13b8a();
|
||||
CBlock block = getTestBlock();
|
||||
|
||||
std::set<uint256> txids;
|
||||
|
||||
// Last txn in block.
|
||||
uint256 txhash1 = uint256S("0x74d681e0e03bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20");
|
||||
uint256 txhash1 = uint256S("0x9ce94190112f5b6763fb73a813c7bc2b63f1279f4345d2815abe3d7b2b0052cf");
|
||||
|
||||
// Second txn in block.
|
||||
uint256 txhash2 = uint256S("0xf9fc751cb7dc372406a9f8d738d5e6f8f63bab71986a39cf36ee70ee17036d07");
|
||||
uint256 txhash2 = uint256S("0x284a6aee6143497ebfede92f4877945714c0a041d79e49e7664fc6299e55d61e");
|
||||
|
||||
txids.insert(txhash1);
|
||||
txids.insert(txhash2);
|
||||
|
@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(merkleblock_construct_from_txids_found)
|
|||
BOOST_CHECK_EQUAL(vIndex[0], 1U);
|
||||
|
||||
BOOST_CHECK_EQUAL(vMatched[1].ToString(), txhash1.ToString());
|
||||
BOOST_CHECK_EQUAL(vIndex[1], 8U);
|
||||
BOOST_CHECK_EQUAL(vIndex[1], 3U);
|
||||
}
|
||||
|
||||
|
||||
|
@ -58,7 +58,7 @@ BOOST_AUTO_TEST_CASE(merkleblock_construct_from_txids_found)
|
|||
*/
|
||||
BOOST_AUTO_TEST_CASE(merkleblock_construct_from_txids_not_found)
|
||||
{
|
||||
CBlock block = getBlock13b8a();
|
||||
CBlock block = getTestBlock();
|
||||
|
||||
std::set<uint256> txids2;
|
||||
txids2.insert(uint256S("0xc0ffee00003bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20"));
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <validation.h>
|
||||
#include <miner.h>
|
||||
#include <policy/policy.h>
|
||||
#include <pow.h>
|
||||
#include <pubkey.h>
|
||||
#include <script/standard.h>
|
||||
#include <txmempool.h>
|
||||
|
@ -47,39 +48,30 @@ static BlockAssembler AssemblerForTest(const CChainParams& params) {
|
|||
return BlockAssembler(params, options);
|
||||
}
|
||||
|
||||
static
|
||||
struct {
|
||||
unsigned char extranonce;
|
||||
unsigned int nonce;
|
||||
} blockinfo[] = {
|
||||
{4, 0xa4a3e223}, {2, 0x15c32f9e}, {1, 0x0375b547}, {1, 0x7004a8a5},
|
||||
{2, 0xce440296}, {2, 0x52cfe198}, {1, 0x77a72cd0}, {2, 0xbb5d6f84},
|
||||
{2, 0x83f30c2c}, {1, 0x48a73d5b}, {1, 0xef7dcd01}, {2, 0x6809c6c4},
|
||||
{2, 0x0883ab3c}, {1, 0x087bbbe2}, {2, 0x2104a814}, {2, 0xdffb6daa},
|
||||
{1, 0xee8a0a08}, {2, 0xba4237c1}, {1, 0xa70349dc}, {1, 0x344722bb},
|
||||
{3, 0xd6294733}, {2, 0xec9f5c94}, {2, 0xca2fbc28}, {1, 0x6ba4f406},
|
||||
{2, 0x015d4532}, {1, 0x6e119b7c}, {2, 0x43e8f314}, {2, 0x27962f38},
|
||||
{2, 0xb571b51b}, {2, 0xb36bee23}, {2, 0xd17924a8}, {2, 0x6bc212d9},
|
||||
{1, 0x630d4948}, {2, 0x9a4c4ebb}, {2, 0x554be537}, {1, 0xd63ddfc7},
|
||||
{2, 0xa10acc11}, {1, 0x759a8363}, {2, 0xfb73090d}, {1, 0xe82c6a34},
|
||||
{1, 0xe33e92d7}, {3, 0x658ef5cb}, {2, 0xba32ff22}, {5, 0x0227a10c},
|
||||
{1, 0xa9a70155}, {5, 0xd096d809}, {1, 0x37176174}, {1, 0x830b8d0f},
|
||||
{1, 0xc6e3910e}, {2, 0x823f3ca8}, {1, 0x99850849}, {1, 0x7521fb81},
|
||||
{1, 0xaacaabab}, {1, 0xd645a2eb}, {5, 0x7aea1781}, {5, 0x9d6e4b78},
|
||||
{1, 0x4ce90fd8}, {1, 0xabdc832d}, {6, 0x4a34f32a}, {2, 0xf2524c1c},
|
||||
{2, 0x1bbeb08a}, {1, 0xad47f480}, {1, 0x9f026aeb}, {1, 0x15a95049},
|
||||
{2, 0xd1cb95b2}, {2, 0xf84bbda5}, {1, 0x0fa62cd1}, {1, 0xe05f9169},
|
||||
{1, 0x78d194a9}, {5, 0x3e38147b}, {5, 0x737ba0d4}, {1, 0x63378e10},
|
||||
{1, 0x6d5f91cf}, {2, 0x88612eb8}, {2, 0xe9639484}, {1, 0xb7fabc9d},
|
||||
{2, 0x19b01592}, {1, 0x5a90dd31}, {2, 0x5bd7e028}, {2, 0x94d00323},
|
||||
{1, 0xa9b9c01a}, {1, 0x3a40de61}, {1, 0x56e7eec7}, {5, 0x859f7ef6},
|
||||
{1, 0xfd8e5630}, {1, 0x2b0c9f7f}, {1, 0xba700e26}, {1, 0x7170a408},
|
||||
{1, 0x70de86a8}, {1, 0x74d64cd5}, {1, 0x49e738a1}, {2, 0x6910b602},
|
||||
{0, 0x643c565f}, {1, 0x54264b3f}, {2, 0x97ea6396}, {2, 0x55174459},
|
||||
{2, 0x03e8779a}, {1, 0x98f34d8f}, {1, 0xc07b2b07}, {1, 0xdfe29668},
|
||||
{1, 0x3141c7c1}, {1, 0xb3b595f4}, {1, 0x735abf08}, {5, 0x623bfbce},
|
||||
{2, 0xd351e722}, {1, 0xf4ca48c9}, {1, 0x5b19c670}, {1, 0xa164bf0e},
|
||||
{2, 0xbbbeb305}, {2, 0xfe1c810a},
|
||||
const unsigned int nonces[] = {
|
||||
56564, 72380, 128907, 2182, 184471, 63950, 34000, 9478, 59377, 10829,
|
||||
66034, 37442, 89195, 26592, 26566, 53604, 125840, 89873, 28210, 13648,
|
||||
65365, 100838, 146064, 9575, 124878, 75942, 24172, 234386, 163091, 4967,
|
||||
10462, 22895, 143012, 26772, 98584, 50257, 76046, 56716, 63762, 20472,
|
||||
27042, 11610, 117648, 59446, 95391, 13726, 72678, 54999, 15643, 66372,
|
||||
159975, 34190, 3253, 3817, 3249, 19231, 287, 14293, 56344, 1314, 24596,
|
||||
39278, 42371, 204220, 17374, 32391, 4980, 127690, 13713, 66198, 89787,
|
||||
33360, 8777, 33257, 194167, 25918, 20999, 165920, 55226, 158831, 13566,
|
||||
37669, 264730, 44469, 57778, 40117, 61777, 196161, 107084, 69370, 49739,
|
||||
168694, 181818, 58959, 48614, 1646, 52654, 13423, 89689, 67406, 126841,
|
||||
22148, 59206, 76962, 77648, 2215, 162303, 137215, 37951, 30207, 53220,
|
||||
34221, 14213, 100990, 24457, 181162, 1451, 14573, 10467, 24983, 262822,
|
||||
167979, 25163, 68559, 88074, 135052, 30256, 24860, 25890, 191606, 307582,
|
||||
41542, 15231, 296998, 87388, 275976, 26110, 42669, 12916, 3833, 10375,
|
||||
9826, 37676, 163341, 168130, 3209, 55275, 140779, 33289, 68881, 18576,
|
||||
136275, 536, 25789, 16372, 51618, 12954, 3584, 235289, 5003, 135396,
|
||||
107987, 871, 29290, 29457, 59987, 36795, 27771, 105636, 68229, 7266,
|
||||
37970, 31076, 9463, 5272, 47100, 5844, 55508, 35003, 7540, 27079,
|
||||
56325, 59682, 22508, 24828, 42895, 69580, 71361, 83950, 8510, 21211,
|
||||
26562, 65709, 122140, 23400, 79693, 36035, 50444, 70005, 36025, 135185,
|
||||
71536, 4941, 11151, 3816, 45028, 45271, 90086, 94324, 18419, 108975,
|
||||
17221, 108672, 166833, 40212, 168684, 21230, 22513, 73286, 43347, 101454,
|
||||
418017, 71718, 93728, 214959, 31443, 31111, 41327, 74140, 25836
|
||||
};
|
||||
|
||||
static CBlockIndex CreateBlockIndex(int nHeight)
|
||||
|
@ -112,20 +104,20 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript&
|
|||
tx.vin[0].prevout.hash = txFirst[0]->GetHash();
|
||||
tx.vin[0].prevout.n = 0;
|
||||
tx.vout.resize(1);
|
||||
tx.vout[0].nValue = 5000000000LL - 1000;
|
||||
tx.vout[0].nValue = 50000000LL - 1000;
|
||||
// This tx has a low fee: 1000 satoshis
|
||||
uint256 hashParentTx = tx.GetHash(); // save this txid for later use
|
||||
mempool.addUnchecked(hashParentTx, entry.Fee(1000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
|
||||
|
||||
// This tx has a medium fee: 10000 satoshis
|
||||
tx.vin[0].prevout.hash = txFirst[1]->GetHash();
|
||||
tx.vout[0].nValue = 5000000000LL - 10000;
|
||||
tx.vout[0].nValue = 50000000LL - 10000;
|
||||
uint256 hashMediumFeeTx = tx.GetHash();
|
||||
mempool.addUnchecked(hashMediumFeeTx, entry.Fee(10000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
|
||||
|
||||
// This tx has a high fee, but depends on the first transaction
|
||||
tx.vin[0].prevout.hash = hashParentTx;
|
||||
tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 50k satoshi fee
|
||||
tx.vout[0].nValue = 50000000LL - 1000 - 50000; // 50k satoshi fee
|
||||
uint256 hashHighFeeTx = tx.GetHash();
|
||||
mempool.addUnchecked(hashHighFeeTx, entry.Fee(50000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
|
||||
|
||||
|
@ -136,7 +128,7 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript&
|
|||
|
||||
// Test that a package below the block min tx fee doesn't get included
|
||||
tx.vin[0].prevout.hash = hashHighFeeTx;
|
||||
tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 0 fee
|
||||
tx.vout[0].nValue = 50000000LL - 1000 - 50000; // 0 fee
|
||||
uint256 hashFreeTx = tx.GetHash();
|
||||
mempool.addUnchecked(hashFreeTx, entry.Fee(0).FromTx(tx));
|
||||
size_t freeTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
|
||||
|
@ -146,7 +138,7 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript&
|
|||
CAmount feeToUse = blockMinFeeRate.GetFee(2*freeTxSize) - 1;
|
||||
|
||||
tx.vin[0].prevout.hash = hashFreeTx;
|
||||
tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse;
|
||||
tx.vout[0].nValue = 50000000LL - 1000 - 50000 - feeToUse;
|
||||
uint256 hashLowFeeTx = tx.GetHash();
|
||||
mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse).FromTx(tx));
|
||||
pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
|
||||
|
@ -172,8 +164,8 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript&
|
|||
// Add a 0-fee transaction that has 2 outputs.
|
||||
tx.vin[0].prevout.hash = txFirst[2]->GetHash();
|
||||
tx.vout.resize(2);
|
||||
tx.vout[0].nValue = 5000000000LL - 100000000;
|
||||
tx.vout[1].nValue = 100000000; // 1BTC output
|
||||
tx.vout[0].nValue = 50000000LL - 1000000LL;
|
||||
tx.vout[1].nValue = 1000000LL; // 1BTC output
|
||||
uint256 hashFreeTx2 = tx.GetHash();
|
||||
mempool.addUnchecked(hashFreeTx2, entry.Fee(0).SpendsCoinbase(true).FromTx(tx));
|
||||
|
||||
|
@ -181,7 +173,7 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript&
|
|||
tx.vin[0].prevout.hash = hashFreeTx2;
|
||||
tx.vout.resize(1);
|
||||
feeToUse = blockMinFeeRate.GetFee(freeTxSize);
|
||||
tx.vout[0].nValue = 5000000000LL - 100000000 - feeToUse;
|
||||
tx.vout[0].nValue = 50000000LL - 1000000LL - feeToUse;
|
||||
uint256 hashLowFeeTx2 = tx.GetHash();
|
||||
mempool.addUnchecked(hashLowFeeTx2, entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx));
|
||||
pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
|
||||
|
@ -195,7 +187,7 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript&
|
|||
// This tx will be mineable, and should cause hashLowFeeTx2 to be selected
|
||||
// as well.
|
||||
tx.vin[0].prevout.n = 1;
|
||||
tx.vout[0].nValue = 100000000 - 10000; // 10k satoshi fee
|
||||
tx.vout[0].nValue = 1000000LL - 10000; // 10k satoshi fee
|
||||
mempool.addUnchecked(tx.GetHash(), entry.Fee(10000).FromTx(tx));
|
||||
pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
|
||||
BOOST_CHECK(pblocktemplate->block.vtx[8]->GetHash() == hashLowFeeTx2);
|
||||
|
@ -225,18 +217,17 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||
// Therefore, load 100 blocks :)
|
||||
int baseheight = 0;
|
||||
std::vector<CTransactionRef> txFirst;
|
||||
for (unsigned int i = 0; i < sizeof(blockinfo)/sizeof(*blockinfo); ++i)
|
||||
for (unsigned int i = 0; i < sizeof(nonces)/sizeof(unsigned int); ++i)
|
||||
{
|
||||
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
||||
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
|
||||
{
|
||||
LOCK(cs_main);
|
||||
pblock->nVersion = 1;
|
||||
pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1;
|
||||
pblock->hashPrevBlock = chainActive.Tip()->GetBlockHash();
|
||||
pblock->nVersion = 5;
|
||||
pblock->nTime = chainActive.Tip()->GetBlockTime() + chainparams.GetConsensus().nPowTargetSpacing;
|
||||
CMutableTransaction txCoinbase(*pblock->vtx[0]);
|
||||
txCoinbase.nVersion = 1;
|
||||
txCoinbase.vin[0].scriptSig = CScript();
|
||||
txCoinbase.vin[0].scriptSig.push_back(blockinfo[i].extranonce);
|
||||
txCoinbase.vin[0].scriptSig.push_back(chainActive.Height());
|
||||
txCoinbase.vin[0].scriptSig = CScript() << int(chainActive.Height() + 1) << i;
|
||||
txCoinbase.vout.resize(1); // Ignore the (optional) segwit commitment added by CreateNewBlock (as the hardcoded nonces don't account for this)
|
||||
txCoinbase.vout[0].scriptPubKey = CScript();
|
||||
pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));
|
||||
|
@ -245,11 +236,24 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||
if (txFirst.size() < 4)
|
||||
txFirst.push_back(pblock->vtx[0]);
|
||||
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
|
||||
pblock->nNonce = blockinfo[i].nonce;
|
||||
pblock->nNonce = nonces[i];
|
||||
|
||||
//Use below code to find nonces, in case we change hashing or difficulty retargeting algo
|
||||
//#define NEED_NEW_NONCES_MINER_TEST
|
||||
#ifdef NEED_NEW_NONCES_MINER_TEST
|
||||
for (int j = 0;; j++)
|
||||
{
|
||||
pblock->nNonce = j;
|
||||
if (CheckProofOfWork(pblock->GetPoWHash(), pblock->nBits, chainparams.GetConsensus()))
|
||||
{
|
||||
std::cout << "Nonce is " << pblock->nNonce << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(*pblock);
|
||||
BOOST_CHECK(ProcessNewBlock(chainparams, shared_pblock, true, nullptr));
|
||||
pblock->hashPrevBlock = pblock->GetHash();
|
||||
}
|
||||
|
||||
LOCK(cs_main);
|
||||
|
@ -258,10 +262,10 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||
// Just to make sure we can still make simple blocks
|
||||
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
||||
|
||||
const CAmount BLOCKSUBSIDY = 50*COIN;
|
||||
const CAmount LOWFEE = CENT;
|
||||
const CAmount HIGHFEE = COIN;
|
||||
const CAmount HIGHERFEE = 4*COIN;
|
||||
const CAmount BLOCKSUBSIDY = 50000000LL;
|
||||
const CAmount LOWFEE = 100000LL;
|
||||
const CAmount HIGHFEE = 1000000LL;
|
||||
const CAmount HIGHERFEE = 4*HIGHFEE;
|
||||
|
||||
// block sigops > limit: 1000 CHECKMULTISIG + 1
|
||||
tx.vin.resize(1);
|
||||
|
@ -273,7 +277,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||
tx.vout[0].nValue = BLOCKSUBSIDY;
|
||||
for (unsigned int i = 0; i < 1001; ++i)
|
||||
{
|
||||
tx.vout[0].nValue -= LOWFEE;
|
||||
tx.vout[0].nValue -= 101;
|
||||
hash = tx.GetHash();
|
||||
bool spendsCoinbase = i == 0; // only first tx spends coinbase
|
||||
// If we don't set the # of sig ops in the CTxMemPoolEntry, template creation fails
|
||||
|
@ -288,11 +292,11 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||
tx.vout[0].nValue = BLOCKSUBSIDY;
|
||||
for (unsigned int i = 0; i < 1001; ++i)
|
||||
{
|
||||
tx.vout[0].nValue -= LOWFEE;
|
||||
tx.vout[0].nValue -= 101;
|
||||
hash = tx.GetHash();
|
||||
bool spendsCoinbase = i == 0; // only first tx spends coinbase
|
||||
// If we do set the # of sig ops in the CTxMemPoolEntry, template creation passes
|
||||
mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOpsCost(80).FromTx(tx));
|
||||
mempool.addUnchecked(hash, entry.Fee(LOWFEE / 2).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOpsCost(80).FromTx(tx));
|
||||
tx.vin[0].prevout.hash = hash;
|
||||
}
|
||||
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
||||
|
@ -309,7 +313,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||
tx.vout[0].nValue = BLOCKSUBSIDY;
|
||||
for (unsigned int i = 0; i < 128; ++i)
|
||||
{
|
||||
tx.vout[0].nValue -= LOWFEE;
|
||||
tx.vout[0].nValue -= 100;
|
||||
hash = tx.GetHash();
|
||||
bool spendsCoinbase = i == 0; // only first tx spends coinbase
|
||||
mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
|
||||
|
@ -369,11 +373,16 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||
// subsidy changing
|
||||
int nHeight = chainActive.Height();
|
||||
// Create an actual 209999-long block chain (without valid blocks).
|
||||
BOOST_CHECK(pclaimTrie);
|
||||
CClaimTrieCache trieCache(pclaimTrie);
|
||||
BOOST_CHECK(chainActive.Tip()->GetBlockHash() == trieCache.getBestBlock());
|
||||
while (chainActive.Tip()->nHeight < 209999) {
|
||||
CBlockIndex* prev = chainActive.Tip();
|
||||
CBlockIndex* next = new CBlockIndex();
|
||||
next->phashBlock = new uint256(InsecureRand256());
|
||||
pcoinsTip->SetBestBlock(next->GetBlockHash());
|
||||
trieCache.setBestBlock(next->GetBlockHash());
|
||||
trieCache.flush();
|
||||
next->pprev = prev;
|
||||
next->nHeight = prev->nHeight + 1;
|
||||
next->BuildSkip();
|
||||
|
@ -386,6 +395,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||
CBlockIndex* next = new CBlockIndex();
|
||||
next->phashBlock = new uint256(InsecureRand256());
|
||||
pcoinsTip->SetBestBlock(next->GetBlockHash());
|
||||
trieCache.setBestBlock(next->GetBlockHash());
|
||||
trieCache.flush();
|
||||
next->pprev = prev;
|
||||
next->nHeight = prev->nHeight + 1;
|
||||
next->BuildSkip();
|
||||
|
@ -416,6 +427,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||
CBlockIndex* del = chainActive.Tip();
|
||||
chainActive.SetTip(del->pprev);
|
||||
pcoinsTip->SetBestBlock(del->pprev->GetBlockHash());
|
||||
trieCache.setBestBlock(del->pprev->GetBlockHash());
|
||||
trieCache.flush();
|
||||
delete del->phashBlock;
|
||||
delete del;
|
||||
}
|
||||
|
@ -427,7 +440,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||
std::vector<int> prevheights;
|
||||
|
||||
// relative height locked
|
||||
tx.nVersion = 2;
|
||||
tx.nVersion = CTransaction::CURRENT_VERSION;
|
||||
tx.vin.resize(1);
|
||||
prevheights.resize(1);
|
||||
tx.vin[0].prevout.hash = txFirst[0]->GetHash(); // only 1 transaction
|
||||
|
@ -440,6 +453,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||
tx.vout[0].scriptPubKey = CScript() << OP_1;
|
||||
tx.nLockTime = 0;
|
||||
hash = tx.GetHash();
|
||||
|
||||
mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
|
||||
BOOST_CHECK(CheckFinalTx(tx, flags)); // Locktime passes
|
||||
BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail
|
||||
|
|
36
src/test/nameclaim_tests.cpp
Normal file
36
src/test/nameclaim_tests.cpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
#include "nameclaim.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include "test/test_bitcoin.h"
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(nameclaim_tests, BasicTestingSetup)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(calc_min_claimtrie_fee)
|
||||
{
|
||||
|
||||
CMutableTransaction tx;
|
||||
tx.vout.resize(1);
|
||||
tx.vout[0].scriptPubKey = ClaimNameScript("A","test");
|
||||
BOOST_CHECK_EQUAL(CalcMinClaimTrieFee(tx, MIN_FEE_PER_NAMECLAIM_CHAR), MIN_FEE_PER_NAMECLAIM_CHAR);
|
||||
|
||||
// check that fee is adjusted based on name length
|
||||
CMutableTransaction tx2;
|
||||
tx2.vout.resize(1);
|
||||
tx2.vout[0].scriptPubKey = ClaimNameScript("ABCDE","test");
|
||||
BOOST_CHECK_EQUAL(CalcMinClaimTrieFee(tx2,MIN_FEE_PER_NAMECLAIM_CHAR), MIN_FEE_PER_NAMECLAIM_CHAR*5);
|
||||
|
||||
// check that multiple OP_CLAIM_NAME outputs are counted
|
||||
CMutableTransaction tx3;
|
||||
tx3.vout.resize(2);
|
||||
tx3.vout[0].scriptPubKey = ClaimNameScript("A","test");
|
||||
tx3.vout[1].scriptPubKey = ClaimNameScript("AB","test");
|
||||
BOOST_CHECK_EQUAL(CalcMinClaimTrieFee(tx3,MIN_FEE_PER_NAMECLAIM_CHAR), MIN_FEE_PER_NAMECLAIM_CHAR*3);
|
||||
|
||||
// if tx has no claim minimum fee is 0
|
||||
CMutableTransaction tx4;
|
||||
tx4.vout.resize(1);
|
||||
BOOST_CHECK_EQUAL(CalcMinClaimTrieFee(tx4,MIN_FEE_PER_NAMECLAIM_CHAR), 0);
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
|
@ -22,7 +22,7 @@ BOOST_AUTO_TEST_CASE(get_next_work)
|
|||
pindexLast.nHeight = 32255;
|
||||
pindexLast.nTime = 1262152739; // Block #32255
|
||||
pindexLast.nBits = 0x1d00ffff;
|
||||
BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00d86aU);
|
||||
BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1D03FFFCU);
|
||||
}
|
||||
|
||||
/* Test the constraint on the upper bound for next work */
|
||||
|
@ -34,7 +34,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_pow_limit)
|
|||
pindexLast.nHeight = 2015;
|
||||
pindexLast.nTime = 1233061996; // Block #2015
|
||||
pindexLast.nBits = 0x1d00ffff;
|
||||
BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00ffffU);
|
||||
BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1D03FFFCU);
|
||||
}
|
||||
|
||||
/* Test the constraint on the lower bound for actual time taken */
|
||||
|
@ -46,7 +46,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual)
|
|||
pindexLast.nHeight = 68543;
|
||||
pindexLast.nTime = 1279297671; // Block #68543
|
||||
pindexLast.nBits = 0x1c05a3f4;
|
||||
BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1c0168fdU);
|
||||
BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1C168FD0U);
|
||||
}
|
||||
|
||||
/* Test the constraint on the upper bound for actual time taken */
|
||||
|
|
|
@ -335,6 +335,24 @@ 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(CallRPC("getnameproof test not_hex"), std::runtime_error);
|
||||
// std::runtime_error: Block not found
|
||||
BOOST_CHECK_THROW(CallRPC("getnameproof test aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), std::runtime_error);
|
||||
// Generate a block to validate the NO_THROW case.
|
||||
BOOST_CHECK_NO_THROW(CallRPC("getnameproof test"));
|
||||
|
||||
BOOST_CHECK_THROW(CallRPC("getclaimsfortx not_hex"), std::runtime_error);
|
||||
BOOST_CHECK_NO_THROW(CallRPC("getclaimsfortx aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
|
||||
|
||||
BOOST_CHECK_THROW(CallRPC("getclaimbyid not_hex"), std::runtime_error);
|
||||
// Wrong length. */
|
||||
BOOST_CHECK_THROW(CallRPC("getclaimbyid a"), std::runtime_error);
|
||||
BOOST_CHECK_NO_THROW(CallRPC("getclaimbyid aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(rpc_getblockstats_calculate_percentiles_by_weight)
|
||||
{
|
||||
int64_t total_weight = 200;
|
||||
|
|
|
@ -722,7 +722,7 @@ BOOST_AUTO_TEST_CASE(script_build)
|
|||
).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem());
|
||||
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
|
||||
"P2PK with non-push scriptSig but with P2SH validation", 0
|
||||
).PushSig(keys.key2).Add(CScript() << OP_NOP8));
|
||||
).PushSig(keys.key2).Add(CScript() << OP_NOP9));
|
||||
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
|
||||
"P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY", SCRIPT_VERIFY_P2SH, true
|
||||
).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem().ScriptError(SCRIPT_ERR_SIG_PUSHONLY));
|
||||
|
@ -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;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -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
|
||||
|
@ -122,9 +127,17 @@ struct TestMemPoolEntryHelper
|
|||
TestMemPoolEntryHelper &SigOpsCost(unsigned int _sigopsCost) { sigOpCost = _sigopsCost; return *this; }
|
||||
};
|
||||
|
||||
CBlock getBlock13b8a();
|
||||
CBlock getTestBlock();
|
||||
|
||||
// define an implicit conversion here so that uint256 may be used directly in BOOST_CHECK_*
|
||||
std::ostream& operator<<(std::ostream& os, const uint256& num);
|
||||
std::ostream& operator<<(std::ostream& os, const uint160& num);
|
||||
std::ostream& operator<<(std::ostream& os, const COutPoint& point);
|
||||
|
||||
class CClaimValue;
|
||||
std::ostream& operator<<(std::ostream& os, const CClaimValue& claim);
|
||||
|
||||
class CClaimTrieNode;
|
||||
std::ostream& operator<<(std::ostream& os, const CClaimTrieNode& node);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -558,27 +558,27 @@ BOOST_AUTO_TEST_CASE(util_GetChainName)
|
|||
std::string error;
|
||||
|
||||
test_args.ParseParameters(0, (char**)argv_testnet, error);
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "main");
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "lbrycrd");
|
||||
|
||||
test_args.ParseParameters(2, (char**)argv_testnet, error);
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "lbrycrdtest");
|
||||
|
||||
test_args.ParseParameters(2, (char**)argv_regtest, error);
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "regtest");
|
||||
|
||||
test_args.ParseParameters(3, (char**)argv_test_no_reg, error);
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "lbrycrdtest");
|
||||
|
||||
test_args.ParseParameters(3, (char**)argv_both, error);
|
||||
BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
|
||||
|
||||
test_args.ParseParameters(0, (char**)argv_testnet, error);
|
||||
test_args.ReadConfigString(testnetconf);
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "lbrycrdtest");
|
||||
|
||||
test_args.ParseParameters(2, (char**)argv_testnet, error);
|
||||
test_args.ReadConfigString(testnetconf);
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "lbrycrdtest");
|
||||
|
||||
test_args.ParseParameters(2, (char**)argv_regtest, error);
|
||||
test_args.ReadConfigString(testnetconf);
|
||||
|
@ -586,7 +586,7 @@ BOOST_AUTO_TEST_CASE(util_GetChainName)
|
|||
|
||||
test_args.ParseParameters(3, (char**)argv_test_no_reg, error);
|
||||
test_args.ReadConfigString(testnetconf);
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "lbrycrdtest");
|
||||
|
||||
test_args.ParseParameters(3, (char**)argv_both, error);
|
||||
test_args.ReadConfigString(testnetconf);
|
||||
|
@ -598,11 +598,11 @@ BOOST_AUTO_TEST_CASE(util_GetChainName)
|
|||
|
||||
test_args.ParseParameters(0, (char**)argv_testnet, error);
|
||||
test_args.ReadConfigString(testnetconf);
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "lbrycrdtest");
|
||||
|
||||
test_args.ParseParameters(2, (char**)argv_testnet, error);
|
||||
test_args.ReadConfigString(testnetconf);
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "lbrycrdtest");
|
||||
|
||||
test_args.ParseParameters(2, (char**)argv_regtest, error);
|
||||
test_args.ReadConfigString(testnetconf);
|
||||
|
@ -610,7 +610,7 @@ BOOST_AUTO_TEST_CASE(util_GetChainName)
|
|||
|
||||
test_args.ParseParameters(2, (char**)argv_test_no_reg, error);
|
||||
test_args.ReadConfigString(testnetconf);
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "lbrycrdtest");
|
||||
|
||||
test_args.ParseParameters(3, (char**)argv_both, error);
|
||||
test_args.ReadConfigString(testnetconf);
|
||||
|
|
|
@ -71,7 +71,7 @@ std::shared_ptr<CBlock> FinalizeBlock(std::shared_ptr<CBlock> pblock)
|
|||
{
|
||||
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
|
||||
|
||||
while (!CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus())) {
|
||||
while (!CheckProofOfWork(pblock->GetPoWHash(), pblock->nBits, Params().GetConsensus())) {
|
||||
++(pblock->nNonce);
|
||||
}
|
||||
|
||||
|
|
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,10 +21,12 @@ 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)
|
||||
static const int64_t nDefaultDbCache = 450;
|
||||
static const int64_t nDefaultDbCache = sizeof(void*) > 4 ? 700 : 450;
|
||||
//! -dbbatchsize default (bytes)
|
||||
static const int64_t nDefaultDbBatchSize = 16 << 20;
|
||||
//! max. -dbcache (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; // >> 2?
|
||||
txout->fCoinBase = (nCode & 2) ? 1: 0;
|
||||
fLastUnspent = (nCode & 1) > 0;
|
||||
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;
|
||||
|
||||
|
@ -707,10 +707,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");
|
||||
|
@ -720,10 +720,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
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <cuckoocache.h>
|
||||
#include <hash.h>
|
||||
#include <index/txindex.h>
|
||||
#include <nameclaim.h>
|
||||
#include <policy/fees.h>
|
||||
#include <policy/policy.h>
|
||||
#include <policy/rbf.h>
|
||||
|
@ -54,164 +55,9 @@
|
|||
#define MICRO 0.000001
|
||||
#define MILLI 0.001
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
enum DisconnectResult
|
||||
{
|
||||
DISCONNECT_OK, // All good.
|
||||
DISCONNECT_UNCLEAN, // Rolled back, but UTXO set was inconsistent with block.
|
||||
DISCONNECT_FAILED // Something else went wrong.
|
||||
};
|
||||
|
||||
class ConnectTrace;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex,
|
||||
CCoinsViewCache& view, 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);
|
||||
} g_chainstate;
|
||||
|
||||
|
||||
struct CDiskTxIndex;
|
||||
|
||||
CChainState g_chainstate;
|
||||
CCriticalSection cs_main;
|
||||
|
||||
BlockMap& mapBlockIndex = g_chainstate.mapBlockIndex;
|
||||
|
@ -239,6 +85,7 @@ arith_uint256 nMinimumChainWork;
|
|||
|
||||
CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
|
||||
CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE;
|
||||
CAmount minFeePerNameClaimChar = MIN_FEE_PER_NAMECLAIM_CHAR;
|
||||
|
||||
CBlockPolicyEstimator feeEstimator;
|
||||
CTxMemPool mempool(&feeEstimator);
|
||||
|
@ -247,7 +94,7 @@ std::atomic_bool g_is_mempool_loaded{false};
|
|||
/** Constant stuff for coinbase transactions we create: */
|
||||
CScript COINBASE_FLAGS;
|
||||
|
||||
const std::string strMessageMagic = "Bitcoin Signed Message:\n";
|
||||
const std::string strMessageMagic = "LBRYcrd Signed Message:\n";
|
||||
|
||||
// Internal stuff
|
||||
namespace {
|
||||
|
@ -290,12 +137,15 @@ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& loc
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return chain.Genesis();
|
||||
}
|
||||
|
||||
std::unique_ptr<CCoinsViewDB> pcoinsdbview;
|
||||
std::unique_ptr<CCoinsViewCache> pcoinsTip;
|
||||
std::unique_ptr<CBlockTreeDB> pblocktree;
|
||||
// FIXME: make unique_ptr
|
||||
CClaimTrie *pclaimTrie = nullptr;
|
||||
|
||||
enum class FlushStateMode {
|
||||
NONE,
|
||||
|
@ -579,13 +429,15 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
|
|||
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
|
||||
std::string reason;
|
||||
if (fRequireStandard && !IsStandardTx(tx, reason))
|
||||
return state.DoS(0, false, REJECT_NONSTANDARD, reason);
|
||||
return state.DoS(0, false, (reason == "dust" ? REJECT_DUST : REJECT_NONSTANDARD), reason);
|
||||
|
||||
// Do not work on transactions that are too small.
|
||||
// A transaction with 1 segwit input and 1 P2WPHK output has non-witness size of 82 bytes.
|
||||
// Transactions smaller than this are not relayed to reduce unnecessary malloc overhead.
|
||||
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) < MIN_STANDARD_TX_NONWITNESS_SIZE)
|
||||
return state.DoS(0, false, REJECT_NONSTANDARD, "tx-size-small");
|
||||
//
|
||||
// NOTE: LBRY does not honor this node rule.
|
||||
/* if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) < MIN_STANDARD_TX_NONWITNESS_SIZE) */
|
||||
/* return state.DoS(0, false, REJECT_NONSTANDARD, "tx-size-small"); */
|
||||
|
||||
// Only accept nLockTime-using transactions that can be mined in the next
|
||||
// block; we don't want our mempool filled up with transactions that can't
|
||||
|
@ -641,6 +493,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
CCoinsView dummy;
|
||||
CCoinsViewCache view(&dummy);
|
||||
|
@ -1091,7 +944,7 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus:
|
|||
}
|
||||
|
||||
// Check the header
|
||||
if (!CheckProofOfWork(block.GetHash(), block.nBits, consensusParams))
|
||||
if (!CheckProofOfWork(block.GetPoWHash(), block.nBits, consensusParams))
|
||||
return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString());
|
||||
|
||||
return true;
|
||||
|
@ -1159,17 +1012,54 @@ bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const CBlockIndex* pindex
|
|||
return ReadRawBlockFromDisk(block, block_pos, message_start);
|
||||
}
|
||||
|
||||
bool withinLevelBounds(int nReduction, int nLevel)
|
||||
{
|
||||
if (((nReduction * nReduction + nReduction) >> 1) > nLevel)
|
||||
return false;
|
||||
nReduction += 1;
|
||||
if (((nReduction * nReduction + nReduction) >> 1) <= nLevel)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)
|
||||
{
|
||||
int halvings = nHeight / consensusParams.nSubsidyHalvingInterval;
|
||||
// Force block reward to zero when right shift is undefined.
|
||||
if (halvings >= 64)
|
||||
if (nHeight == 0)
|
||||
{
|
||||
return 400000000 * COIN;
|
||||
}
|
||||
else if (nHeight <= 5100)
|
||||
{
|
||||
return 1 * COIN;
|
||||
}
|
||||
else if (nHeight <= 55000)
|
||||
{
|
||||
int l = nHeight - 5000;
|
||||
int nLevel = 0;
|
||||
for (int i = 0; i < l; i+=100)
|
||||
{
|
||||
nLevel++;
|
||||
}
|
||||
return nLevel * COIN;
|
||||
}
|
||||
CAmount nStartingSubsidy = 500 * COIN;
|
||||
int nLevel = (nHeight - 55001) / consensusParams.nSubsidyLevelInterval;
|
||||
int nReduction = ((-1 + (int)sqrt((8 * nLevel) + 1)) / 2);
|
||||
while (!(withinLevelBounds(nReduction, nLevel)))
|
||||
{
|
||||
if (((nReduction * nReduction + nReduction) >> 1) > nLevel)
|
||||
{
|
||||
nReduction--;
|
||||
}
|
||||
else
|
||||
{
|
||||
nReduction++;
|
||||
}
|
||||
}
|
||||
CAmount nSubsidyReduction = nReduction * COIN;
|
||||
if (nSubsidyReduction >= nStartingSubsidy)
|
||||
return 0;
|
||||
|
||||
CAmount nSubsidy = 50 * COIN;
|
||||
// Subsidy is cut in half every 210,000 blocks which will occur approximately every 4 years.
|
||||
nSubsidy >>= halvings;
|
||||
return nSubsidy;
|
||||
return nStartingSubsidy - nSubsidyReduction;
|
||||
}
|
||||
|
||||
bool IsInitialBlockDownload()
|
||||
|
@ -1321,10 +1211,12 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txund
|
|||
// mark inputs spent
|
||||
if (!tx.IsCoinBase()) {
|
||||
txundo.vprevout.reserve(tx.vin.size());
|
||||
for (const CTxIn &txin : tx.vin) {
|
||||
txundo.vprevout.emplace_back();
|
||||
bool is_spent = inputs.SpendCoin(txin.prevout, &txundo.vprevout.back());
|
||||
for(size_t i = 0; i < tx.vin.size(); i++) {
|
||||
const CTxIn& txin = tx.vin[i];
|
||||
Coin coin{};
|
||||
bool is_spent = inputs.SpendCoin(txin.prevout, &coin);
|
||||
assert(is_spent);
|
||||
txundo.vprevout.push_back(coin);
|
||||
}
|
||||
}
|
||||
// add outputs
|
||||
|
@ -1525,8 +1417,9 @@ static bool AbortNode(const std::string& strMessage, const std::string& userMess
|
|||
{
|
||||
SetMiscWarning(strMessage);
|
||||
LogPrintf("*** %s\n", strMessage);
|
||||
throw "nasty";
|
||||
uiInterface.ThreadSafeMessageBox(
|
||||
userMessage.empty() ? _("Error: A fatal internal error occurred, see debug.log for details") : userMessage,
|
||||
userMessage.empty() ? "Error: A fatal internal error occurred, see debug.log for details. System message: " + strMessage : userMessage,
|
||||
"", CClientUIInterface::MSG_ERROR);
|
||||
StartShutdown();
|
||||
return false;
|
||||
|
@ -1544,13 +1437,22 @@ static bool AbortNode(CValidationState& state, const std::string& strMessage, co
|
|||
* Restore the UTXO in a Coin at a given COutPoint
|
||||
* @param undo The Coin to be restored.
|
||||
* @param view The coins view to which to apply the changes.
|
||||
* @param view The claim trieCache to which to apply the changes.
|
||||
* @param out The out point that corresponds to the tx input.
|
||||
* @return A DisconnectResult as an int
|
||||
*/
|
||||
int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out)
|
||||
int ApplyTxInUndo(unsigned int index, CTxUndo& txUndo, CCoinsViewCache& view, CClaimTrieCache& trieCache, const COutPoint& out)
|
||||
{
|
||||
bool fClean = true;
|
||||
Coin& undo = txUndo.vprevout[index];
|
||||
unsigned int nClaimValidHeight = 0;
|
||||
bool fIsClaim = false;
|
||||
const auto claimIt = txUndo.claimInfo.find(index);
|
||||
if (claimIt != txUndo.claimInfo.end()) {
|
||||
nClaimValidHeight = claimIt->second.nClaimValidHeight;
|
||||
fIsClaim = claimIt->second.fIsClaim;
|
||||
}
|
||||
|
||||
bool fClean = true;
|
||||
if (view.HaveCoin(out)) fClean = false; // overwriting transaction output
|
||||
|
||||
if (undo.nHeight == 0) {
|
||||
|
@ -1565,6 +1467,59 @@ int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out)
|
|||
return DISCONNECT_FAILED; // adding output for transaction without known metadata
|
||||
}
|
||||
}
|
||||
|
||||
/* restore claim if applicable */
|
||||
int op;
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
if (fIsClaim && DecodeClaimScript(undo.out.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(out.hash, out.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 nValidHeight = static_cast<int>(nClaimValidHeight);
|
||||
if (nValidHeight > 0 && nValidHeight >= undo.nHeight)
|
||||
{
|
||||
LogPrintf("%s: (txid: %s, nOut: %d) Restoring %s to the claim trie due to a block being disconnected\n", __func__, out.hash.ToString(), out.n, name);
|
||||
if (!trieCache.undoSpendClaim(name, COutPoint(out.hash, out.n), claimId, undo.out.nValue, undo.nHeight, nValidHeight))
|
||||
LogPrintf("%s: Something went wrong inserting the claim\n", __func__);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrintf("%s: (txid: %s, nOut: %d) Not restoring %s to the claim trie because it expired before it was spent\n", __func__, out.hash.ToString(), out.n, name.c_str());
|
||||
LogPrintf("%s: nValidHeight = %d, undo.nHeight = %d, nCurrentHeight = %d\n", __func__, nValidHeight, undo.nHeight, chainActive.Height());
|
||||
}
|
||||
}
|
||||
else if (op == OP_SUPPORT_CLAIM)
|
||||
{
|
||||
assert(vvchParams.size() == 2);
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
uint160 supportedClaimId(vvchParams[1]);
|
||||
int nValidHeight = static_cast<int>(nClaimValidHeight);
|
||||
if (nValidHeight > 0 && nValidHeight >= undo.nHeight)
|
||||
{
|
||||
LogPrintf("%s: (txid: %s, nOut: %d) Restoring support for %s in claimid %s due to a block being disconnected\n", __func__, out.hash.ToString(), out.n, name, supportedClaimId.ToString());
|
||||
if (!trieCache.undoSpendSupport(name, COutPoint(out.hash, out.n), supportedClaimId, undo.out.nValue, undo.nHeight, nValidHeight))
|
||||
LogPrintf("%s: Something went wrong inserting support for the claim\n", __func__);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrintf("%s: (txid: %s, nOut: %d) Not restoring support for %s in claimid %s because the support expired before it was spent\n", __func__, out.hash.ToString(), out.n, name, supportedClaimId.ToString());
|
||||
LogPrintf("%s: nValidHeight = %d, undo.nHeight = %d, nCurrentHeight = %d\n", __func__, nValidHeight, undo.nHeight, chainActive.Height());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The potential_overwrite parameter to AddCoin is only allowed to be false if we know for
|
||||
// sure that the coin did not already exist in the cache. As we have queried for that above
|
||||
// using HaveCoin, we don't need to guess. When fClean is false, a coin already existed and
|
||||
|
@ -1576,8 +1531,11 @@ int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out)
|
|||
|
||||
/** Undo the effects of this block (with given index) on the UTXO set represented by coins.
|
||||
* When FAILED is returned, view is left in an indeterminate state. */
|
||||
DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view)
|
||||
DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view, CClaimTrieCache& trieCache)
|
||||
{
|
||||
assert(pindex->GetBlockHash() == view.GetBestBlock());
|
||||
assert(pindex->GetBlockHash() == trieCache.getBestBlock());
|
||||
|
||||
bool fClean = true;
|
||||
|
||||
CBlockUndo blockUndo;
|
||||
|
@ -1591,6 +1549,9 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI
|
|||
return DISCONNECT_FAILED;
|
||||
}
|
||||
|
||||
const bool decremented = trieCache.decrementBlock(blockUndo.insertUndo, blockUndo.expireUndo, blockUndo.insertSupportUndo, blockUndo.expireSupportUndo, blockUndo.takeoverHeightUndo);
|
||||
assert(decremented);
|
||||
|
||||
// undo transactions in reverse order
|
||||
for (int i = block.vtx.size() - 1; i >= 0; i--) {
|
||||
const CTransaction &tx = *(block.vtx[i]);
|
||||
|
@ -1610,6 +1571,58 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI
|
|||
}
|
||||
}
|
||||
|
||||
// remove any claims
|
||||
for (size_t j = 0; j < tx.vout.size(); j++)
|
||||
{
|
||||
const CTxOut& txout = tx.vout[j];
|
||||
|
||||
int op;
|
||||
std::vector<std::vector<unsigned char>> vvchParams;
|
||||
if (DecodeClaimScript(txout.scriptPubKey, op, vvchParams))
|
||||
{
|
||||
if (op == OP_CLAIM_NAME || op == OP_UPDATE_CLAIM)
|
||||
{
|
||||
uint160 claimId;
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
std::string value(vvchParams[1].begin(), vvchParams[1].end());
|
||||
if (op == OP_CLAIM_NAME)
|
||||
{
|
||||
assert(vvchParams.size() == 2);
|
||||
claimId = ClaimIdHash(hash, j);
|
||||
LogPrintf("--- %s[%lu]: OP_CLAIM_NAME \"%s\" = \"%s\" with claimId %s and tx prevout %s at index %d\n",
|
||||
__func__, pindex->nHeight, name, SanitizeString(value),
|
||||
claimId.GetHex(), hash.ToString(), j);
|
||||
}
|
||||
else if (op == OP_UPDATE_CLAIM)
|
||||
{
|
||||
assert(vvchParams.size() == 3);
|
||||
claimId = uint160(vvchParams[1]);
|
||||
LogPrintf("--- %s[%lu]: OP_UPDATE_CLAIM \"%s\" = \"%s\" with claimId %s and tx prevout %s at index %d\n",
|
||||
__func__, pindex->nHeight, name, SanitizeString(value),
|
||||
claimId.GetHex(), hash.ToString(), j);
|
||||
}
|
||||
LogPrintf("%s: (txid: %s, nOut: %d) Trying to remove %s from the claim trie due to its block being disconnected\n",
|
||||
__func__, hash.ToString(), j, name);
|
||||
if (!trieCache.undoAddClaim(name, COutPoint(hash, j)))
|
||||
{
|
||||
LogPrintf("%s: Could not find the claim in the trie or the cache\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]);
|
||||
LogPrintf("--- %s[%lu]: OP_SUPPORT_CLAIM \"%s\" with claimId %s and tx prevout %s at index %d\n",
|
||||
__func__, pindex->nHeight, name, supportedClaimId.GetHex(), hash.ToString(), j);
|
||||
LogPrintf("%s: (txid: %s, nOut: %d) Removing support for claim id %s on %s due to its block being disconnected\n",
|
||||
__func__, hash.ToString(), j, supportedClaimId.ToString(), name);
|
||||
if (!trieCache.undoAddSupport(name, COutPoint(hash, j)))
|
||||
LogPrintf("%s: Something went wrong removing support for name %s in hash %s\n", __func__, name.c_str(), hash.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// restore inputs
|
||||
if (i > 0) { // not coinbases
|
||||
CTxUndo &txundo = blockUndo.vtxundo[i-1];
|
||||
|
@ -1619,16 +1632,30 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI
|
|||
}
|
||||
for (unsigned int j = tx.vin.size(); j-- > 0;) {
|
||||
const COutPoint &out = tx.vin[j].prevout;
|
||||
int res = ApplyTxInUndo(std::move(txundo.vprevout[j]), view, out);
|
||||
/* int res = ApplyTxInUndo(std::move(txundo.vprevout[j]), txundo, view, trieCache, out); */
|
||||
int res = ApplyTxInUndo(j, txundo, view, trieCache, out);
|
||||
if (res == DISCONNECT_FAILED) return DISCONNECT_FAILED;
|
||||
fClean = fClean && res != DISCONNECT_UNCLEAN;
|
||||
}
|
||||
// At this point, all of txundo.vprevout should have been moved out.
|
||||
//
|
||||
// Note: This comment is no longer true, but doesn't
|
||||
// affect anything either since it's no longer accessed.
|
||||
}
|
||||
}
|
||||
|
||||
// move best block pointer to prevout block
|
||||
view.SetBestBlock(pindex->pprev->GetBlockHash());
|
||||
assert(trieCache.finalizeDecrement());
|
||||
trieCache.setBestBlock(pindex->pprev->GetBlockHash());
|
||||
assert(trieCache.getMerkleHash() == pindex->pprev->hashClaimTrie);
|
||||
|
||||
if (pindex->nHeight == Params().GetConsensus().nExtendedClaimExpirationForkHeight)
|
||||
{
|
||||
LogPrintf("Decremented past the extended claim expiration hard fork height\n");
|
||||
pclaimTrie->setExpirationTime(Params().GetConsensus().GetExpirationTime(pindex->nHeight-1));
|
||||
trieCache.forkForExpirationChange(false);
|
||||
}
|
||||
|
||||
return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN;
|
||||
}
|
||||
|
@ -1669,7 +1696,7 @@ static bool WriteUndoDataForBlock(const CBlockUndo& blockundo, CValidationState&
|
|||
if (pindex->GetUndoPos().IsNull()) {
|
||||
CDiskBlockPos _pos;
|
||||
if (!FindUndoPos(state, pindex->nFile, _pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40))
|
||||
return error("ConnectBlock(): FindUndoPos failed");
|
||||
return error("WriteUndoDataForBlock(): FindUndoPos failed");
|
||||
if (!UndoWriteToDisk(blockundo, _pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart()))
|
||||
return AbortNode(state, "Failed to write undo data");
|
||||
|
||||
|
@ -1803,7 +1830,7 @@ static int64_t nBlocksTotal = 0;
|
|||
* Validity checks that depend on the UTXO set are also done; ConnectBlock()
|
||||
* can fail if those validity checks fail (among other reasons). */
|
||||
bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex,
|
||||
CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck)
|
||||
CCoinsViewCache& view, CClaimTrieCache& trieCache, const CChainParams& chainparams, bool fJustCheck)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
assert(pindex);
|
||||
|
@ -1837,12 +1864,18 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
|
|||
uint256 hashPrevBlock = pindex->pprev == nullptr ? uint256() : pindex->pprev->GetBlockHash();
|
||||
assert(hashPrevBlock == view.GetBestBlock());
|
||||
|
||||
// also verify that the trie cache's current state corresponds to the previous block
|
||||
assert(hashPrevBlock == trieCache.getBestBlock());
|
||||
|
||||
// Special case for the genesis block, skipping connection of its transactions
|
||||
// (its coinbase is unspendable)
|
||||
if (block.GetHash() == chainparams.GetConsensus().hashGenesisBlock) {
|
||||
if (!fJustCheck)
|
||||
{
|
||||
view.SetBestBlock(pindex->GetBlockHash());
|
||||
return true;
|
||||
trieCache.setBestBlock(pindex->GetBlockHash());
|
||||
}
|
||||
/* return true; */
|
||||
}
|
||||
|
||||
nBlocksTotal++;
|
||||
|
@ -1947,20 +1980,23 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
|
|||
// post BIP34 before approximately height 486,000,000 and presumably will
|
||||
// be reset before it reaches block 1,983,702 and starts doing unnecessary
|
||||
// BIP30 checking again.
|
||||
assert(pindex->pprev);
|
||||
CBlockIndex *pindexBIP34height = pindex->pprev->GetAncestor(chainparams.GetConsensus().BIP34Height);
|
||||
//Only continue to enforce if we're below BIP34 activation height or the block hash at that height doesn't correspond.
|
||||
fEnforceBIP30 = fEnforceBIP30 && (!pindexBIP34height || !(pindexBIP34height->GetBlockHash() == chainparams.GetConsensus().BIP34Hash));
|
||||
/* assert(pindex->pprev); */
|
||||
if (pindex->pprev)
|
||||
{
|
||||
CBlockIndex *pindexBIP34height = pindex->pprev->GetAncestor(chainparams.GetConsensus().BIP34Height);
|
||||
//Only continue to enforce if we're below BIP34 activation height or the block hash at that height doesn't correspond.
|
||||
fEnforceBIP30 = fEnforceBIP30 && (!pindexBIP34height || !(pindexBIP34height->GetBlockHash() == chainparams.GetConsensus().BIP34Hash));
|
||||
|
||||
// TODO: Remove BIP30 checking from block height 1,983,702 on, once we have a
|
||||
// consensus change that ensures coinbases at those heights can not
|
||||
// duplicate earlier coinbases.
|
||||
if (fEnforceBIP30 || pindex->nHeight >= BIP34_IMPLIES_BIP30_LIMIT) {
|
||||
for (const auto& tx : block.vtx) {
|
||||
for (size_t o = 0; o < tx->vout.size(); o++) {
|
||||
if (view.HaveCoin(COutPoint(tx->GetHash(), o))) {
|
||||
return state.DoS(100, error("ConnectBlock(): tried to overwrite transaction"),
|
||||
REJECT_INVALID, "bad-txns-BIP30");
|
||||
// TODO: Remove BIP30 checking from block height 1,983,702 on, once we have a
|
||||
// consensus change that ensures coinbases at those heights can not
|
||||
// duplicate earlier coinbases.
|
||||
if (fEnforceBIP30 || pindex->nHeight >= BIP34_IMPLIES_BIP30_LIMIT) {
|
||||
for (const auto& tx : block.vtx) {
|
||||
for (size_t o = 0; o < tx->vout.size(); o++) {
|
||||
if (view.HaveCoin(COutPoint(tx->GetHash(), o))) {
|
||||
return state.DoS(100, error("ConnectBlock(): tried to overwrite transaction"),
|
||||
REJECT_INVALID, "bad-txns-BIP30");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1975,6 +2011,14 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
|
|||
// Get the script flags for this block
|
||||
unsigned int flags = GetBlockScriptFlags(pindex, chainparams.GetConsensus());
|
||||
|
||||
// v 13 LBRYcrd hard fork to extend expiration time
|
||||
if (pindex->nHeight == Params().GetConsensus().nExtendedClaimExpirationForkHeight)
|
||||
{
|
||||
LogPrintf("Incremented past the extended claim expiration hard fork height\n");
|
||||
pclaimTrie->setExpirationTime(chainparams.GetConsensus().GetExpirationTime(pindex->nHeight));
|
||||
trieCache.forkForExpirationChange(true);
|
||||
}
|
||||
|
||||
int64_t nTime2 = GetTimeMicros(); nTimeForks += nTime2 - nTime1;
|
||||
LogPrint(BCLog::BENCH, " - Fork checks: %.2fms [%.2fs (%.2fms/blk)]\n", MILLI * (nTime2 - nTime1), nTimeForks * MICRO, nTimeForks * MILLI / nBlocksTotal);
|
||||
|
||||
|
@ -1986,12 +2030,16 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
|
|||
CAmount nFees = 0;
|
||||
int nInputs = 0;
|
||||
int64_t nSigOpsCost = 0;
|
||||
CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size()));
|
||||
std::vector<std::pair<uint256, CDiskTxPos> > vPos;
|
||||
vPos.reserve(block.vtx.size());
|
||||
blockundo.vtxundo.reserve(block.vtx.size() - 1);
|
||||
std::vector<PrecomputedTransactionData> txdata;
|
||||
txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated
|
||||
for (unsigned int i = 0; i < block.vtx.size(); i++)
|
||||
{
|
||||
const CTransaction &tx = *(block.vtx[i]);
|
||||
std::map<unsigned int, unsigned int> mClaimUndoHeights;
|
||||
|
||||
nInputs += tx.vin.size();
|
||||
|
||||
|
@ -2037,8 +2085,136 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
|
|||
bool fCacheResults = fJustCheck; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */
|
||||
if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, fCacheResults, txdata[i], nScriptCheckThreads ? &vChecks : nullptr))
|
||||
return error("ConnectBlock(): CheckInputs on %s failed with %s",
|
||||
tx.GetHash().ToString(), FormatStateMessage(state));
|
||||
tx.GetHash().ToString(), FormatStateMessage(state));
|
||||
control.Add(vChecks);
|
||||
|
||||
// To handle claim updates, stick all claims found in the inputs into a map of
|
||||
// name: (txhash, nOut). When running through the outputs, if any claim's
|
||||
// name is found in the map, send the name's txhash and nOut to the trie cache,
|
||||
// and then remove the name: (txhash, nOut) mapping from the map.
|
||||
// If there are two or more claims in the inputs with the same name, only
|
||||
// use the first.
|
||||
|
||||
typedef std::vector<std::pair<std::string, uint160> > spentClaimsType;
|
||||
spentClaimsType spentClaims;
|
||||
|
||||
for (unsigned int j = 0; j < tx.vin.size(); j++)
|
||||
{
|
||||
const CTxIn& txin = tx.vin[j];
|
||||
const Coin& coin = view.AccessCoin(txin.prevout);
|
||||
|
||||
int op;
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
if (DecodeClaimScript(coin.out.scriptPubKey, op, vvchParams))
|
||||
{
|
||||
if (op == OP_CLAIM_NAME || op == OP_UPDATE_CLAIM)
|
||||
{
|
||||
uint160 claimId;
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
std::string value(vvchParams[1].begin(), vvchParams[1].end());
|
||||
if (op == OP_CLAIM_NAME)
|
||||
{
|
||||
assert(vvchParams.size() == 2);
|
||||
claimId = ClaimIdHash(txin.prevout.hash, txin.prevout.n);
|
||||
LogPrintf("+++ %s[%lu]: OP_CLAIM_NAME \"%s\" = \"%s\" with claimId %s and tx prevout %s at index %d\n",
|
||||
__func__, pindex->nHeight, name, SanitizeString(value),
|
||||
claimId.GetHex(), txin.prevout.hash.GetHex(), txin.prevout.n);
|
||||
}
|
||||
else if (op == OP_UPDATE_CLAIM)
|
||||
{
|
||||
assert(vvchParams.size() == 3);
|
||||
claimId = uint160(vvchParams[1]);
|
||||
LogPrintf("+++ %s[%lu]: OP_UPDATE_CLAIM \"%s\" = \"%s\" with claimId %s and tx prevout %s at index %d\n",
|
||||
__func__, pindex->nHeight, name, SanitizeString(value),
|
||||
claimId.GetHex(), txin.prevout.hash.GetHex(), txin.prevout.n);
|
||||
}
|
||||
int nValidAtHeight;
|
||||
LogPrintf("%s: Removing %s (%s) from the claim trie. Tx: %s, nOut: %d\n",
|
||||
__func__, name, claimId.GetHex(), txin.prevout.hash.GetHex(), txin.prevout.n);
|
||||
if (trieCache.spendClaim(name, COutPoint(txin.prevout.hash, txin.prevout.n), nValidAtHeight))
|
||||
{
|
||||
mClaimUndoHeights[j] = nValidAtHeight;
|
||||
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());
|
||||
uint160 supportedClaimId(vvchParams[1]);
|
||||
LogPrintf("+++ %s[%lu]: OP_SUPPORT_CLAIM \"%s\" with claimId %s and tx prevout %s at index %d\n",
|
||||
__func__, pindex->nHeight, name,
|
||||
supportedClaimId.GetHex(), txin.prevout.hash.GetHex(), txin.prevout.n);
|
||||
int nValidAtHeight;
|
||||
LogPrintf("%s: Removing support for %s in %s. Tx: %s, nOut: %d, removed txid: %s\n",
|
||||
__func__, supportedClaimId.ToString(), name, txin.prevout.hash.ToString(),
|
||||
txin.prevout.n, tx.GetHash().ToString());
|
||||
if (trieCache.spendSupport(name, COutPoint(txin.prevout.hash, txin.prevout.n), nValidAtHeight))
|
||||
{
|
||||
mClaimUndoHeights[j] = nValidAtHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int j = 0; j < tx.vout.size(); j++)
|
||||
{
|
||||
const CTxOut& txout = tx.vout[j];
|
||||
|
||||
int op;
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
if (DecodeClaimScript(txout.scriptPubKey, op, vvchParams))
|
||||
{
|
||||
if (op == OP_CLAIM_NAME)
|
||||
{
|
||||
assert(vvchParams.size() == 2);
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
LogPrintf("%s: Inserting %s into the claim trie. Tx: %s, nOut: %d\n",
|
||||
__func__, name, tx.GetHash().GetHex(), j);
|
||||
if (!trieCache.addClaim(name, COutPoint(tx.GetHash(), j), ClaimIdHash(tx.GetHash(), j), txout.nValue, pindex->nHeight))
|
||||
{
|
||||
LogPrintf("%s: Something went wrong inserting the claim\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]);
|
||||
LogPrintf("%s: Got a claim update. Name: %s, claimId: %s, new txid: %s, nOut: %d\n",
|
||||
__func__, name, claimId.GetHex(), tx.GetHash().GetHex(), j);
|
||||
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(), j), claimId, txout.nValue, pindex->nHeight))
|
||||
{
|
||||
LogPrintf("%s: Something went wrong updating the claim\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(), j), txout.nValue, supportedClaimId, pindex->nHeight))
|
||||
{
|
||||
LogPrintf("%s: Something went wrong inserting the support\n", __func__);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CTxUndo undoDummy;
|
||||
|
@ -2046,7 +2222,43 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
|
|||
blockundo.vtxundo.push_back(CTxUndo());
|
||||
}
|
||||
UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight);
|
||||
if (i > 0 && !mClaimUndoHeights.empty())
|
||||
{
|
||||
/* std::vector<CTxInUndo>& txinUndos = blockUndo.vtxundo.back().vprevout */
|
||||
/* CTxUndo &txundo = blockUndo.vtxundo[i-1]; */
|
||||
CTxUndo& txUndo = blockundo.vtxundo.back();
|
||||
for (std::map<unsigned int, unsigned int>::iterator itHeight = mClaimUndoHeights.begin(); itHeight != mClaimUndoHeights.end(); ++itHeight)
|
||||
{
|
||||
// Note: by appearing in this map, we know it's a claim so the bool is redundant
|
||||
txUndo.claimInfo[itHeight->first] = { itHeight->second, true };
|
||||
}
|
||||
}
|
||||
// The CTxUndo vector contains the heights at which claims should be put into the trie.
|
||||
// This is necessary because some claims are inserted immediately into the trie, and
|
||||
// others are inserted after a delay, depending on the state of the claim trie at the time
|
||||
// that the claim was originally inserted into the blockchain. That state will not be
|
||||
// available when and if this block is disconnected.
|
||||
// It also contains whether or not any given txin represents a claim that should
|
||||
// be put back into the trie. If we didn't find a claim or support in the trie
|
||||
// or cache when trying to spend it, we shouldn't try to put a claim or support back
|
||||
// in. Some OP_UPDATE_CLAIM's, for example, may be invalid, and so may never have been
|
||||
// inserted into the trie in the first place.
|
||||
|
||||
vPos.push_back(std::make_pair(tx.GetHash(), pos));
|
||||
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
|
||||
}
|
||||
|
||||
const auto incremented = trieCache.incrementBlock(blockundo.insertUndo, blockundo.expireUndo, blockundo.insertSupportUndo, blockundo.expireSupportUndo, blockundo.takeoverHeightUndo);
|
||||
assert(incremented);
|
||||
|
||||
if (trieCache.getMerkleHash() != block.hashClaimTrie)
|
||||
{
|
||||
return state.DoS(100,
|
||||
error("ConnectBlock() : the merkle root of the claim trie does not match "
|
||||
"(actual=%s vs block=%s)", trieCache.getMerkleHash().GetHex(),
|
||||
block.hashClaimTrie.GetHex()), REJECT_INVALID, "bad-claim-merkle-hash");
|
||||
}
|
||||
|
||||
int64_t nTime3 = GetTimeMicros(); nTimeConnect += nTime3 - nTime2;
|
||||
LogPrint(BCLog::BENCH, " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs (%.2fms/blk)]\n", (unsigned)block.vtx.size(), MILLI * (nTime3 - nTime2), MILLI * (nTime3 - nTime2) / block.vtx.size(), nInputs <= 1 ? 0 : MILLI * (nTime3 - nTime2) / (nInputs-1), nTimeConnect * MICRO, nTimeConnect * MILLI / nBlocksTotal);
|
||||
|
||||
|
@ -2065,7 +2277,9 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
|
|||
if (fJustCheck)
|
||||
return true;
|
||||
|
||||
if (!WriteUndoDataForBlock(blockundo, state, pindex, chainparams))
|
||||
if (pindex->pprev != nullptr &&
|
||||
!WriteUndoDataForBlock(blockundo, state, pindex, chainparams) &&
|
||||
!pblocktree->WriteTxIndex(vPos))
|
||||
return false;
|
||||
|
||||
if (!pindex->IsValid(BLOCK_VALID_SCRIPTS)) {
|
||||
|
@ -2076,6 +2290,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
|
|||
assert(pindex->phashBlock);
|
||||
// add this block to the view's block chain
|
||||
view.SetBestBlock(pindex->GetBlockHash());
|
||||
trieCache.setBestBlock(pindex->GetBlockHash());
|
||||
|
||||
int64_t nTime5 = GetTimeMicros(); nTimeIndex += nTime5 - nTime4;
|
||||
LogPrint(BCLog::BENCH, " - Index writing: %.2fms [%.2fs (%.2fms/blk)]\n", MILLI * (nTime5 - nTime4), nTimeIndex * MICRO, nTimeIndex * MILLI / nBlocksTotal);
|
||||
|
@ -2182,6 +2397,8 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &
|
|||
// overwrite one. Still, use a conservative safety factor of 2.
|
||||
if (!CheckDiskSpace(48 * 2 * 2 * pcoinsTip->GetCacheSize()))
|
||||
return state.Error("out of disk space");
|
||||
if (!pclaimTrie->WriteToDisk())
|
||||
return state.Error("Failed to write to claim trie database");
|
||||
// Flush the chainstate (which may refer to block index entries).
|
||||
if (!pcoinsTip->Flush())
|
||||
return AbortNode(state, "Failed to write to coin database");
|
||||
|
@ -2312,11 +2529,14 @@ bool CChainState::DisconnectTip(CValidationState& state, const CChainParams& cha
|
|||
int64_t nStart = GetTimeMicros();
|
||||
{
|
||||
CCoinsViewCache view(pcoinsTip.get());
|
||||
CClaimTrieCache trieCache(pclaimTrie);
|
||||
assert(view.GetBestBlock() == pindexDelete->GetBlockHash());
|
||||
if (DisconnectBlock(block, pindexDelete, view) != DISCONNECT_OK)
|
||||
if (DisconnectBlock(block, pindexDelete, view, trieCache) != DISCONNECT_OK)
|
||||
return error("DisconnectTip(): DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString());
|
||||
bool flushed = view.Flush();
|
||||
assert(flushed);
|
||||
assert(trieCache.flush());
|
||||
assert(pindexDelete->pprev->hashClaimTrie == trieCache.getMerkleHash());
|
||||
}
|
||||
LogPrint(BCLog::BENCH, "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * MILLI);
|
||||
// Write the chain state to disk, if necessary.
|
||||
|
@ -2443,7 +2663,8 @@ bool CChainState::ConnectTip(CValidationState& state, const CChainParams& chainp
|
|||
LogPrint(BCLog::BENCH, " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * MILLI, nTimeReadFromDisk * MICRO);
|
||||
{
|
||||
CCoinsViewCache view(pcoinsTip.get());
|
||||
bool rv = ConnectBlock(blockConnecting, state, pindexNew, view, chainparams);
|
||||
CClaimTrieCache trieCache(pclaimTrie);
|
||||
bool rv = ConnectBlock(blockConnecting, state, pindexNew, view, trieCache, chainparams);
|
||||
GetMainSignals().BlockChecked(blockConnecting, state);
|
||||
if (!rv) {
|
||||
if (state.IsInvalid())
|
||||
|
@ -2454,6 +2675,8 @@ bool CChainState::ConnectTip(CValidationState& state, const CChainParams& chainp
|
|||
LogPrint(BCLog::BENCH, " - Connect total: %.2fms [%.2fs (%.2fms/blk)]\n", (nTime3 - nTime2) * MILLI, nTimeConnectTotal * MICRO, nTimeConnectTotal * MILLI / nBlocksTotal);
|
||||
bool flushed = view.Flush();
|
||||
assert(flushed);
|
||||
flushed = trieCache.flush();
|
||||
assert(flushed);
|
||||
}
|
||||
int64_t nTime4 = GetTimeMicros(); nTimeFlush += nTime4 - nTime3;
|
||||
LogPrint(BCLog::BENCH, " - Flush: %.2fms [%.2fs (%.2fms/blk)]\n", (nTime4 - nTime3) * MILLI, nTimeFlush * MICRO, nTimeFlush * MILLI / nBlocksTotal);
|
||||
|
@ -3079,7 +3302,7 @@ static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos,
|
|||
static bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true)
|
||||
{
|
||||
// Check proof of work matches claimed amount
|
||||
if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, consensusParams))
|
||||
if (fCheckPOW && !CheckProofOfWork(block.GetPoWHash(), block.nBits, consensusParams))
|
||||
return state.DoS(50, false, REJECT_INVALID, "high-hash", false, "proof of work failed");
|
||||
|
||||
return true;
|
||||
|
@ -3559,8 +3782,9 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons
|
|||
NotifyHeaderTip();
|
||||
|
||||
CValidationState state; // Only used to report errors, not invalidity - ignore it
|
||||
if (!g_chainstate.ActivateBestChain(state, chainparams, pblock))
|
||||
if (!g_chainstate.ActivateBestChain(state, chainparams, pblock)) {
|
||||
return error("%s: ActivateBestChain failed (%s)", __func__, FormatStateMessage(state));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -3570,6 +3794,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams,
|
|||
AssertLockHeld(cs_main);
|
||||
assert(pindexPrev && pindexPrev == chainActive.Tip());
|
||||
CCoinsViewCache viewNew(pcoinsTip.get());
|
||||
CClaimTrieCache trieCache(pclaimTrie);
|
||||
uint256 block_hash(block.GetHash());
|
||||
CBlockIndex indexDummy(block);
|
||||
indexDummy.pprev = pindexPrev;
|
||||
|
@ -3583,7 +3808,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams,
|
|||
return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state));
|
||||
if (!ContextualCheckBlock(block, state, chainparams.GetConsensus(), pindexPrev))
|
||||
return error("%s: Consensus::ContextualCheckBlock: %s", __func__, FormatStateMessage(state));
|
||||
if (!g_chainstate.ConnectBlock(block, state, &indexDummy, viewNew, chainparams, true))
|
||||
if (!g_chainstate.ConnectBlock(block, state, &indexDummy, viewNew, trieCache, chainparams, true))
|
||||
return false;
|
||||
assert(state.IsValid());
|
||||
|
||||
|
@ -3982,6 +4207,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
|
|||
nCheckLevel = std::max(0, std::min(4, nCheckLevel));
|
||||
LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
|
||||
CCoinsViewCache coins(coinsview);
|
||||
CClaimTrieCache trieCache(pclaimTrie);
|
||||
CBlockIndex* pindex;
|
||||
CBlockIndex* pindexFailure = nullptr;
|
||||
int nGoodTransactions = 0;
|
||||
|
@ -4024,7 +4250,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
|
|||
// check level 3: check for inconsistencies during memory-only disconnect of tip blocks
|
||||
if (nCheckLevel >= 3 && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) {
|
||||
assert(coins.GetBestBlock() == pindex->GetBlockHash());
|
||||
DisconnectResult res = g_chainstate.DisconnectBlock(block, pindex, coins);
|
||||
DisconnectResult res = g_chainstate.DisconnectBlock(block, pindex, coins, trieCache);
|
||||
if (res == DISCONNECT_FAILED) {
|
||||
return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
|
||||
}
|
||||
|
@ -4053,7 +4279,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
|
|||
CBlock block;
|
||||
if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus()))
|
||||
return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
|
||||
if (!g_chainstate.ConnectBlock(block, state, pindex, coins, chainparams))
|
||||
if (!g_chainstate.ConnectBlock(block, state, pindex, coins, trieCache, chainparams))
|
||||
return error("VerifyDB(): *** found unconnectable block at %d, hash=%s (%s)", pindex->nHeight, pindex->GetBlockHash().ToString(), FormatStateMessage(state));
|
||||
}
|
||||
}
|
||||
|
@ -4090,6 +4316,7 @@ bool CChainState::ReplayBlocks(const CChainParams& params, CCoinsView* view)
|
|||
LOCK(cs_main);
|
||||
|
||||
CCoinsViewCache cache(view);
|
||||
CClaimTrieCache trieCache(pclaimTrie);
|
||||
|
||||
std::vector<uint256> hashHeads = view->GetHeadBlocks();
|
||||
if (hashHeads.empty()) return true; // We're already in a consistent state.
|
||||
|
@ -4124,7 +4351,7 @@ bool CChainState::ReplayBlocks(const CChainParams& params, CCoinsView* view)
|
|||
return error("RollbackBlock(): ReadBlockFromDisk() failed at %d, hash=%s", pindexOld->nHeight, pindexOld->GetBlockHash().ToString());
|
||||
}
|
||||
LogPrintf("Rolling back %s (%i)\n", pindexOld->GetBlockHash().ToString(), pindexOld->nHeight);
|
||||
DisconnectResult res = DisconnectBlock(block, pindexOld, cache);
|
||||
DisconnectResult res = DisconnectBlock(block, pindexOld, cache, trieCache);
|
||||
if (res == DISCONNECT_FAILED) {
|
||||
return error("RollbackBlock(): DisconnectBlock failed at %d, hash=%s", pindexOld->nHeight, pindexOld->GetBlockHash().ToString());
|
||||
}
|
||||
|
@ -4145,7 +4372,9 @@ bool CChainState::ReplayBlocks(const CChainParams& params, CCoinsView* view)
|
|||
}
|
||||
|
||||
cache.SetBestBlock(pindexNew->GetBlockHash());
|
||||
trieCache.setBestBlock(pindexNew->GetBlockHash());
|
||||
cache.Flush();
|
||||
trieCache.flush();
|
||||
uiInterface.ShowProgress("", 100, false);
|
||||
return true;
|
||||
}
|
||||
|
|
174
src/validation.h
174
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;
|
||||
|
@ -349,6 +355,170 @@ 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 & RPC usage
|
||||
* BEGIN
|
||||
************************************************************/
|
||||
|
||||
/**
|
||||
* Global state
|
||||
*/
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
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 & RPC usage
|
||||
* END
|
||||
************************************************************/
|
||||
|
||||
/**
|
||||
* Closure representing one script verification
|
||||
* Note that this stores references to the spending transaction
|
||||
|
@ -460,9 +630,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)
|
||||
|
|
|
@ -52,7 +52,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
|
|||
WalletRescanReserver reserver(&wallet);
|
||||
reserver.reserve();
|
||||
BOOST_CHECK_EQUAL(nullBlock, wallet.ScanForWalletTransactions(oldTip, nullptr, reserver));
|
||||
BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 100 * COIN);
|
||||
BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 2 * COIN);
|
||||
}
|
||||
|
||||
// Prune the older block file.
|
||||
|
@ -67,7 +67,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
|
|||
WalletRescanReserver reserver(&wallet);
|
||||
reserver.reserve();
|
||||
BOOST_CHECK_EQUAL(oldTip, wallet.ScanForWalletTransactions(oldTip, nullptr, reserver));
|
||||
BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 50 * COIN);
|
||||
BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 1 * COIN);
|
||||
}
|
||||
|
||||
// Verify importmulti RPC returns failure for a key whose creation time is
|
||||
|
@ -195,7 +195,7 @@ BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
|
|||
// credit amount is calculated.
|
||||
wtx.MarkDirty();
|
||||
wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
|
||||
BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(), 50*COIN);
|
||||
BOOST_CHECK_EQUAL(wtx.GetImmatureCredit(), 1 * COIN);
|
||||
}
|
||||
|
||||
static int64_t AddTx(CWallet& wallet, uint32_t lockTime, int64_t mockTime, int64_t blockTime)
|
||||
|
@ -327,13 +327,13 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
|
|||
BOOST_CHECK_EQUAL(list.begin()->second.size(), 1U);
|
||||
|
||||
// Check initial balance from one mature coinbase transaction.
|
||||
BOOST_CHECK_EQUAL(50 * COIN, wallet->GetAvailableBalance());
|
||||
BOOST_CHECK_EQUAL(1 * COIN, wallet->GetAvailableBalance());
|
||||
|
||||
// Add a transaction creating a change address, and confirm ListCoins still
|
||||
// returns the coin associated with the change address underneath the
|
||||
// coinbaseKey pubkey, even though the change address has a different
|
||||
// pubkey.
|
||||
AddTx(CRecipient{GetScriptForRawPubKey({}), 1 * COIN, false /* subtract fee */});
|
||||
AddTx(CRecipient{GetScriptForRawPubKey({}), 10 * CENT, false /* subtract fee */});
|
||||
list = wallet->ListCoins();
|
||||
BOOST_CHECK_EQUAL(list.size(), 1U);
|
||||
BOOST_CHECK_EQUAL(boost::get<CKeyID>(list.begin()->first).ToString(), coinbaseAddress);
|
||||
|
|
Loading…
Add table
Reference in a new issue
don't change it now, but we should have come up with something creative for this