Compare commits
3 commits
master
...
cache_nth_
Author | SHA1 | Date | |
---|---|---|---|
|
d9e83ba216 | ||
|
c309f811c1 | ||
|
fbf7de9fb2 |
90 changed files with 3606 additions and 7570 deletions
8
.github/ISSUE_TEMPLATE.md
vendored
8
.github/ISSUE_TEMPLATE.md
vendored
|
@ -1,8 +1,8 @@
|
|||
<!-- This issue tracker is only for technical issues related to lbrycrd (the LBRY blockchain).
|
||||
<!-- This issue tracker is only for technical issues related to Bitcoin Core.
|
||||
|
||||
General questions and/or support requests are best directed to the community chat at https://chat.lbry.org.
|
||||
General bitcoin questions and/or support requests are best directed to the Bitcoin StackExchange at https://bitcoin.stackexchange.com.
|
||||
|
||||
For reporting security issues, please email security@lbry.com.
|
||||
For reporting security issues, please read instructions at https://bitcoincore.org/en/contact/.
|
||||
|
||||
If the node is "stuck" during sync or giving "block checksum mismatch" errors, please ensure your hardware is stable by running memtest and observe CPU temperature with a load-test tool such as linpack before creating an issue! -->
|
||||
|
||||
|
@ -13,7 +13,7 @@ If the node is "stuck" during sync or giving "block checksum mismatch" errors, p
|
|||
|
||||
<!--- How reliably can you reproduce the issue, what are the steps to do so? -->
|
||||
|
||||
<!-- What version of lbrycrd are you using, where did you get it (website, self-compiled, etc)? -->
|
||||
<!-- What version of Bitcoin Core are you using, where did you get it (website, self-compiled, etc)? -->
|
||||
|
||||
<!-- What type of machine are you observing the error on (OS/CPU and disk type)? -->
|
||||
|
||||
|
|
25
.travis.yml
25
.travis.yml
|
@ -7,6 +7,7 @@ cache:
|
|||
stages:
|
||||
- build
|
||||
- test
|
||||
- quality
|
||||
|
||||
jobs:
|
||||
include:
|
||||
|
@ -14,7 +15,7 @@ jobs:
|
|||
- &build-template
|
||||
stage: build
|
||||
name: linux
|
||||
env: NAME=linux DOCKER_IMAGE=lbry/build_lbrycrd_gcc EXT=
|
||||
env: NAME=linux EXT=
|
||||
os: linux
|
||||
dist: xenial
|
||||
language: minimal
|
||||
|
@ -22,9 +23,8 @@ jobs:
|
|||
- docker
|
||||
install:
|
||||
- mkdir -p ${HOME}/ccache
|
||||
- docker pull $DOCKER_IMAGE
|
||||
- docker pull $DOCKER_BUILD_IMAGE
|
||||
script:
|
||||
- echo "build..."
|
||||
- docker run -v "$(pwd):/lbrycrd" -v "${HOME}/ccache:/ccache" -w /lbrycrd -e CCACHE_DIR=/ccache ${DOCKER_IMAGE} packaging/build_${NAME}_64bit.sh
|
||||
before_deploy:
|
||||
- mkdir -p dist
|
||||
|
@ -48,11 +48,11 @@ jobs:
|
|||
|
||||
- <<: *build-template
|
||||
name: windows
|
||||
env: NAME=windows DOCKER_IMAGE=lbry/build_lbrycrd EXT=.exe
|
||||
env: NAME=windows EXT=.exe
|
||||
|
||||
- <<: *build-template
|
||||
name: osx
|
||||
env: NAME=darwin DOCKER_IMAGE=lbry/build_lbrycrd EXT=
|
||||
env: NAME=darwin EXT=
|
||||
before_install:
|
||||
- mkdir -p ./depends/SDKs && pushd depends/SDKs && curl -C - ${MAC_OS_SDK} | tar --skip-old-files -xJ && popd
|
||||
|
||||
|
@ -63,7 +63,7 @@ jobs:
|
|||
dist: xenial
|
||||
language: minimal
|
||||
git:
|
||||
clone: false
|
||||
depth: 3
|
||||
install:
|
||||
- mkdir -p testrun && cd testrun
|
||||
- curl http://build.lbry.io/lbrycrd/${TRAVIS_BRANCH}/lbrycrd-${NAME}-test.zip -o temp.zip
|
||||
|
@ -78,11 +78,20 @@ jobs:
|
|||
services:
|
||||
- docker
|
||||
script:
|
||||
- docker pull lbry/wine
|
||||
- docker run -v "$(pwd):/test" -e "WINEDEBUG=-all" -e "TRIEHASH_FUZZER_BLOCKS=1000" -it lbry/wine wine "/test/test_lbrycrd.exe"
|
||||
- docker pull $DOCKER_WINE_IMAGE
|
||||
- docker run -v "$(pwd):/test" -e "WINEDEBUG=-all" -e "TRIEHASH_FUZZER_BLOCKS=1000" -it $DOCKER_WINE_IMAGE wine "/test/test_lbrycrd.exe"
|
||||
|
||||
- <<: *test-template
|
||||
os: osx
|
||||
osx_image: xcode8.3
|
||||
env: NAME=darwin
|
||||
|
||||
|
||||
- stage: quality
|
||||
name: "check format"
|
||||
os: linux
|
||||
dist: xenial
|
||||
language: minimal
|
||||
install:
|
||||
- sudo apt-get install -y clang-format-3.9
|
||||
script: git diff -U0 origin/master -- '*.h' '*.cpp' | ./contrib/devtools/clang-format-diff.py -p1
|
||||
|
|
113
README.md
113
README.md
|
@ -1,35 +1,14 @@
|
|||
# LBRYcrd - The LBRY blockchain
|
||||
|
||||
[![Build Status](https://travis-ci.org/lbryio/lbrycrd.svg?branch=master)](https://travis-ci.org/lbryio/lbrycrd)
|
||||
[![MIT licensed](https://img.shields.io/dub/l/vibe-d.svg?style=flat)](https://github.com/lbryio/lbry-desktop/blob/master/LICENSE)
|
||||
|
||||
LBRYcrd uses a blockchain similar to bitcoin's to implement an index and payment system for content on the LBRY network. It is a fork of [bitcoin core](https://github.com/bitcoin/bitcoin). In addition to the libraries used by bitcoin, LBRYcrd also uses [icu4c](https://github.com/unicode-org/icu/tree/master/icu4c).
|
||||
LBRYcrd uses a blockchain similar to bitcoin's to implement an index and payment system for content on the LBRY network. It is a fork of bitcoin core. In addition to the libraries used by bitcoin, LBRYcrd also uses icu4c.
|
||||
|
||||
Please read the [lbry.tech overview](https://lbry.tech/overview) for a general understanding of the LBRY pieces. From there you could read the [LBRY spec](https://spec.lbry.com/) for specifics on the data in the blockchain.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Installation](#installation)
|
||||
2. [Usage](#usage)
|
||||
1. [Examples](#examples)
|
||||
2. [Data directory](#data-directory)
|
||||
3. [Running from Source](#running-from-source)
|
||||
1. [Ubuntu with pulled static dependencies](#ubuntu-with-pulled-static-dependencies)
|
||||
2. [Ubuntu with local shared dependencies](#ubuntu-with-local-shared-dependencies)
|
||||
3. [MacOS (cross-compiled)](<#macos-(cross-compiled)>)
|
||||
4. [MacOS with local shared dependencies](#macos-with-local-shared-dependencies)
|
||||
5. [Windows (cross-compiled)](<#windows-(cross-compiled)>)
|
||||
6. [Use with CLion](#use-with-clion)
|
||||
4. [Contributing](#contributing)
|
||||
- [Testnet](#testnet)
|
||||
5. [Mailing List](#mailing-list)
|
||||
6. [License](#license)
|
||||
7. [Security](#security)
|
||||
8. [Contact](#contact)
|
||||
Please read the [lbry.tech overview](https://lbry.tech/overview) for a general understanding of the LBRY pieces. From there you could read the [LBRY spec](https://spec.lbry.com/) for specifics on the data in the blockchain.
|
||||
|
||||
## Installation
|
||||
|
||||
Latest binaries are available from https://github.com/lbryio/lbrycrd/releases. There is no installation procedure; the CLI binaries will run as-is and will have any uncommon dependencies statically linked into the binary. The QT GUI is not supported. LBRYcrd is distributed as a collection of executable files; traditional installers are not provided.
|
||||
Latest binaries are available from https://github.com/lbryio/lbrycrd/releases. There is no installation procedure; the CLI binaries will run as-is and will have any uncommon dependencies statically linked into the binary. The QT GUI is not supported. LBRYcrd is distributed as a collection of executable files; traditional installers are not provided.
|
||||
|
||||
## Usage
|
||||
|
||||
|
@ -37,7 +16,7 @@ The `lbrycrdd` executable will start a LBRYcrd node and connect you to the LBRYc
|
|||
to interact with lbrycrdd through the command line. Command-line help for both executables are available through
|
||||
the "--help" flag (e.g. `lbrycrdd --help`). Examples:
|
||||
|
||||
#### Examples
|
||||
#### Examples:
|
||||
|
||||
Run `./lbrycrdd -server -daemon` to start lbrycrdd in the background.
|
||||
|
||||
|
@ -46,8 +25,7 @@ Run `./lbrycrd-cli -getinfo` to check for some basic information about your LBRY
|
|||
Run `./lbrycrd-cli help` to get a list of all commands that you can run. To get help on specific commands run `./lbrycrd-cli [command_name] help`
|
||||
|
||||
Test locally:
|
||||
|
||||
```sh
|
||||
```
|
||||
./lbrycrdd -server -regtest -txindex # run this in its own window
|
||||
./lbrycrd-cli -regtest generate 120 # mine 20 spendable coins
|
||||
./lbrycrd-cli -regtest claimname my_name deadbeef 1 # hold a name claim with 1 coin
|
||||
|
@ -57,26 +35,24 @@ Test locally:
|
|||
./lbrycrd-cli -regtest stop # kill lbrycrdd
|
||||
rm -fr ~/.lbrycrd/regtest/ # destroy regtest data
|
||||
```
|
||||
|
||||
For further understanding of a "regtest" setup, see the local stack setup instructions here: https://lbry.tech/resources/regtest-setup
|
||||
|
||||
The CLI help is also browsable online at https://lbry.tech/api/blockchain
|
||||
|
||||
#### Data directory
|
||||
#### Data directory:
|
||||
|
||||
Lbrycrdd will use the below default data directories (changeable with -datadir):
|
||||
|
||||
```sh
|
||||
```
|
||||
Windows: %APPDATA%\lbrycrd
|
||||
Mac: ~/Library/Application Support/lbrycrd
|
||||
Unix: ~/.lbrycrd
|
||||
```
|
||||
|
||||
The data directory contains various things such as your default wallet (wallet.dat), debug logs (debug.log), and blockchain data. You can optionally create a configuration file lbrycrd.conf in the default data directory which will be used by default when running lbrycrdd.
|
||||
|
||||
For a list of configuration parameters, run `./lbrycrdd --help`. Below is a sample lbrycrd.conf to enable JSON RPC server on lbrycrdd.
|
||||
|
||||
```sh
|
||||
```
|
||||
rpcuser=lbry
|
||||
rpcpassword=xyz123456790
|
||||
daemon=1
|
||||
|
@ -85,19 +61,15 @@ txindex=1
|
|||
```
|
||||
|
||||
## Running from Source
|
||||
|
||||
The easiest way to compile is to utilize the Docker image that contains the necessary compilers: lbry/build_lbrycrd. This will allow you to reproduce the build as made on our build servers. In this sample we map a local lbrycrd folder and a local ccache folder inside the image:
|
||||
```sh
|
||||
The easiest way to compile is to utilize the Docker image that contains the necessary compilers: lbry/build_lbrycrd. This will allow you to reproduce the build as made on our build servers. I this sample we map a local lbrycrd folder and a local ccache folder inside the image:
|
||||
```
|
||||
git clone https://github.com/lbryio/lbrycrd.git
|
||||
cd lbrycrd
|
||||
docker run -v "$(pwd):/lbrycrd" --rm -v "${HOME}/ccache:/ccache" -w /lbrycrd -e CCACHE_DIR=/ccache lbry/build_lbrycrd packaging/build_linux_64bit.sh
|
||||
```
|
||||
|
||||
Some examples of compiling directly:
|
||||
|
||||
#### Ubuntu with pulled static dependencies
|
||||
|
||||
```sh
|
||||
#### Ubuntu with pulled static dependencies:
|
||||
```
|
||||
sudo apt install build-essential git libtool autotools-dev automake pkg-config bsdmainutils curl ca-certificates
|
||||
git clone https://github.com/lbryio/lbrycrd.git
|
||||
cd lbrycrd
|
||||
|
@ -105,20 +77,16 @@ cd lbrycrd
|
|||
./src/test/test_lbrycrd
|
||||
|
||||
```
|
||||
|
||||
Other Linux distros would be similar. The build shell script is fairly trivial; take a peek at its contents.
|
||||
|
||||
#### Ubuntu with local shared dependencies
|
||||
|
||||
#### Ubuntu with local shared dependencies:
|
||||
Note: using untested dependencies may lead to conflicting results.
|
||||
|
||||
```sh
|
||||
```
|
||||
sudo add-apt-repository ppa:bitcoin/bitcoin
|
||||
sudo apt-get update
|
||||
sudo apt-get install libdb4.8-dev libdb4.8++-dev libicu-dev libssl-dev libevent-dev \
|
||||
sudo apt-get install libdb4.8-dev libdb4.8++-dev libicu-dev libssl-dev libevent-dev \
|
||||
build-essential git libtool autotools-dev automake pkg-config bsdmainutils curl ca-certificates \
|
||||
libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev
|
||||
|
||||
|
||||
# optionally include libminiupnpc-dev libzmq3-dev
|
||||
|
||||
git clone https://github.com/lbryio/lbrycrd.git
|
||||
|
@ -129,13 +97,11 @@ make -j$(nproc)
|
|||
./src/lbrycrdd -server ...
|
||||
|
||||
```
|
||||
|
||||
#### MacOS (cross-compiled)
|
||||
|
||||
```sh
|
||||
#### MacOS (cross-compiled):
|
||||
```
|
||||
sudo apt-get install clang llvm git libtool autotools-dev automake pkg-config bsdmainutils curl ca-certificates \
|
||||
libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev
|
||||
|
||||
|
||||
git clone https://github.com/lbryio/lbrycrd.git
|
||||
cd lbrycrd
|
||||
# download MacOS SDK from your favorite source
|
||||
|
@ -144,12 +110,9 @@ tar ... extract SDK to depends/SDKs/MacOSX10.11.sdk
|
|||
./packaging/build_darwin_64bit.sh
|
||||
|
||||
```
|
||||
|
||||
Look in packaging/build_darwin_64bit.sh for further understanding.
|
||||
|
||||
#### MacOS with local shared dependencies
|
||||
|
||||
```sh
|
||||
#### MacOS with local shared dependencies:
|
||||
```
|
||||
brew install boost berkeley-db@4 icu4c libevent
|
||||
# fix conflict with gawk pulled first:
|
||||
brew reinstall readline
|
||||
|
@ -164,17 +127,14 @@ CONFIG_SITE=$(pwd)/depends/x86_64-apple-darwin15.6.0/share/config.site ./configu
|
|||
make -j$(sysctl -n hw.ncpu)
|
||||
|
||||
```
|
||||
|
||||
#### Windows (cross-compiled)
|
||||
|
||||
#### Windows (cross-compiled):
|
||||
Compiling on MS Windows (outside of WSL) is not supported. The Windows build is cross-compiled from Linux like so:
|
||||
|
||||
```sh
|
||||
```
|
||||
sudo apt-get install build-essential git libtool autotools-dev automake pkg-config bsdmainutils curl ca-certificates \
|
||||
g++-mingw-w64-x86-64 mingw-w64-x86-64-dev
|
||||
|
||||
|
||||
update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix
|
||||
|
||||
|
||||
git clone https://github.com/lbryio/lbrycrd.git
|
||||
cd lbrycrd
|
||||
./packaging/build_windows_64bit.sh
|
||||
|
@ -183,16 +143,13 @@ cd lbrycrd
|
|||
|
||||
If you encounter any errors, please check `doc/build-*.md` for further instructions. If you're still stuck, [create an issue](https://github.com/lbryio/lbrycrd/issues/new) with the output of that command, your system info, and any other information you think might be helpful. The scripts in the packaging folder are simple and will grant extra light on the build process as needed.
|
||||
|
||||
#### Use with CLion
|
||||
|
||||
#### Use with CLion:
|
||||
CLion has not traditionally supported Autotools projects, although some progress on that is now in the works. We do include a cmake build file for compiling lbrycrd. See contrib/cmake. Alas, CLion doesn't support external projects in cmake, so that particular approach is also insufficient. CLion does support "compile_commands.json" projects. Fortunately, this can be easily generated for lbrycrd like so:
|
||||
|
||||
```sh
|
||||
```
|
||||
pip install --user compiledb
|
||||
./autogen.sh && ./configure --enable-static=no --enable-shared --with-pic --without-gui CXXFLAGS="-O0 -g" CFLAGS="-O0 -g" # or whatever normal lbrycrd config
|
||||
compiledb make -j10
|
||||
```
|
||||
|
||||
Then open the newly generated compile_commands.json file as a project in CLion. Debugging is supported if you compiled with `-g`. To enable that you will need to create a target in CLion by going to File -> Settings -> Build -> Custom Build Targets. Add an empty target with your choice of name. From there you can go to "Edit Configurations", typically found in a drop-down at the top of the editor. Add a Custom Build Application, select your new target, select the compiled file (i.e. test_lbrycrd or lbrycrdd, etc), and then add any necessary command line parameters. Ensure that there is nothing in the "Before launch" section.
|
||||
|
||||
## Contributing
|
||||
|
@ -210,8 +167,8 @@ regularly to indicate new official, stable release versions.
|
|||
Testing and code review is the bottleneck for development; we get more pull
|
||||
requests than we can review and test on short notice. Please be patient and help out by testing
|
||||
other people's pull requests, and remember this is a security-critical project where any mistake might cost people
|
||||
lots of money. Developers are strongly encouraged to write [unit tests](/src/test/README.md) for new code and to
|
||||
submit new unit tests for old code. Unit tests are compiled by default and can be run with `src/test/test_lbrycrd`
|
||||
lots of money. Developers are strongly encouraged to write [unit tests](/doc/unit-tests.md) for new code and to
|
||||
submit new unit tests for old code. Unit tests are compiled by default and can be run with `src/test/test_lbrycrd`.
|
||||
|
||||
The Travis CI system makes sure that every pull request is built, and that unit and sanity tests are automatically run. See https://travis-ci.org/lbryio/lbrycrd
|
||||
|
||||
|
@ -219,11 +176,7 @@ The Travis CI system makes sure that every pull request is built, and that unit
|
|||
|
||||
Testnet is maintained for testing purposes and can be accessed using the command `./lbrycrdd -testnet`. If you would like to obtain testnet credits, please contact brannon@lbry.com or grin@lbry.com .
|
||||
|
||||
It is easy to solo mine on testnet. (It's easy on mainnet too, but much harder to win.) For instructions see [SGMiner](https://github.com/lbryio/sgminer-gm) and [Mining Contributions](https://github.com/lbryio/lbrycrd/tree/master/contrib/mining)
|
||||
|
||||
## Mailing List
|
||||
|
||||
We maintain a mailing list for notifications of upgrades, security issues, and soft/hard forks. To join, visit [https://lbry.com/forklist](https://lbry.com/forklist).
|
||||
It is easy to solo mine on testnet. (It's easy on mainnet too, but much harder to win.) For instructions see https://github.com/lbryio/sgminer-gm and https://github.com/lbryio/lbrycrd/tree/master/contrib/mining
|
||||
|
||||
## License
|
||||
|
||||
|
@ -231,9 +184,11 @@ This project is MIT licensed. For the full license, see [LICENSE](LICENSE).
|
|||
|
||||
## Security
|
||||
|
||||
We take security seriously. Please contact [security@lbry.com](mailto:security@lbry.com) regarding any security issues.
|
||||
Our PGP key is [here](https://lbry.com/faq/pgp-key) if you need it.
|
||||
We take security seriously. Please contact security@lbry.com regarding any security issues.
|
||||
Our PGP key is [here](https://keybase.io/lbry/key.asc) if you need it.
|
||||
|
||||
## Contact
|
||||
|
||||
The primary contact for this project is [@BrannonKing](https://github.com/BrannonKing) (brannon@lbry.com)
|
||||
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ export LC_ALL=C
|
|||
set -e
|
||||
srcdir="$(dirname $0)"
|
||||
cd "$srcdir"
|
||||
if [ -z ${LIBTOOLIZE} ] && GLIBTOOLIZE="$(which glibtoolize 2>/dev/null)"; then
|
||||
if [ -z ${LIBTOOLIZE} ] && GLIBTOOLIZE="`which glibtoolize 2>/dev/null`"; then
|
||||
LIBTOOLIZE="${GLIBTOOLIZE}"
|
||||
export LIBTOOLIZE
|
||||
fi
|
||||
|
|
|
@ -2,10 +2,10 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
|
|||
AC_PREREQ([2.60])
|
||||
define(_CLIENT_VERSION_MAJOR, 0)
|
||||
define(_CLIENT_VERSION_MINOR, 17)
|
||||
define(_CLIENT_VERSION_REVISION, 3)
|
||||
define(_CLIENT_VERSION_BUILD, 3)
|
||||
define(_CLIENT_VERSION_REVISION, 2)
|
||||
define(_CLIENT_VERSION_BUILD, 1)
|
||||
define(_CLIENT_VERSION_IS_RELEASE, true)
|
||||
define(_COPYRIGHT_YEAR, 2021)
|
||||
define(_COPYRIGHT_YEAR, 2019)
|
||||
define(_COPYRIGHT_HOLDERS,[The %s developers])
|
||||
define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[LBRYcrd Core]])
|
||||
AC_INIT([LBRYcrd Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[https://github.com/lbryio/lbrycrd/issues],[lbrycrd],[https://lbry.com/])
|
||||
|
|
|
@ -36,13 +36,13 @@ if [ -z "${CODESIGN_ALLOCATE}" ]; then
|
|||
fi
|
||||
|
||||
find ${TEMPDIR} -name "*.sign" | while read i; do
|
||||
SIZE=$(stat -c %s "${i}")
|
||||
TARGET_FILE="$(echo "${i}" | sed 's/\.sign$//')"
|
||||
SIZE=`stat -c %s "${i}"`
|
||||
TARGET_FILE="`echo "${i}" | sed 's/\.sign$//'`"
|
||||
|
||||
echo "Allocating space for the signature of size ${SIZE} in ${TARGET_FILE}"
|
||||
${CODESIGN_ALLOCATE} -i "${TARGET_FILE}" -a ${ARCH} ${SIZE} -o "${i}.tmp"
|
||||
|
||||
OFFSET=$(${PAGESTUFF} "${i}.tmp" -p | tail -2 | grep offset | sed 's/[^0-9]*//g')
|
||||
OFFSET=`${PAGESTUFF} "${i}.tmp" -p | tail -2 | grep offset | sed 's/[^0-9]*//g'`
|
||||
if [ -z ${QUIET} ]; then
|
||||
echo "Attaching signature at offset ${OFFSET}"
|
||||
fi
|
||||
|
|
|
@ -27,19 +27,19 @@ ${CODESIGN} -f --file-list ${TEMPLIST} "$@" "${BUNDLE}"
|
|||
|
||||
grep -v CodeResources < "${TEMPLIST}" | while read i; do
|
||||
TARGETFILE="${BUNDLE}/`echo "${i}" | sed "s|.*${BUNDLE}/||"`"
|
||||
SIZE=$(pagestuff "$i" -p | tail -2 | grep size | sed 's/[^0-9]*//g')
|
||||
OFFSET=$(pagestuff "$i" -p | tail -2 | grep offset | sed 's/[^0-9]*//g')
|
||||
SIZE=`pagestuff "$i" -p | tail -2 | grep size | sed 's/[^0-9]*//g'`
|
||||
OFFSET=`pagestuff "$i" -p | tail -2 | grep offset | sed 's/[^0-9]*//g'`
|
||||
SIGNFILE="${TEMPDIR}/${OUTROOT}/${TARGETFILE}.sign"
|
||||
DIRNAME="$(dirname "${SIGNFILE}")"
|
||||
DIRNAME="`dirname "${SIGNFILE}"`"
|
||||
mkdir -p "${DIRNAME}"
|
||||
echo "Adding detached signature for: ${TARGETFILE}. Size: ${SIZE}. Offset: ${OFFSET}"
|
||||
dd if="$i" of="${SIGNFILE}" bs=1 skip=${OFFSET} count=${SIZE} 2>/dev/null
|
||||
done
|
||||
|
||||
grep CodeResources < "${TEMPLIST}" | while read i; do
|
||||
TARGETFILE="${BUNDLE}/$(echo "${i}" | sed "s|.*${BUNDLE}/||")"
|
||||
TARGETFILE="${BUNDLE}/`echo "${i}" | sed "s|.*${BUNDLE}/||"`"
|
||||
RESOURCE="${TEMPDIR}/${OUTROOT}/${TARGETFILE}"
|
||||
DIRNAME="$(dirname "${RESOURCE}")"
|
||||
DIRNAME="`dirname "${RESOURCE}"`"
|
||||
mkdir -p "${DIRNAME}"
|
||||
echo "Adding resource for: \"${TARGETFILE}\""
|
||||
cp "${i}" "${RESOURCE}"
|
||||
|
|
|
@ -36,7 +36,7 @@ insert into coins(name, symbol, symbol2, algo, enable, auto_ready, rpcuser, rpcp
|
|||
values('Local LBRY Instance', 'LBC', 'LBC', 'lbry', 1, 1, 'ruser', 'rpswd', '127.0.0.1', 19245, 1, 'utf-8', 0, 1, 0, 0, 0);
|
||||
exit
|
||||
```
|
||||
Use port 19245 for testnet, port 9245 for main. Set usesegwit to 1 after the segwit fork is enabled on December 11, 2019.
|
||||
Use port 19245 for testnet, port 9245 for main.
|
||||
#### 3. Run the stratum server:
|
||||
```
|
||||
docker run --network host -d lbry/yiimp_stratum
|
||||
|
@ -47,11 +47,10 @@ docker run --network host -it lbry/yiimp_stratum bash
|
|||
cat config/lbry.conf
|
||||
./stratum config/lbry
|
||||
```
|
||||
When testing with an ASIC you may need to modify the TCP server address in said lbry.conf file to be an external IP address.
|
||||
|
||||
#### 4. Connect sgminer to it:
|
||||
```
|
||||
sgminer -k lbry -o stratum+tcp://127.0.0.1:3334/ -D -T -O mn824Su1wX7ip8WcNYzXwwWqvBvkeWGRo6:x
|
||||
```
|
||||
The username there is the account to receive payments from the pool. The password is unused. Tested with https://github.com/lbryio/sgminer-gm.
|
||||
You can use whatever miner you prefer.
|
||||
You can use whatever miner you prefer.
|
|
@ -23,7 +23,7 @@ TIMESERVER=http://timestamp.comodoca.com
|
|||
CERTFILE="win-codesign.cert"
|
||||
|
||||
mkdir -p "${OUTSUBDIR}"
|
||||
basename -a $(ls -1 "${SRCDIR}"/*-unsigned.exe) | while read UNSIGNED; do
|
||||
basename -a `ls -1 "${SRCDIR}"/*-unsigned.exe` | while read UNSIGNED; do
|
||||
echo Signing "${UNSIGNED}"
|
||||
"${OSSLSIGNCODE}" sign -certs "${CERTFILE}" -t "${TIMESERVER}" -in "${SRCDIR}/${UNSIGNED}" -out "${WORKDIR}/${UNSIGNED}" "$@"
|
||||
"${OSSLSIGNCODE}" extract-signature -pem -in "${WORKDIR}/${UNSIGNED}" -out "${OUTSUBDIR}/${UNSIGNED}.pem" && rm "${WORKDIR}/${UNSIGNED}"
|
||||
|
|
|
@ -131,7 +131,7 @@ $(host_prefix)/share/config.site : config.site.in $(host_prefix)/.stamp_$(final_
|
|||
-e 's|@build_os@|$(build_os)|' \
|
||||
-e 's|@host_os@|$(host_os)|' \
|
||||
-e 's|@CFLAGS@|$(strip $(host_CFLAGS) $(host_$(release_type)_CFLAGS))|' \
|
||||
-e 's|@CXXFLAGS@|$(strip -pipe $(host_$(release_type)_CXXFLAGS))|' \
|
||||
-e 's|@CXXFLAGS@|$(strip $(host_CXXFLAGS) $(host_$(release_type)_CXXFLAGS))|' \
|
||||
-e 's|@CPPFLAGS@|$(strip $(host_CPPFLAGS) $(host_$(release_type)_CPPFLAGS))|' \
|
||||
-e 's|@LDFLAGS@|$(strip $(host_LDFLAGS) $(host_$(release_type)_LDFLAGS))|' \
|
||||
-e 's|@allow_host_packages@|$(ALLOW_HOST_PACKAGES)|' \
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -7,13 +7,12 @@ darwin_CC=clang -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) -isysroo
|
|||
darwin_CXX=clang++ -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) -isysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) -stdlib=libc++ -B $(host_prefix)/native/bin
|
||||
|
||||
darwin_CFLAGS=-pipe
|
||||
darwin_CXXFLAGS=$(darwin_CFLAGS) -std=c++11
|
||||
darwin_CXXFLAGS=$(darwin_CFLAGS)
|
||||
|
||||
darwin_release_CFLAGS=-O2 -g
|
||||
darwin_release_CFLAGS=-O2
|
||||
darwin_release_CXXFLAGS=$(darwin_release_CFLAGS)
|
||||
|
||||
darwin_debug_CFLAGS=-Og -g
|
||||
darwin_debug_CXXFLAGS=-O0 -g
|
||||
|
||||
darwin_native_toolchain=native_cctools
|
||||
darwin_debug_CFLAGS=-Og
|
||||
darwin_debug_CXXFLAGS=$(darwin_debug_CFLAGS)
|
||||
|
||||
darwin_native_toolchain=native_cctools
|
|
@ -1,14 +1,11 @@
|
|||
linux_CFLAGS=-pipe
|
||||
linux_CXXFLAGS=$(linux_CFLAGS) -std=c++11
|
||||
linux_CXXFLAGS=$(linux_CFLAGS)
|
||||
|
||||
linux_release_CFLAGS=-O3 -g
|
||||
ifeq (1,$(shell ldd --version | head -1 | awk '{print $$NF < 2.28}'))
|
||||
linux_release_CFLAGS+= -include $(BASEDIR)/glibc_version_header/force_link_glibc_2.19.h
|
||||
endif
|
||||
linux_release_CFLAGS=-O2
|
||||
linux_release_CXXFLAGS=$(linux_release_CFLAGS)
|
||||
|
||||
linux_debug_CFLAGS=-O1 -g
|
||||
linux_debug_CXXFLAGS=-O0 -g
|
||||
linux_debug_CFLAGS=-Og
|
||||
linux_debug_CXXFLAGS=$(linux_debug_CFLAGS)
|
||||
|
||||
linux_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
mingw32_CFLAGS=-pipe
|
||||
mingw32_CXXFLAGS=$(mingw32_CFLAGS) -std=c++11
|
||||
mingw32_CXXFLAGS=$(mingw32_CFLAGS)
|
||||
|
||||
mingw32_release_CFLAGS=-O2 -g
|
||||
mingw32_release_CFLAGS=-O2
|
||||
mingw32_release_CXXFLAGS=$(mingw32_release_CFLAGS)
|
||||
|
||||
mingw32_debug_CFLAGS=-O1 -g
|
||||
mingw32_debug_CXXFLAGS=-O0 -g
|
||||
mingw32_debug_CFLAGS=-O1
|
||||
mingw32_debug_CXXFLAGS=$(mingw32_debug_CFLAGS)
|
||||
|
||||
mingw32_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package=bdb
|
||||
$(package)_version=4.8.30
|
||||
$(package)_download_path=https://download.oracle.com/berkeley-db
|
||||
$(package)_download_path=http://download.oracle.com/berkeley-db
|
||||
$(package)_file_name=db-$($(package)_version).NC.tar.gz
|
||||
$(package)_sha256_hash=12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef
|
||||
$(package)_build_subdir=build_unix
|
||||
|
@ -9,7 +9,7 @@ define $(package)_set_vars
|
|||
$(package)_config_opts=--disable-shared --enable-cxx --disable-replication
|
||||
$(package)_config_opts_mingw32=--enable-mingw
|
||||
$(package)_config_opts_linux=--with-pic
|
||||
$(package)_cppflags_mingw32=-DUNICODE -D_UNICODE
|
||||
$(package)_cxxflags=-std=c++11
|
||||
endef
|
||||
|
||||
define $(package)_preprocess_cmds
|
||||
|
@ -29,4 +29,3 @@ endef
|
|||
define $(package)_stage_cmds
|
||||
$(MAKE) DESTDIR=$($(package)_staging_dir) install_lib install_include
|
||||
endef
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package=boost
|
||||
$(package)_version=1_69_0
|
||||
$(package)_download_path=https://boostorg.jfrog.io/artifactory/main/release/1.69.0/source/
|
||||
$(package)_download_path=https://dl.bintray.com/boostorg/release/1.69.0/source/
|
||||
$(package)_file_name=$(package)_$($(package)_version).tar.bz2
|
||||
$(package)_sha256_hash=8f32d4617390d1c2d16f26a27ab60d97807b35440d45891fa340fc2648b04406
|
||||
$(package)_dependencies=icu
|
||||
|
|
|
@ -22,6 +22,7 @@ define $(package)_preprocess_cmds
|
|||
PKG_CONFIG_SYSROOT_DIR=/ \
|
||||
PKG_CONFIG_LIBDIR=$(host_prefix)/lib/pkgconfig \
|
||||
PKG_CONFIG_PATH=$(host_prefix)/share/pkgconfig \
|
||||
sed -i.old 's/^GEN_DEPS.cc.*/& $(CXXFLAGS)/' source/config/mh-mingw* && \
|
||||
mkdir -p build && cd build && \
|
||||
../source/runConfigureICU Linux $($(package)_standard_opts) CXXFLAGS=-std=c++11 && \
|
||||
$(MAKE) && cd ..
|
||||
|
@ -31,8 +32,6 @@ define $(package)_config_cmds
|
|||
PKG_CONFIG_SYSROOT_DIR=/ \
|
||||
PKG_CONFIG_LIBDIR=$(host_prefix)/lib/pkgconfig \
|
||||
PKG_CONFIG_PATH=$(host_prefix)/share/pkgconfig \
|
||||
sed -i.old 's|^GEN_DEPS.c=.*|& $($(package)_cflags)|' config/mh-mingw* && \
|
||||
sed -i.old 's|^GEN_DEPS.cc=.*|& $($(package)_cxxflags)|' config/mh-mingw* && \
|
||||
$($(package)_autoconf)
|
||||
endef
|
||||
|
||||
|
|
|
@ -27,5 +27,4 @@ define $(package)_stage_cmds
|
|||
endef
|
||||
|
||||
define $(package)_postprocess_cmds
|
||||
rm lib/*.la
|
||||
endef
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package=miniupnpc
|
||||
$(package)_version=2.0.20180203
|
||||
$(package)_download_path=https://miniupnp.tuxfamily.org/files/
|
||||
$(package)_download_path=http://miniupnp.free.fr/files
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
||||
$(package)_sha256_hash=90dda8c7563ca6cd4a83e23b3c66dbbea89603a1675bfdb852897c2c9cc220b7
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ $(package)_file_name=$(package)-$($(package)_version).tar.gz
|
|||
$(package)_sha256_hash=8f9faeaebad088e772f4ef5e38252d472be4d878c6b3a2718c10a4fcebe7a41c
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_config_env=AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CC="$($(package)_cc) $($(package)_cflags) $($(package)_cppflags)"
|
||||
$(package)_config_env=AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)"
|
||||
$(package)_config_opts=--prefix=$(host_prefix) --openssldir=$(host_prefix)/etc/openssl
|
||||
$(package)_config_opts+=no-camellia
|
||||
$(package)_config_opts+=no-capieng
|
||||
|
@ -42,6 +42,7 @@ $(package)_config_opts+=no-weak-ssl-ciphers
|
|||
$(package)_config_opts+=no-whirlpool
|
||||
$(package)_config_opts+=no-zlib
|
||||
$(package)_config_opts+=no-zlib-dynamic
|
||||
$(package)_config_opts+=$($(package)_cflags) $($(package)_cppflags)
|
||||
$(package)_config_opts_linux=-fPIC -Wa,--noexecstack
|
||||
$(package)_config_opts_x86_64_linux=linux-x86_64
|
||||
$(package)_config_opts_i686_linux=linux-generic32
|
||||
|
|
|
@ -4,6 +4,7 @@ $(package)_download_path=$(native_$(package)_download_path)
|
|||
$(package)_file_name=$(native_$(package)_file_name)
|
||||
$(package)_sha256_hash=$(native_$(package)_sha256_hash)
|
||||
$(package)_dependencies=native_$(package)
|
||||
$(package)_cxxflags=-std=c++11
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_config_opts=--disable-shared --with-protoc=$(build_prefix)/bin/protoc
|
||||
|
|
|
@ -6,10 +6,9 @@ $(package)_sha256_hash=bcbabe1e2c7d0eec4ed612e10b94b112dd5f06fcefa994a0c79a45d83
|
|||
$(package)_patches=0001-fix-build-with-older-mingw64.patch 0002-disable-pthread_set_name_np.patch
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_config_opts=--without-docs --disable-shared --without-libsodium --disable-curve --disable-curve-keygen --disable-perf --disable-Werror --disable-drafts
|
||||
$(package)_config_opts += --without-libsodium --without-libgssapi_krb5 --without-pgm --without-norm --without-vmci
|
||||
$(package)_config_opts += --disable-libunwind --disable-radix-tree --without-gcov
|
||||
$(package)_config_opts=--without-docs --disable-shared --without-libsodium --disable-curve --disable-curve-keygen --disable-perf --disable-Werror
|
||||
$(package)_config_opts_linux=--with-pic
|
||||
$(package)_cxxflags=-std=c++11
|
||||
endef
|
||||
|
||||
define $(package)_preprocess_cmds
|
||||
|
@ -32,5 +31,5 @@ endef
|
|||
|
||||
define $(package)_postprocess_cmds
|
||||
sed -i.old "s/ -lstdc++//" lib/pkgconfig/libzmq.pc && \
|
||||
rm -rf bin share lib/*.la
|
||||
rm -rf bin share
|
||||
endef
|
||||
|
|
|
@ -30,13 +30,13 @@ if which ccache >/dev/null; then
|
|||
fi
|
||||
|
||||
pushd depends
|
||||
make -j$(getconf _NPROCESSORS_ONLN) HOST=x86_64-apple-darwin14 NO_QT=1 V=1
|
||||
make -j`getconf _NPROCESSORS_ONLN` HOST=x86_64-apple-darwin14 NO_QT=1 V=1
|
||||
popd
|
||||
|
||||
./autogen.sh
|
||||
DEPS_DIR=$(pwd)/depends/x86_64-apple-darwin14
|
||||
DEPS_DIR=`pwd`/depends/x86_64-apple-darwin14
|
||||
CONFIG_SITE=${DEPS_DIR}/share/config.site ./configure --enable-reduce-exports --without-gui --with-icu="${DEPS_DIR}" --enable-static --disable-shared
|
||||
make -j$(getconf _NPROCESSORS_ONLN)
|
||||
make -j`getconf _NPROCESSORS_ONLN`
|
||||
${DEPS_DIR}/native/bin/x86_64-apple-darwin14-strip src/lbrycrdd src/lbrycrd-cli src/lbrycrd-tx
|
||||
|
||||
if which ccache >/dev/null; then
|
||||
|
|
|
@ -20,13 +20,13 @@ export CXXFLAGS="${CXXFLAGS:--frecord-gcc-switches}"
|
|||
echo "CXXFLAGS set to $CXXFLAGS"
|
||||
|
||||
cd depends
|
||||
make -j$(getconf _NPROCESSORS_ONLN) HOST=x86_64-pc-linux-gnu NO_QT=1 V=1
|
||||
make -j`getconf _NPROCESSORS_ONLN` HOST=x86_64-pc-linux-gnu NO_QT=1 V=1
|
||||
cd ..
|
||||
|
||||
./autogen.sh
|
||||
DEPS_DIR=$(pwd)/depends/x86_64-pc-linux-gnu
|
||||
DEPS_DIR=`pwd`/depends/x86_64-pc-linux-gnu
|
||||
CONFIG_SITE=${DEPS_DIR}/share/config.site ./configure --enable-static --disable-shared --with-pic --without-gui
|
||||
make -j$(getconf _NPROCESSORS_ONLN)
|
||||
make -j`getconf _NPROCESSORS_ONLN`
|
||||
strip src/lbrycrdd src/lbrycrd-cli src/lbrycrd-tx
|
||||
|
||||
if which ccache >/dev/null; then
|
||||
|
@ -34,4 +34,4 @@ if which ccache >/dev/null; then
|
|||
ccache -s
|
||||
fi
|
||||
|
||||
echo "Linux 64bit build is complete"
|
||||
echo "Linux 64bit build is complete"
|
|
@ -20,14 +20,17 @@ if which ccache >/dev/null; then
|
|||
ccache -ps
|
||||
fi
|
||||
|
||||
export CXXFLAGS="${CXXFLAGS:--frecord-gcc-switches}"
|
||||
echo "CXXFLAGS set to $CXXFLAGS"
|
||||
|
||||
pushd depends
|
||||
make -j$(getconf _NPROCESSORS_ONLN) HOST=i686-w64-mingw32 NO_QT=1 V=1
|
||||
make -j`getconf _NPROCESSORS_ONLN` HOST=i686-w64-mingw32 NO_QT=1 V=1
|
||||
popd
|
||||
|
||||
./autogen.sh
|
||||
DEPS_DIR=$(pwd)/depends/i686-w64-mingw32
|
||||
DEPS_DIR=`pwd`/depends/i686-w64-mingw32
|
||||
CONFIG_SITE=${DEPS_DIR}/share/config.site ./configure --prefix=/ --without-gui --with-icu="$DEPS_DIR" --enable-static --disable-shared
|
||||
make -j$(getconf _NPROCESSORS_ONLN)
|
||||
make -j`getconf _NPROCESSORS_ONLN`
|
||||
i686-w64-mingw32-strip src/lbrycrdd.exe src/lbrycrd-cli.exe src/lbrycrd-tx.exe
|
||||
|
||||
if which ccache >/dev/null; then
|
||||
|
|
|
@ -19,14 +19,17 @@ if which ccache >/dev/null; then
|
|||
ccache -ps
|
||||
fi
|
||||
|
||||
export CXXFLAGS="${CXXFLAGS:--frecord-gcc-switches}"
|
||||
echo "CXXFLAGS set to $CXXFLAGS"
|
||||
|
||||
pushd depends
|
||||
make -j$(getconf _NPROCESSORS_ONLN) HOST=x86_64-w64-mingw32 NO_QT=1 V=1
|
||||
make -j`getconf _NPROCESSORS_ONLN` HOST=x86_64-w64-mingw32 NO_QT=1 V=1
|
||||
popd
|
||||
|
||||
./autogen.sh
|
||||
DEPS_DIR=$(pwd)/depends/x86_64-w64-mingw32
|
||||
DEPS_DIR=`pwd`/depends/x86_64-w64-mingw32
|
||||
CONFIG_SITE=${DEPS_DIR}/share/config.site ./configure --prefix=/ --without-gui --with-icu="$DEPS_DIR" --enable-static --disable-shared
|
||||
make -j$(getconf _NPROCESSORS_ONLN)
|
||||
make -j`getconf _NPROCESSORS_ONLN`
|
||||
x86_64-w64-mingw32-strip src/lbrycrdd.exe src/lbrycrd-cli.exe src/lbrycrd-tx.exe
|
||||
|
||||
if which ccache >/dev/null; then
|
||||
|
|
|
@ -66,11 +66,6 @@ BITCOIN_TESTS =\
|
|||
test/net_tests.cpp \
|
||||
test/claimtriecache_tests.cpp \
|
||||
test/claimtriebranching_tests.cpp \
|
||||
test/claimtrieexpirationfork_tests.cpp \
|
||||
test/claimtriefixture.cpp \
|
||||
test/claimtriehashfork_tests.cpp \
|
||||
test/claimtrienormalization_tests.cpp \
|
||||
test/claimtrierpc_tests.cpp \
|
||||
test/nameclaim_tests.cpp \
|
||||
test/netbase_tests.cpp \
|
||||
test/pmt_tests.cpp \
|
||||
|
|
|
@ -123,7 +123,7 @@ void CChainParams::UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64
|
|||
class CMainParams : public CChainParams {
|
||||
public:
|
||||
CMainParams() {
|
||||
strNetworkID = CBaseChainParams::MAIN;
|
||||
strNetworkID = "lbrycrd";
|
||||
consensus.nSubsidyLevelInterval = 1<<5;
|
||||
consensus.nMajorityEnforceBlockUpgrade = 750;
|
||||
consensus.nMajorityRejectBlockOutdated = 950;
|
||||
|
@ -144,9 +144,9 @@ public:
|
|||
consensus.nAllowMinDiffMaxHeight = -1;
|
||||
consensus.nNormalizedNameForkHeight = 539940; // targeting 21 March 2019
|
||||
consensus.nMinTakeoverWorkaroundHeight = 496850;
|
||||
consensus.nMaxTakeoverWorkaroundHeight = 658300; // targeting 30 Oct 2019
|
||||
consensus.nWitnessForkHeight = 680770; // targeting 11 Dec 2019
|
||||
consensus.nAllClaimsInMerkleForkHeight = 658310; // targeting 30 Oct 2019
|
||||
consensus.nMaxTakeoverWorkaroundHeight = 654400; // targeting 30 Oct 2019
|
||||
consensus.nWitnessForkHeight = 676900; // targeting 11 Dec 2019
|
||||
consensus.nAllClaimsInMerkleForkHeight = 654400; // targeting 30 Oct 2019
|
||||
consensus.fPowAllowMinDifficultyBlocks = false;
|
||||
consensus.fPowNoRetargeting = false;
|
||||
consensus.nRuleChangeActivationThreshold = 1916; // 95% of a half week
|
||||
|
@ -166,10 +166,10 @@ public:
|
|||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1548288000; // Jan 24, 2019
|
||||
|
||||
// The best chain should have at least this much work.
|
||||
consensus.nMinimumChainWork = uint256S("000000000000000000000000000000000000000000000499ed6684d1bf6f6fd3"); //946000
|
||||
consensus.nMinimumChainWork = uint256S("00000000000000000000000000000000000000000000024108e3204a44a57a5a"); //621000
|
||||
|
||||
// By default assume that the signatures in ancestors of this block are valid.
|
||||
consensus.defaultAssumeValid = uint256S("0d3b537afe49820e1c6efc555463f955251b1293c6e5130137e1e25744431172"); //946000
|
||||
consensus.defaultAssumeValid = uint256S("7899464514d0d8854919e87eb234fd5f0c35d06418bd5fd3c1a8f7092b2a9317"); //620000
|
||||
|
||||
/**
|
||||
* The message start string is designed to be unlikely to occur in normal data.
|
||||
|
@ -195,11 +195,9 @@ public:
|
|||
vSeeds.clear();
|
||||
vFixedSeeds.clear();
|
||||
|
||||
vSeeds.emplace_back("dnsseed1.lbry.io"); // LBRY Inc
|
||||
vSeeds.emplace_back("dnsseed2.lbry.io"); // LBRY Inc
|
||||
vSeeds.emplace_back("dnsseed3.lbry.io"); // LBRY Inc
|
||||
vSeeds.emplace_back("seed.lbry.grin.io"); // Grin
|
||||
vSeeds.emplace_back("seed.allaboutlbc.com"); // Madiator2011
|
||||
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, 0x55);
|
||||
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1, 0x7a);
|
||||
|
@ -207,6 +205,8 @@ 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 = "lbc";
|
||||
|
||||
vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main));
|
||||
|
@ -241,7 +241,7 @@ public:
|
|||
class CTestNetParams : public CChainParams {
|
||||
public:
|
||||
CTestNetParams() {
|
||||
strNetworkID = CBaseChainParams::TESTNET;
|
||||
strNetworkID = "lbrycrdtest";
|
||||
consensus.nSubsidyLevelInterval = 1 << 5;
|
||||
consensus.nMajorityEnforceBlockUpgrade = 51;
|
||||
consensus.nMajorityRejectBlockOutdated = 75;
|
||||
|
@ -262,9 +262,9 @@ public:
|
|||
consensus.nAllowMinDiffMaxHeight = 1100000;
|
||||
consensus.nNormalizedNameForkHeight = 993380; // targeting, 21 Feb 2019
|
||||
consensus.nMinTakeoverWorkaroundHeight = 99;
|
||||
consensus.nMaxTakeoverWorkaroundHeight = 1198550; // targeting 30 Sep 2019
|
||||
consensus.nWitnessForkHeight = 1198600;
|
||||
consensus.nAllClaimsInMerkleForkHeight = 1198560; // targeting 30 Sep 2019
|
||||
consensus.nMaxTakeoverWorkaroundHeight = 1181920; // targeting 29 Sep 2019
|
||||
consensus.nWitnessForkHeight = 1181950;
|
||||
consensus.nAllClaimsInMerkleForkHeight = 1181920; // targeting 29 Sep 2019
|
||||
consensus.fPowAllowMinDifficultyBlocks = true;
|
||||
consensus.fPowNoRetargeting = false;
|
||||
consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains
|
||||
|
@ -351,7 +351,7 @@ public:
|
|||
class CRegTestParams : public CChainParams {
|
||||
public:
|
||||
CRegTestParams() {
|
||||
strNetworkID = CBaseChainParams::REGTEST;
|
||||
strNetworkID = "lbrycrdreg";
|
||||
consensus.nSubsidyLevelInterval = 1 << 5;
|
||||
consensus.BIP16Exception = uint256();
|
||||
consensus.BIP34Height = 1000; // BIP34 is needed for validation_block_tests
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
const std::string CBaseChainParams::MAIN = "lbrycrd";
|
||||
const std::string CBaseChainParams::TESTNET = "lbrycrdtest";
|
||||
const std::string CBaseChainParams::REGTEST = "lbrycrdreg";
|
||||
const std::string CBaseChainParams::REGTEST = "regtest";
|
||||
|
||||
void SetupChainParamsBaseOptions()
|
||||
{
|
||||
|
|
|
@ -149,7 +149,7 @@ bool ProcessClaim(CClaimScriptOp& claimOp, CClaimTrieCache& trieCache, const CSc
|
|||
{
|
||||
int op;
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
if (!DecodeClaimScript(scriptPubKey, op, vvchParams, trieCache.allowSupportMetadata()))
|
||||
if (!DecodeClaimScript(scriptPubKey, op, vvchParams))
|
||||
return false;
|
||||
|
||||
switch (op) {
|
||||
|
|
|
@ -208,15 +208,15 @@ COptional<const std::vector<queueEntryType<T>>> CClaimTrieCacheBase::getQueueCac
|
|||
}
|
||||
|
||||
template <>
|
||||
queueNameRowType* CClaimTrieCacheBase::getQueueCacheNameRow<CClaimValue>(const std::string& name, bool createIfNoExists)
|
||||
queueNameRowType* CClaimTrieCacheBase::getQueueCacheNameRow<CClaimValue>(const std::string& name, bool createIfNotExists)
|
||||
{
|
||||
return getQueue(*(base->db), CLAIM_QUEUE_NAME_ROW, name, claimQueueNameCache, createIfNoExists);
|
||||
return getQueue(*(base->db), CLAIM_QUEUE_NAME_ROW, name, claimQueueNameCache, createIfNotExists);
|
||||
}
|
||||
|
||||
template <>
|
||||
queueNameRowType* CClaimTrieCacheBase::getQueueCacheNameRow<CSupportValue>(const std::string& name, bool createIfNoExists)
|
||||
queueNameRowType* CClaimTrieCacheBase::getQueueCacheNameRow<CSupportValue>(const std::string& name, bool createIfNotExists)
|
||||
{
|
||||
return getQueue(*(base->db), SUPPORT_QUEUE_NAME_ROW, name, supportQueueNameCache, createIfNoExists);
|
||||
return getQueue(*(base->db), SUPPORT_QUEUE_NAME_ROW, name, supportQueueNameCache, createIfNotExists);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -246,15 +246,15 @@ COptional<const queueNameRowType> CClaimTrieCacheBase::getQueueCacheNameRow(cons
|
|||
}
|
||||
|
||||
template <>
|
||||
expirationQueueRowType* CClaimTrieCacheBase::getExpirationQueueCacheRow<CClaimValue>(int nHeight, bool createIfNoExists)
|
||||
expirationQueueRowType* CClaimTrieCacheBase::getExpirationQueueCacheRow<CClaimValue>(int nHeight, bool createIfNotExists)
|
||||
{
|
||||
return getQueue(*(base->db), CLAIM_EXP_QUEUE_ROW, nHeight, expirationQueueCache, createIfNoExists);
|
||||
return getQueue(*(base->db), CLAIM_EXP_QUEUE_ROW, nHeight, expirationQueueCache, createIfNotExists);
|
||||
}
|
||||
|
||||
template <>
|
||||
expirationQueueRowType* CClaimTrieCacheBase::getExpirationQueueCacheRow<CSupportValue>(int nHeight, bool createIfNoExists)
|
||||
expirationQueueRowType* CClaimTrieCacheBase::getExpirationQueueCacheRow<CSupportValue>(int nHeight, bool createIfNotExists)
|
||||
{
|
||||
return getQueue(*(base->db), SUPPORT_EXP_QUEUE_ROW, nHeight, supportExpirationQueueCache, createIfNoExists);
|
||||
return getQueue(*(base->db), SUPPORT_EXP_QUEUE_ROW, nHeight, supportExpirationQueueCache, createIfNotExists);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -266,8 +266,12 @@ expirationQueueRowType* CClaimTrieCacheBase::getExpirationQueueCacheRow(int, boo
|
|||
|
||||
bool CClaimTrieCacheBase::haveClaim(const std::string& name, const COutPoint& outPoint) const
|
||||
{
|
||||
auto it = find(name);
|
||||
return it && it->haveClaim(outPoint);
|
||||
if (auto it = nodesToAddOrUpdate.find(name))
|
||||
return it->haveClaim(outPoint);
|
||||
if (nodesToDelete.count(name))
|
||||
return false;
|
||||
CClaimTrieData data;
|
||||
return base->find(name, data) && data.haveClaim(outPoint);
|
||||
}
|
||||
|
||||
bool CClaimTrieCacheBase::haveSupport(const std::string& name, const COutPoint& outPoint) const
|
||||
|
@ -320,39 +324,71 @@ bool CClaimTrieCacheBase::haveSupportInQueue(const std::string& name, const COut
|
|||
return haveInQueue<CSupportValue>(name, outPoint, nValidAtHeight);
|
||||
}
|
||||
|
||||
void CClaimTrie::recurseNodes(const std::string& name, const CClaimTrieDataNode& current, std::function<recurseNodesCB> function) const
|
||||
{
|
||||
CClaimTrieData data;
|
||||
find(name, data);
|
||||
|
||||
if (!(data.flags & CAME_FROM_NODE_CACHE))
|
||||
data.hash = current.hash;
|
||||
|
||||
function(name, data, current.children);
|
||||
|
||||
for (auto& child: current.children) {
|
||||
CClaimTrieDataNode node;
|
||||
auto childName = name + child;
|
||||
if (find(childName, node))
|
||||
recurseNodes(childName, node, function);
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t CClaimTrie::getTotalNamesInTrie() const
|
||||
{
|
||||
std::size_t count = 0;
|
||||
for (auto it = begin(); it != end(); ++it)
|
||||
if (!it->empty()) ++count;
|
||||
CClaimTrieDataNode node;
|
||||
if (find({}, node))
|
||||
recurseNodes({}, node, [&count](const std::string &name, const CClaimTrieData &data, const std::vector<std::string>& children) {
|
||||
count += !data.empty();
|
||||
});
|
||||
return count;
|
||||
}
|
||||
|
||||
std::size_t CClaimTrie::getTotalClaimsInTrie() const
|
||||
{
|
||||
std::size_t count = 0;
|
||||
for (auto it = begin(); it != end(); ++it)
|
||||
count += it->claims.size();
|
||||
CClaimTrieDataNode node;
|
||||
if (find({}, node))
|
||||
recurseNodes({}, node, [&count]
|
||||
(const std::string &name, const CClaimTrieData &data, const std::vector<std::string>& children) {
|
||||
count += data.claims.size();
|
||||
});
|
||||
return count;
|
||||
}
|
||||
|
||||
CAmount CClaimTrie::getTotalValueOfClaimsInTrie(bool fControllingOnly) const
|
||||
{
|
||||
CAmount value_in_subtrie = 0;
|
||||
for (auto it = begin(); it != end(); ++it) {
|
||||
for (auto& claim : it->claims) {
|
||||
value_in_subtrie += claim.nAmount;
|
||||
if (fControllingOnly)
|
||||
break;
|
||||
}
|
||||
}
|
||||
CClaimTrieDataNode node;
|
||||
if (find({}, node))
|
||||
recurseNodes({}, node, [&value_in_subtrie, fControllingOnly]
|
||||
(const std::string &name, const CClaimTrieData &data, const std::vector<std::string>& children) {
|
||||
for (const auto &claim : data.claims) {
|
||||
value_in_subtrie += claim.nAmount;
|
||||
if (fControllingOnly)
|
||||
break;
|
||||
}
|
||||
});
|
||||
return value_in_subtrie;
|
||||
}
|
||||
|
||||
bool CClaimTrieCacheBase::getInfoForName(const std::string& name, CClaimValue& claim) const
|
||||
{
|
||||
auto it = find(name);
|
||||
return it && it->getBestClaim(claim);
|
||||
if (auto it = nodesToAddOrUpdate.find(name))
|
||||
return it->getBestClaim(claim);
|
||||
if (nodesToDelete.count(name))
|
||||
return false;
|
||||
CClaimTrieData claims;
|
||||
return base->find(name, claims) && claims.getBestClaim(claim);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -374,9 +410,15 @@ CClaimSupportToName CClaimTrieCacheBase::getClaimsForName(const std::string& nam
|
|||
auto supports = getSupportsForName(name);
|
||||
insertRowsFromQueue(supports, name);
|
||||
|
||||
if (auto it = find(name)) {
|
||||
if (auto it = nodesToAddOrUpdate.find(name)) {
|
||||
claims = it->claims;
|
||||
nLastTakeoverHeight = it->nHeightOfLastTakeover;
|
||||
} else if (!nodesToDelete.count(name)) {
|
||||
CClaimTrieData data;
|
||||
if (base->find(name, data)) {
|
||||
claims = data.claims;
|
||||
nLastTakeoverHeight = data.nHeightOfLastTakeover;
|
||||
}
|
||||
}
|
||||
insertRowsFromQueue(claims, name);
|
||||
|
||||
|
@ -411,89 +453,137 @@ void completeHash(uint256& partialHash, const std::string& key, std::size_t to)
|
|||
.Finalize(partialHash.begin());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
using iCbType = std::function<void(T&)>;
|
||||
|
||||
template <typename TIterator>
|
||||
uint256 recursiveMerkleHash(TIterator& it, const iCbType<TIterator>& process)
|
||||
bool CClaimTrie::checkConsistency(const uint256& rootHash) const
|
||||
{
|
||||
std::vector<uint8_t> vchToHash;
|
||||
const auto pos = it.key().size();
|
||||
for (auto& child : it.children()) {
|
||||
process(child);
|
||||
auto& key = child.key();
|
||||
auto hash = child->hash;
|
||||
completeHash(hash, key, pos);
|
||||
vchToHash.push_back(key[pos]);
|
||||
vchToHash.insert(vchToHash.end(), hash.begin(), hash.end());
|
||||
CClaimTrieDataNode node;
|
||||
if (!find({}, node) || node.hash != rootHash) {
|
||||
if (rootHash == one)
|
||||
return true;
|
||||
|
||||
return error("Mismatched root claim trie hashes. This may happen when there is not a clean process shutdown. Please run with -reindex.");
|
||||
}
|
||||
|
||||
CClaimValue claim;
|
||||
if (it->getBestClaim(claim)) {
|
||||
uint256 valueHash = getValueHash(claim.outPoint, it->nHeightOfLastTakeover);
|
||||
vchToHash.insert(vchToHash.end(), valueHash.begin(), valueHash.end());
|
||||
} else if (!it.hasChildren()) {
|
||||
return {};
|
||||
}
|
||||
bool success = true;
|
||||
recurseNodes({}, node, [&success, this](const std::string &name, const CClaimTrieData &data, const std::vector<std::string>& children) {
|
||||
if (!success) return;
|
||||
|
||||
return Hash(vchToHash.begin(), vchToHash.end());
|
||||
}
|
||||
|
||||
bool CClaimTrieCacheBase::recursiveCheckConsistency(CClaimTrie::const_iterator& it, std::string& failed) const
|
||||
{
|
||||
struct CRecursiveBreak {};
|
||||
using iterator = CClaimTrie::const_iterator;
|
||||
iCbType<iterator> process = [&failed, &process](iterator& it) {
|
||||
if (it->hash.IsNull() || it->hash != recursiveMerkleHash(it, process)) {
|
||||
failed = it.key();
|
||||
throw CRecursiveBreak();
|
||||
std::vector<uint8_t> vchToHash;
|
||||
const auto pos = name.size();
|
||||
for (auto &child : children) {
|
||||
auto key = name + child;
|
||||
CClaimTrieDataNode node;
|
||||
success &= find(key, node);
|
||||
auto hash = node.hash;
|
||||
completeHash(hash, key, pos);
|
||||
vchToHash.push_back(key[pos]);
|
||||
vchToHash.insert(vchToHash.end(), hash.begin(), hash.end());
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
process(it);
|
||||
} catch (const CRecursiveBreak&) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
CClaimValue claim;
|
||||
if (data.getBestClaim(claim)) {
|
||||
uint256 valueHash = getValueHash(claim.outPoint, data.nHeightOfLastTakeover);
|
||||
vchToHash.insert(vchToHash.end(), valueHash.begin(), valueHash.end());
|
||||
} else {
|
||||
success &= !children.empty(); // we disallow leaf nodes without claims
|
||||
}
|
||||
success &= data.hash == Hash(vchToHash.begin(), vchToHash.end());
|
||||
});
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool CClaimTrieCacheBase::checkConsistency() const
|
||||
std::vector<std::pair<std::string, CClaimTrieDataNode>> CClaimTrie::nodes(const std::string &key) const
|
||||
{
|
||||
if (base->empty())
|
||||
std::vector<std::pair<std::string, CClaimTrieDataNode>> ret;
|
||||
CClaimTrieDataNode node;
|
||||
|
||||
if (!find({}, node))
|
||||
return ret;
|
||||
|
||||
ret.emplace_back(std::string{}, node);
|
||||
|
||||
std::string partialKey = key;
|
||||
|
||||
while (!node.children.empty()) {
|
||||
// auto it = node.children.lower_bound(partialKey); // for using a std::map
|
||||
auto it = std::lower_bound(node.children.begin(), node.children.end(), partialKey);
|
||||
if (it != node.children.end() && *it == partialKey) {
|
||||
// we're completely done
|
||||
if (find(key, node))
|
||||
ret.emplace_back(key, node);
|
||||
break;
|
||||
}
|
||||
if (it != node.children.begin()) --it;
|
||||
const auto count = match(partialKey, *it);
|
||||
|
||||
if (count != it->size()) break;
|
||||
if (count == partialKey.size()) break;
|
||||
partialKey = partialKey.substr(count);
|
||||
auto frontKey = key.substr(0, key.size() - partialKey.size());
|
||||
if (find(frontKey, node))
|
||||
ret.emplace_back(frontKey, node);
|
||||
else break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CClaimTrie::contains(const std::string& key) const
|
||||
{
|
||||
return cacheNodes.find(key) || db->Exists(std::make_pair(TRIE_NODE_CHILDREN, key));
|
||||
}
|
||||
|
||||
bool CClaimTrie::empty() const
|
||||
{
|
||||
return cacheNodes.empty() && !contains({});
|
||||
}
|
||||
|
||||
std::vector<std::string> extractChildren(CClaimPrefixTrie::const_iterator it)
|
||||
{
|
||||
std::vector<std::string> children;
|
||||
auto size = it.key().size();
|
||||
for (auto& child : it.children()) // ordering here is important
|
||||
children.emplace_back(child.key().substr(size));
|
||||
return children;
|
||||
}
|
||||
|
||||
static std::size_t cacheHits = 0;
|
||||
static std::size_t cacheMisses = 0;
|
||||
bool CClaimTrie::find(const std::string& key, CClaimTrieDataNode& node) const
|
||||
{
|
||||
if (auto it = cacheNodes.find(key)) {
|
||||
if (it.hasChildren()) {
|
||||
cacheHits++;
|
||||
node.hash = it->hash;
|
||||
node.children = extractChildren(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
auto ret = db->Read(std::make_pair(TRIE_NODE_CHILDREN, key), node);
|
||||
if (ret) ++cacheMisses;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CClaimTrie::find(const std::string& key, CClaimTrieData& data) const
|
||||
{
|
||||
if (auto it = cacheNodes.find(key)) {
|
||||
cacheHits++;
|
||||
data = it.data();
|
||||
data.flags |= CAME_FROM_NODE_CACHE;
|
||||
return true;
|
||||
|
||||
auto it = base->cbegin();
|
||||
std::string failed;
|
||||
auto consistent = recursiveCheckConsistency(it, failed);
|
||||
if (!consistent) {
|
||||
LogPrintf("\nPrinting base tree from its parent:\n");
|
||||
auto basePath = base->nodes(failed);
|
||||
if (basePath.size() > 1) basePath.pop_back();
|
||||
dumpToLog(basePath.back(), false);
|
||||
auto cachePath = nodesToAddOrUpdate.nodes(failed);
|
||||
if (!cachePath.empty()) {
|
||||
LogPrintf("\nPrinting %s's parent from cache:\n", failed);
|
||||
if (cachePath.size() > 1) cachePath.pop_back();
|
||||
dumpToLog(cachePath.back(), false);
|
||||
}
|
||||
if (!nodesToDelete.empty()) {
|
||||
std::string joined;
|
||||
for (const auto &piece : nodesToDelete) joined += ", " + piece;
|
||||
LogPrintf("Nodes to be deleted: %s\n", joined.substr(2));
|
||||
}
|
||||
}
|
||||
return consistent;
|
||||
auto ret = db->Read(std::make_pair(TRIE_NODE_CLAIMS, key), data);
|
||||
if (ret) ++cacheMisses;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename K, typename T>
|
||||
void BatchWrite(CDBBatch& batch, uint8_t dbkey, const K& key, const std::vector<T>& value)
|
||||
void BatchWrite(CDBBatch& batch, uint8_t dbkey, const K& key, const T& value)
|
||||
{
|
||||
if (value.empty()) {
|
||||
if (value.empty())
|
||||
batch.Erase(std::make_pair(dbkey, key));
|
||||
} else {
|
||||
else
|
||||
batch.Write(std::make_pair(dbkey, key), value);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
|
@ -522,24 +612,39 @@ bool CClaimTrieCacheBase::flush()
|
|||
|
||||
getMerkleHash();
|
||||
|
||||
for (const auto& nodeName : nodesToDelete) {
|
||||
if (nodesToAddOrUpdate.contains(nodeName))
|
||||
continue;
|
||||
auto nodes = base->nodes(nodeName);
|
||||
base->erase(nodeName);
|
||||
for (auto& node : nodes)
|
||||
if (!node)
|
||||
batch.Erase(std::make_pair(TRIE_NODE, node.key()));
|
||||
if (base->cacheNodes.height() > 40000)
|
||||
base->cacheNodes.clear();
|
||||
|
||||
for (auto it = nodesToAddOrUpdate.begin(); it != nodesToAddOrUpdate.end(); ++it) {
|
||||
bool removed = forDeleteFromBase.erase(it.key());
|
||||
if (it->flags & HASH_DIRTY) {
|
||||
CClaimTrieDataNode node;
|
||||
node.hash = it->hash;
|
||||
node.children = extractChildren(it);
|
||||
|
||||
batch.Write(std::make_pair(TRIE_NODE_CHILDREN, it.key()), node);
|
||||
|
||||
if (removed || (it->flags & CLAIMS_DIRTY))
|
||||
BatchWrite(batch, TRIE_NODE_CLAIMS, it.key(), it.data());
|
||||
}
|
||||
it->flags = 0;
|
||||
}
|
||||
|
||||
for (auto& name: forDeleteFromBase) {
|
||||
base->cacheNodes.erase(name);
|
||||
batch.Erase(std::make_pair(TRIE_NODE_CHILDREN, name));
|
||||
batch.Erase(std::make_pair(TRIE_NODE_CLAIMS, name));
|
||||
}
|
||||
|
||||
for (auto it = nodesToAddOrUpdate.begin(); it != nodesToAddOrUpdate.end(); ++it) {
|
||||
auto old = base->find(it.key());
|
||||
if (!old || old.data() != it.data()) {
|
||||
base->copy(it);
|
||||
batch.Write(std::make_pair(TRIE_NODE, it.key()), it.data());
|
||||
if (it.depth() < 4) {
|
||||
base->cacheNodes.copy(it, it.depth() == 3 || (it->flags & HASH_DIRTY && !it.hasChildren()));
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Height: %d, Hits: %zu, Misses: %zu, Cache Size: %zu\n", nNextHeight, cacheHits, cacheMisses, base->cacheNodes.height());
|
||||
cacheHits = cacheMisses = 0;
|
||||
|
||||
BatchWriteQueue(batch, SUPPORT, supportCache);
|
||||
|
||||
BatchWriteQueue(batch, CLAIM_QUEUE_ROW, claimQueueCache);
|
||||
|
@ -555,76 +660,37 @@ bool CClaimTrieCacheBase::flush()
|
|||
LogPrintf("TrieCache size: %zu nodes on block %d, batch writes %zu bytes.\n",
|
||||
nodesToAddOrUpdate.height(), nNextHeight, batch.SizeEstimate());
|
||||
}
|
||||
auto ret = base->db->WriteBatch(batch);
|
||||
|
||||
clear();
|
||||
return ret;
|
||||
return base->db->WriteBatch(batch);
|
||||
}
|
||||
|
||||
bool CClaimTrieCacheBase::ReadFromDisk(const CBlockIndex* tip)
|
||||
bool CClaimTrieCacheBase::validateTrieConsistency(const CBlockIndex* tip)
|
||||
{
|
||||
LogPrintf("Loading the claim trie from disk...\n");
|
||||
|
||||
base->nNextHeight = nNextHeight = tip ? tip->nHeight + 1 : 0;
|
||||
|
||||
if (tip && base->db->Exists(std::make_pair(TRIE_NODE_CHILDREN, std::string()))) {
|
||||
LogPrintf("The claim trie database contains deprecated data and will need to be rebuilt.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
clear();
|
||||
base->clear();
|
||||
boost::scoped_ptr<CDBIterator> pcursor(base->db->NewIterator());
|
||||
|
||||
for (pcursor->SeekToFirst(); pcursor->Valid(); pcursor->Next()) {
|
||||
std::pair<uint8_t, std::string> key;
|
||||
if (!pcursor->GetKey(key) || key.first != TRIE_NODE)
|
||||
continue;
|
||||
|
||||
CClaimTrieData data;
|
||||
if (pcursor->GetValue(data)) {
|
||||
if (data.empty()) {
|
||||
// we have a situation where our old trie had many empty nodes
|
||||
// we don't want to automatically throw those all into our prefix trie
|
||||
// we'll run a second pass to clean them up
|
||||
continue;
|
||||
}
|
||||
|
||||
// nEffectiveAmount isn't serialized but it needs to be initialized (as done in reorderClaims):
|
||||
auto supports = getSupportsForName(key.second);
|
||||
data.reorderClaims(supports);
|
||||
base->insert(key.second, std::move(data));
|
||||
} else {
|
||||
return error("%s(): error reading claim trie from disk", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
for (pcursor->SeekToFirst(); pcursor->Valid(); pcursor->Next()) {
|
||||
std::pair<uint8_t, std::string> key;
|
||||
if (!pcursor->GetKey(key) || key.first != TRIE_NODE)
|
||||
continue;
|
||||
auto hit = base->find(key.second);
|
||||
if (hit) {
|
||||
CClaimTrieData data;
|
||||
if (pcursor->GetValue(data))
|
||||
hit->hash = data.hash;
|
||||
}
|
||||
else {
|
||||
base->db->Erase(key); // this uses a lot of memory and it's 1-time upgrade from 12.4 so we aren't going to batch it
|
||||
}
|
||||
}
|
||||
if (!tip || tip->nHeight < 1)
|
||||
return true;
|
||||
|
||||
LogPrintf("Checking claim trie consistency... ");
|
||||
if (checkConsistency()) {
|
||||
if (base->checkConsistency(tip->hashClaimTrie)) {
|
||||
LogPrintf("consistent\n");
|
||||
if (tip && tip->hashClaimTrie != getMerkleHash())
|
||||
return error("%s(): hashes don't match when reading claimtrie from disk", __func__);
|
||||
return true;
|
||||
}
|
||||
LogPrintf("inconsistent!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CClaimTrieCacheBase::ReadFromDisk(const CBlockIndex* tip)
|
||||
{
|
||||
base->nNextHeight = nNextHeight = tip ? tip->nHeight + 1 : 0;
|
||||
clear();
|
||||
|
||||
if (tip && base->db->Exists(std::make_pair(TRIE_NODE, std::string()))) {
|
||||
LogPrintf("The claim trie database contains deprecated data and will need to be rebuilt");
|
||||
return false;
|
||||
}
|
||||
return validateTrieConsistency(tip);
|
||||
}
|
||||
|
||||
CClaimTrieCacheBase::CClaimTrieCacheBase(CClaimTrie* base) : base(base)
|
||||
{
|
||||
assert(base);
|
||||
|
@ -636,60 +702,84 @@ int CClaimTrieCacheBase::expirationTime() const
|
|||
return Params().GetConsensus().nOriginalClaimExpirationTime;
|
||||
}
|
||||
|
||||
uint256 CClaimTrieCacheBase::recursiveComputeMerkleHash(CClaimTrie::iterator& it)
|
||||
uint256 CClaimTrieCacheBase::recursiveComputeMerkleHash(CClaimPrefixTrie::iterator& it)
|
||||
{
|
||||
using iterator = CClaimTrie::iterator;
|
||||
iCbType<iterator> process = [&process](iterator& it) {
|
||||
if (it->hash.IsNull())
|
||||
it->hash = recursiveMerkleHash(it, process);
|
||||
assert(!it->hash.IsNull());
|
||||
};
|
||||
process(it);
|
||||
return it->hash;
|
||||
if (!it->hash.IsNull())
|
||||
return it->hash;
|
||||
|
||||
std::vector<uint8_t> vchToHash;
|
||||
const auto pos = it.key().size();
|
||||
for (auto& child : it.children()) {
|
||||
auto hash = recursiveComputeMerkleHash(child);
|
||||
auto& key = child.key();
|
||||
completeHash(hash, key, pos);
|
||||
vchToHash.push_back(key[pos]);
|
||||
vchToHash.insert(vchToHash.end(), hash.begin(), hash.end());
|
||||
}
|
||||
|
||||
CClaimValue claim;
|
||||
if (it->getBestClaim(claim)) {
|
||||
uint256 valueHash = getValueHash(claim.outPoint, it->nHeightOfLastTakeover);
|
||||
vchToHash.insert(vchToHash.end(), valueHash.begin(), valueHash.end());
|
||||
}
|
||||
|
||||
return it->hash = Hash(vchToHash.begin(), vchToHash.end());
|
||||
}
|
||||
|
||||
uint256 CClaimTrieCacheBase::getMerkleHash()
|
||||
{
|
||||
auto it = nodesToAddOrUpdate.begin();
|
||||
if (!it && nodesToDelete.empty())
|
||||
it = base->begin();
|
||||
return !it ? one : recursiveComputeMerkleHash(it);
|
||||
if (auto it = nodesToAddOrUpdate.begin())
|
||||
return recursiveComputeMerkleHash(it);
|
||||
if (nodesToDelete.empty() && nodesAlreadyCached.empty()) {
|
||||
CClaimTrieDataNode node;
|
||||
if (base->find({}, node))
|
||||
return node.hash; // it may be valuable to have base cache its current root hash
|
||||
}
|
||||
return one; // we have no data or we deleted everything
|
||||
}
|
||||
|
||||
CClaimTrie::const_iterator CClaimTrieCacheBase::find(const std::string& name) const
|
||||
CClaimPrefixTrie::const_iterator CClaimTrieCacheBase::begin() const
|
||||
{
|
||||
auto it = nodesToAddOrUpdate.find(name);
|
||||
if (it || nodesToDelete.count(name))
|
||||
return it;
|
||||
return base->find(name);
|
||||
return nodesToAddOrUpdate.begin();
|
||||
}
|
||||
|
||||
CClaimPrefixTrie::const_iterator CClaimTrieCacheBase::end() const
|
||||
{
|
||||
return nodesToAddOrUpdate.end();
|
||||
}
|
||||
|
||||
bool CClaimTrieCacheBase::empty() const
|
||||
{
|
||||
return nodesToAddOrUpdate.empty(); // only used with the dump method, and we don't want to dump base
|
||||
return nodesToAddOrUpdate.empty();
|
||||
}
|
||||
|
||||
CClaimTrie::iterator CClaimTrieCacheBase::cacheData(const std::string& name, bool create)
|
||||
CClaimPrefixTrie::iterator CClaimTrieCacheBase::cacheData(const std::string& name, bool create)
|
||||
{
|
||||
// get data from the cache. if no data, create empty one
|
||||
const auto insert = [this](CClaimTrie::iterator& it) {
|
||||
auto& key = it.key();
|
||||
// we only ever cache nodes once per cache instance
|
||||
if (!nodesAlreadyCached.count(key)) {
|
||||
// do not insert nodes that are already present
|
||||
nodesAlreadyCached.insert(key);
|
||||
nodesToAddOrUpdate.insert(key, it.data());
|
||||
}
|
||||
};
|
||||
|
||||
// we need all parent nodes and their one level deep children
|
||||
// to calculate merkle hash
|
||||
auto nodes = base->nodes(name);
|
||||
for (auto& node: nodes) {
|
||||
for (auto& child : node.children())
|
||||
if (!nodesAlreadyCached.count(child.key()))
|
||||
nodesToAddOrUpdate.copy(child);
|
||||
insert(node);
|
||||
if (nodesAlreadyCached.insert(node.first).second) {
|
||||
// do not insert nodes that are already present
|
||||
CClaimTrieData data;
|
||||
base->find(node.first, data);
|
||||
if (!(data.flags & CAME_FROM_NODE_CACHE))
|
||||
data.hash = node.second.hash;
|
||||
nodesToAddOrUpdate.insert(node.first, std::move(data));
|
||||
}
|
||||
for (auto& child : node.second.children) {
|
||||
auto childKey = node.first + child;
|
||||
if (nodesAlreadyCached.insert(childKey).second) {
|
||||
CClaimTrieData childData;
|
||||
base->find(childKey, childData);
|
||||
if (!(childData.flags & CAME_FROM_NODE_CACHE)) {
|
||||
CClaimTrieDataNode childNode;
|
||||
if (base->find(childKey, childNode))
|
||||
childData.hash = childNode.hash;
|
||||
}
|
||||
nodesToAddOrUpdate.insert(childKey, std::move(childData));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto it = nodesToAddOrUpdate.find(name);
|
||||
|
@ -715,10 +805,11 @@ bool CClaimTrieCacheBase::getLastTakeoverForName(const std::string& name, uint16
|
|||
std::tie(claimId, takeoverHeight) = cit->second;
|
||||
return true;
|
||||
}
|
||||
if (auto it = base->find(name)) {
|
||||
takeoverHeight = it->nHeightOfLastTakeover;
|
||||
CClaimTrieData data;
|
||||
if (base->find(name, data)) {
|
||||
takeoverHeight = data.nHeightOfLastTakeover;
|
||||
CClaimValue claim;
|
||||
if (it->getBestClaim(claim)) {
|
||||
if (data.getBestClaim(claim)) {
|
||||
claimId = claim.claimId;
|
||||
return true;
|
||||
}
|
||||
|
@ -728,8 +819,13 @@ bool CClaimTrieCacheBase::getLastTakeoverForName(const std::string& name, uint16
|
|||
|
||||
void CClaimTrieCacheBase::markAsDirty(const std::string& name, bool fCheckTakeover)
|
||||
{
|
||||
for (auto& node : nodesToAddOrUpdate.nodes(name))
|
||||
for (auto& node : nodesToAddOrUpdate.nodes(name)) {
|
||||
node->flags |= HASH_DIRTY;
|
||||
|
||||
node->hash.SetNull();
|
||||
if (node.key() == name)
|
||||
node->flags |= CLAIMS_DIRTY;
|
||||
}
|
||||
|
||||
if (fCheckTakeover)
|
||||
namesToCheckForTakeover.insert(name);
|
||||
|
@ -763,6 +859,9 @@ bool CClaimTrieCacheBase::removeClaimFromTrie(const std::string& name, const COu
|
|||
for (auto& child: it.children())
|
||||
cacheData(child.key(), false);
|
||||
|
||||
for (auto& node : nodesToAddOrUpdate.nodes(name))
|
||||
forDeleteFromBase.emplace(node.key());
|
||||
|
||||
nodesToAddOrUpdate.erase(name);
|
||||
nodesToDelete.insert(name);
|
||||
|
||||
|
@ -935,14 +1034,10 @@ bool CClaimTrieCacheBase::remove(T& value, const std::string& name, const COutPo
|
|||
nValidAtHeight = nHeight + getDelayForName(name);
|
||||
std::string adjusted = adjustNameForValidHeight(name, nValidAtHeight);
|
||||
|
||||
auto rfq = removeFromQueue(adjusted, outPoint, value);
|
||||
if (rfq || removeFromCache(name, outPoint, value, fCheckTakeover)) {
|
||||
if (removeFromQueue(adjusted, outPoint, value) || removeFromCache(name, outPoint, value, fCheckTakeover)) {
|
||||
int expirationHeight = value.nHeight + expirationTime();
|
||||
if (auto itQueueRow = getExpirationQueueCacheRow<T>(expirationHeight, false)) {
|
||||
if (auto itQueueRow = getExpirationQueueCacheRow<T>(expirationHeight, false))
|
||||
eraseOutPoint(*itQueueRow, CNameOutPointType{adjusted, outPoint});
|
||||
if (adjusted != name) // workaround for an off-by-1 error in normalization block (wherein we might get both):
|
||||
eraseOutPoint(*itQueueRow, CNameOutPointType{name, outPoint});
|
||||
}
|
||||
nValidAtHeight = value.nValidAtHeight;
|
||||
return true;
|
||||
}
|
||||
|
@ -1003,11 +1098,13 @@ bool CClaimTrieCacheBase::removeSupportFromMap(const std::string& name, const CO
|
|||
return false;
|
||||
}
|
||||
|
||||
void CClaimTrieCacheBase::dumpToLog(CClaimTrie::const_iterator it, bool diffFromBase) const
|
||||
void CClaimTrieCacheBase::dumpToLog(CClaimPrefixTrie::const_iterator it, bool diffFromBase) const
|
||||
{
|
||||
if (!it) return;
|
||||
|
||||
if (diffFromBase) {
|
||||
auto hit = base->find(it.key());
|
||||
if (hit && hit->hash == it->hash)
|
||||
CClaimTrieDataNode node;
|
||||
if (base->find(it.key(), node) && node.hash == it->hash)
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1101,12 +1198,9 @@ void CClaimTrieCacheBase::undoIncrement(insertUndoType& insertUndo, std::vector<
|
|||
if (auto itExpirationRow = getExpirationQueueCacheRow<T>(nNextHeight, false)) {
|
||||
for (const auto& itEntry : *itExpirationRow) {
|
||||
T value;
|
||||
if (removeFromCache(itEntry.name, itEntry.outPoint, value, true)) {
|
||||
expireUndo.emplace_back(itEntry.name, value);
|
||||
addTo(deleted, value);
|
||||
}
|
||||
else // a bug in the normalization stuff allows some of these to stick around after the claims were spent; don't crash
|
||||
LogPrintf("Warning: missing expired entry %s, %s:%d\n", itEntry.name, itEntry.outPoint.hash.GetHex(), itEntry.outPoint.n);
|
||||
assert(removeFromCache(itEntry.name, itEntry.outPoint, value, true));
|
||||
expireUndo.emplace_back(itEntry.name, value);
|
||||
addTo(deleted, value);
|
||||
}
|
||||
itExpirationRow->clear();
|
||||
}
|
||||
|
@ -1324,8 +1418,12 @@ int CClaimTrieCacheBase::getNumBlocksOfContinuousOwnership(const std::string& na
|
|||
that->removalWorkaround.erase(hit);
|
||||
return 0;
|
||||
}
|
||||
auto it = nodesToAddOrUpdate.find(name);
|
||||
return (it || (it = base->find(name))) && !it->empty() ? nNextHeight - it->nHeightOfLastTakeover : 0;
|
||||
if (auto it = nodesToAddOrUpdate.find(name))
|
||||
return it->empty() ? 0 : nNextHeight - it->nHeightOfLastTakeover;
|
||||
CClaimTrieData data;
|
||||
if (base->find(name, data) && !data.empty())
|
||||
return nNextHeight - data.nHeightOfLastTakeover;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CClaimTrieCacheBase::getDelayForName(const std::string& name) const
|
||||
|
@ -1352,22 +1450,23 @@ std::string CClaimTrieCacheBase::adjustNameForValidHeight(const std::string& nam
|
|||
|
||||
bool CClaimTrieCacheBase::clear()
|
||||
{
|
||||
forDeleteFromBase.clear();
|
||||
nodesToAddOrUpdate.clear();
|
||||
claimsToAddToByIdIndex.clear();
|
||||
supportCache.clear();
|
||||
nodesToDelete.clear();
|
||||
claimsToDeleteFromByIdIndex.clear();
|
||||
takeoverCache.clear();
|
||||
claimQueueCache.clear();
|
||||
supportQueueCache.clear();
|
||||
removalWorkaround.clear();
|
||||
nodesToAddOrUpdate.clear();
|
||||
nodesAlreadyCached.clear();
|
||||
takeoverWorkaround.clear();
|
||||
removalWorkaround.clear();
|
||||
claimQueueNameCache.clear();
|
||||
expirationQueueCache.clear();
|
||||
supportQueueNameCache.clear();
|
||||
claimsToAddToByIdIndex.clear();
|
||||
namesToCheckForTakeover.clear();
|
||||
supportExpirationQueueCache.clear();
|
||||
claimsToDeleteFromByIdIndex.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1377,7 +1476,7 @@ bool CClaimTrieCacheBase::getProofForName(const std::string& name, CClaimTriePro
|
|||
cacheData(name, false);
|
||||
getMerkleHash();
|
||||
proof = CClaimTrieProof();
|
||||
for (auto& it : static_cast<const CClaimTrie&>(nodesToAddOrUpdate).nodes(name)) {
|
||||
for (auto& it : static_cast<const CClaimPrefixTrie&>(nodesToAddOrUpdate).nodes(name)) {
|
||||
CClaimValue claim;
|
||||
const auto& key = it.key();
|
||||
bool fNodeHasValue = it->getBestClaim(claim);
|
||||
|
@ -1393,7 +1492,7 @@ bool CClaimTrieCacheBase::getProofForName(const std::string& name, CClaimTriePro
|
|||
for (auto i = pos; i + 1 < childKey.size(); ++i) {
|
||||
children.emplace_back(childKey[i], uint256{});
|
||||
proof.nodes.emplace_back(children, fNodeHasValue, valueHash);
|
||||
children.clear();
|
||||
children.clear(); // move promises to leave it in a valid state only
|
||||
valueHash.SetNull();
|
||||
fNodeHasValue = false;
|
||||
}
|
||||
|
@ -1417,22 +1516,33 @@ bool CClaimTrieCacheBase::getProofForName(const std::string& name, CClaimTriePro
|
|||
return true;
|
||||
}
|
||||
|
||||
void CClaimTrieCacheBase::iterate(std::function<void(const std::string&, const CClaimTrieData&)> callback) const
|
||||
{
|
||||
if (nodesToAddOrUpdate.empty()) {
|
||||
for (auto it = base->cbegin(); it != base->cend(); ++it)
|
||||
if (!nodesToDelete.count(it.key()))
|
||||
callback(it.key(), it.data());
|
||||
return;
|
||||
void CClaimTrieCacheBase::recurseNodes(const std::string &name,
|
||||
std::function<void(const std::string &, const CClaimTrieData &)> function) const {
|
||||
|
||||
std::function<CClaimTrie::recurseNodesCB> baseFunction = [this, &function]
|
||||
(const std::string& name, const CClaimTrieData& data, const std::vector<std::string>&) {
|
||||
if (nodesToDelete.find(name) == nodesToDelete.end())
|
||||
function(name, data);
|
||||
};
|
||||
|
||||
if (empty()) {
|
||||
CClaimTrieDataNode node;
|
||||
if (base->find(name, node))
|
||||
base->recurseNodes(name, node, baseFunction);
|
||||
}
|
||||
for (auto it = nodesToAddOrUpdate.begin(); it != nodesToAddOrUpdate.end(); ++it) {
|
||||
callback(it.key(), it.data());
|
||||
if (it.hasChildren() || nodesToDelete.count(it.key()))
|
||||
continue;
|
||||
auto children = base->find(it.key()).children();
|
||||
for (auto& child : children)
|
||||
for (; child; ++child)
|
||||
if (!nodesToDelete.count(child.key()))
|
||||
callback(child.key(), child.data());
|
||||
else {
|
||||
for (auto it = begin(); it != end(); ++it) {
|
||||
function(it.key(), it.data());
|
||||
if (!it.hasChildren()) {
|
||||
CClaimTrieDataNode node;
|
||||
if (base->find(it.key(), node))
|
||||
for (auto& partialKey: node.children) {
|
||||
auto childKey = it.key() + partialKey;
|
||||
CClaimTrieDataNode childNode;
|
||||
if (base->find(childKey, childNode))
|
||||
base->recurseNodes(childKey, childNode, baseFunction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
102
src/claimtrie.h
102
src/claimtrie.h
|
@ -18,8 +18,9 @@
|
|||
#include <unordered_set>
|
||||
|
||||
// leveldb keys
|
||||
#define TRIE_NODE 'n'
|
||||
#define TRIE_NODE 'n' // deprecated
|
||||
#define TRIE_NODE_CHILDREN 'b'
|
||||
#define TRIE_NODE_CLAIMS 'c'
|
||||
#define CLAIM_BY_ID 'i'
|
||||
#define CLAIM_QUEUE_ROW 'r'
|
||||
#define CLAIM_QUEUE_NAME_ROW 'm'
|
||||
|
@ -62,6 +63,7 @@ struct CClaimValue
|
|||
READWRITE(nAmount);
|
||||
READWRITE(nHeight);
|
||||
READWRITE(nValidAtHeight);
|
||||
READWRITE(nEffectiveAmount);
|
||||
}
|
||||
|
||||
bool operator<(const CClaimValue& other) const
|
||||
|
@ -134,12 +136,21 @@ struct CSupportValue
|
|||
typedef std::vector<CClaimValue> claimEntryType;
|
||||
typedef std::vector<CSupportValue> supportEntryType;
|
||||
|
||||
enum CClaimTrieDataFlags: uint32_t {
|
||||
HASH_DIRTY = 1U,
|
||||
CLAIMS_DIRTY = 2U,
|
||||
CAME_FROM_NODE_CACHE = 4U,
|
||||
};
|
||||
|
||||
struct CClaimTrieData
|
||||
{
|
||||
uint256 hash;
|
||||
claimEntryType claims;
|
||||
int nHeightOfLastTakeover = 0;
|
||||
|
||||
// non-serialized data:
|
||||
uint32_t flags = 0;
|
||||
uint256 hash;
|
||||
|
||||
CClaimTrieData() = default;
|
||||
CClaimTrieData(CClaimTrieData&&) = default;
|
||||
CClaimTrieData(const CClaimTrieData&) = default;
|
||||
|
@ -157,25 +168,13 @@ struct CClaimTrieData
|
|||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
||||
{
|
||||
READWRITE(hash);
|
||||
|
||||
if (ser_action.ForRead()) {
|
||||
if (s.eof()) {
|
||||
claims.clear();
|
||||
nHeightOfLastTakeover = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (claims.empty())
|
||||
return;
|
||||
|
||||
READWRITE(claims);
|
||||
READWRITE(nHeightOfLastTakeover);
|
||||
}
|
||||
|
||||
bool operator==(const CClaimTrieData& other) const
|
||||
{
|
||||
return hash == other.hash && nHeightOfLastTakeover == other.nHeightOfLastTakeover && claims == other.claims;
|
||||
return nHeightOfLastTakeover == other.nHeightOfLastTakeover && claims == other.claims;
|
||||
}
|
||||
|
||||
bool operator!=(const CClaimTrieData& other) const
|
||||
|
@ -189,6 +188,29 @@ struct CClaimTrieData
|
|||
}
|
||||
};
|
||||
|
||||
struct CClaimTrieDataNode
|
||||
{
|
||||
uint256 hash;
|
||||
// we're using a vector to avoid RAM thrashing and for faster serialization ops.
|
||||
// We're assuming its data is inserted in order and never modified.
|
||||
std::vector<std::string> children;
|
||||
|
||||
CClaimTrieDataNode() = default;
|
||||
CClaimTrieDataNode(CClaimTrieDataNode&&) = default;
|
||||
CClaimTrieDataNode(const CClaimTrieDataNode&) = default;
|
||||
CClaimTrieDataNode& operator=(CClaimTrieDataNode&&) = default;
|
||||
CClaimTrieDataNode& operator=(const CClaimTrieDataNode& d) = default;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
||||
{
|
||||
READWRITE(hash);
|
||||
READWRITE(children);
|
||||
}
|
||||
};
|
||||
|
||||
struct COutPointHeightType
|
||||
{
|
||||
COutPoint outPoint;
|
||||
|
@ -343,7 +365,9 @@ struct CClaimSupportToName
|
|||
const std::vector<CSupportValue> unmatchedSupports;
|
||||
};
|
||||
|
||||
class CClaimTrie : public CPrefixTrie<std::string, CClaimTrieData>
|
||||
typedef CPrefixTrie<std::string, CClaimTrieData> CClaimPrefixTrie;
|
||||
|
||||
class CClaimTrie
|
||||
{
|
||||
public:
|
||||
CClaimTrie() = default;
|
||||
|
@ -366,12 +390,24 @@ public:
|
|||
|
||||
std::size_t getTotalNamesInTrie() const;
|
||||
std::size_t getTotalClaimsInTrie() const;
|
||||
virtual bool checkConsistency(const uint256& rootHash) const;
|
||||
CAmount getTotalValueOfClaimsInTrie(bool fControllingOnly) const;
|
||||
|
||||
bool contains(const std::string& key) const;
|
||||
bool empty() const;
|
||||
bool find(const std::string& key, CClaimTrieDataNode& node) const;
|
||||
bool find(const std::string& key, CClaimTrieData& claims) const;
|
||||
|
||||
std::vector<std::pair<std::string, CClaimTrieDataNode>> nodes(const std::string& key) const;
|
||||
|
||||
protected:
|
||||
int nNextHeight = 0;
|
||||
int nProportionalDelayFactor = 0;
|
||||
std::unique_ptr<CDBWrapper> db;
|
||||
|
||||
CClaimPrefixTrie cacheNodes;
|
||||
using recurseNodesCB = void(const std::string&, const CClaimTrieData&, const std::vector<std::string>&);
|
||||
void recurseNodes(const std::string& name, const CClaimTrieDataNode& current, std::function<recurseNodesCB> function) const;
|
||||
};
|
||||
|
||||
struct CClaimTrieProofNode
|
||||
|
@ -486,7 +522,6 @@ public:
|
|||
|
||||
bool flush();
|
||||
bool empty() const;
|
||||
bool checkConsistency() const;
|
||||
bool ReadFromDisk(const CBlockIndex* tip);
|
||||
|
||||
bool haveClaim(const std::string& name, const COutPoint& outPoint) const;
|
||||
|
@ -527,20 +562,21 @@ public:
|
|||
|
||||
virtual CClaimSupportToName getClaimsForName(const std::string& name) const;
|
||||
|
||||
CClaimTrie::const_iterator find(const std::string& name) const;
|
||||
void iterate(std::function<void(const std::string&, const CClaimTrieData&)> callback) const;
|
||||
CClaimPrefixTrie::const_iterator begin() const;
|
||||
CClaimPrefixTrie::const_iterator end() const;
|
||||
|
||||
void dumpToLog(CClaimTrie::const_iterator it, bool diffFromBase = true) const;
|
||||
void dumpToLog(CClaimPrefixTrie::const_iterator it, bool diffFromBase = true) const;
|
||||
virtual std::string adjustNameForValidHeight(const std::string& name, int validHeight) const;
|
||||
|
||||
protected:
|
||||
void recurseNodes(const std::string& name, std::function<void(const std::string&, const CClaimTrieData&)> function) const;
|
||||
|
||||
protected:
|
||||
CClaimTrie* base;
|
||||
CClaimTrie nodesToAddOrUpdate; // nodes pulled in from base (and possibly modified thereafter), written to base on flush
|
||||
CClaimPrefixTrie nodesToAddOrUpdate; // nodes pulled in from base (and possibly modified thereafter), written to base on flush
|
||||
std::unordered_set<std::string> nodesAlreadyCached; // set of nodes already pulled into cache from base
|
||||
std::unordered_set<std::string> namesToCheckForTakeover; // takeover numbers are updated on increment
|
||||
|
||||
virtual uint256 recursiveComputeMerkleHash(CClaimTrie::iterator& it);
|
||||
virtual bool recursiveCheckConsistency(CClaimTrie::const_iterator& it, std::string& failed) const;
|
||||
virtual uint256 recursiveComputeMerkleHash(CClaimPrefixTrie::iterator& it);
|
||||
|
||||
virtual bool insertClaimIntoTrie(const std::string& name, const CClaimValue& claim, bool fCheckTakeover);
|
||||
virtual bool removeClaimFromTrie(const std::string& name, const COutPoint& outPoint, CClaimValue& claim, bool fCheckTakeover);
|
||||
|
@ -553,7 +589,7 @@ protected:
|
|||
int getDelayForName(const std::string& name) const;
|
||||
virtual int getDelayForName(const std::string& name, const uint160& claimId) const;
|
||||
|
||||
CClaimTrie::iterator cacheData(const std::string& name, bool create = true);
|
||||
CClaimPrefixTrie::iterator cacheData(const std::string& name, bool create = true);
|
||||
|
||||
bool getLastTakeoverForName(const std::string& name, uint160& claimId, int& takeoverHeight) const;
|
||||
|
||||
|
@ -584,6 +620,7 @@ private:
|
|||
std::unordered_set<std::string> nodesToDelete; // to be removed from base (and disk) on flush
|
||||
std::unordered_map<std::string, bool> takeoverWorkaround;
|
||||
std::unordered_set<std::string> removalWorkaround;
|
||||
std::unordered_set<std::string> forDeleteFromBase;
|
||||
|
||||
bool shouldUseTakeoverWorkaround(const std::string& key) const;
|
||||
void addTakeoverWorkaroundPotential(const std::string& key);
|
||||
|
@ -595,6 +632,8 @@ private:
|
|||
bool removeSupport(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight, bool fCheckTakeover);
|
||||
bool removeClaim(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight, bool fCheckTakeover);
|
||||
|
||||
bool validateTrieConsistency(const CBlockIndex* tip);
|
||||
|
||||
template <typename T>
|
||||
void insertRowsFromQueue(std::vector<T>& result, const std::string& name) const;
|
||||
|
||||
|
@ -741,16 +780,21 @@ public:
|
|||
void initializeIncrement() override;
|
||||
bool finalizeDecrement(std::vector<std::pair<std::string, int>>& takeoverHeightUndo) override;
|
||||
|
||||
bool allowSupportMetadata() const;
|
||||
|
||||
protected:
|
||||
uint256 recursiveComputeMerkleHash(CClaimTrie::iterator& it) override;
|
||||
bool recursiveCheckConsistency(CClaimTrie::const_iterator& it, std::string& failed) const override;
|
||||
uint256 recursiveComputeMerkleHash(CClaimPrefixTrie::iterator& it) override;
|
||||
|
||||
private:
|
||||
void copyAllBaseToCache();
|
||||
};
|
||||
|
||||
class CClaimTrieHashFork : public CClaimTrie
|
||||
{
|
||||
public:
|
||||
using CClaimTrie::CClaimTrie;
|
||||
protected:
|
||||
bool checkConsistency(const uint256& rootHash) const override;
|
||||
};
|
||||
|
||||
typedef CClaimTrieCacheHashFork CClaimTrieCache;
|
||||
|
||||
#endif // BITCOIN_CLAIMTRIE_H
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include <claimtrie.h>
|
||||
#include <hash.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/locale.hpp>
|
||||
#include <boost/locale/conversion.hpp>
|
||||
#include <boost/locale/localization_backend.hpp>
|
||||
|
@ -172,12 +174,17 @@ bool CClaimTrieCacheNormalizationFork::normalizeAllNamesInTrieIfNecessary(insert
|
|||
// run the one-time upgrade of all names that need to change
|
||||
// it modifies the (cache) trie as it goes, so we need to grab everything to be modified first
|
||||
|
||||
for (auto it = base->cbegin(); it != base->cend(); ++it) {
|
||||
const std::string normalized = normalizeClaimName(it.key(), true);
|
||||
if (normalized == it.key())
|
||||
boost::scoped_ptr<CDBIterator> pcursor(base->db->NewIterator());
|
||||
for (pcursor->SeekToFirst(); pcursor->Valid(); pcursor->Next()) {
|
||||
std::pair<uint8_t, std::string> key;
|
||||
if (!pcursor->GetKey(key) || key.first != TRIE_NODE_CHILDREN)
|
||||
continue;
|
||||
|
||||
const auto& name = key.second;
|
||||
const std::string normalized = normalizeClaimName(name, true);
|
||||
if (normalized == key.second)
|
||||
continue;
|
||||
|
||||
auto& name = it.key();
|
||||
auto supports = getSupportsForName(name);
|
||||
for (auto support : supports) {
|
||||
// if it's already going to expire just skip it
|
||||
|
@ -272,17 +279,23 @@ std::vector<uint256> getClaimHashes(const CClaimTrieData& data)
|
|||
template <typename T>
|
||||
using iCbType = std::function<uint256(T&)>;
|
||||
|
||||
template <typename TIterator>
|
||||
uint256 recursiveBinaryTreeHash(TIterator& it, const iCbType<TIterator>& process)
|
||||
template <typename T>
|
||||
using decay = typename std::decay<T>::type;
|
||||
|
||||
template <typename Vector, typename T>
|
||||
uint256 recursiveMerkleHash(const CClaimTrieData& data, Vector&& children, const iCbType<T>& childHash)
|
||||
{
|
||||
static_assert(std::is_same<decay<Vector>, std::vector<decay<T>>>::value, "Vector should be std vector");
|
||||
static_assert(std::is_same<decltype(children[0]), T&>::value, "Vector element type should match callback type");
|
||||
|
||||
std::vector<uint256> childHashes;
|
||||
for (auto& child : it.children())
|
||||
childHashes.emplace_back(process(child));
|
||||
for (auto& child : children)
|
||||
childHashes.emplace_back(childHash(child));
|
||||
|
||||
std::vector<uint256> claimHashes;
|
||||
if (!it->empty())
|
||||
claimHashes = getClaimHashes(it.data());
|
||||
else if (!it.hasChildren())
|
||||
if (!data.empty())
|
||||
claimHashes = getClaimHashes(data);
|
||||
else if (children.empty())
|
||||
return {};
|
||||
|
||||
auto left = childHashes.empty() ? leafHash : ComputeMerkleRoot(childHashes);
|
||||
|
@ -291,44 +304,53 @@ uint256 recursiveBinaryTreeHash(TIterator& it, const iCbType<TIterator>& process
|
|||
return Hash(left.begin(), left.end(), right.begin(), right.end());
|
||||
}
|
||||
|
||||
uint256 CClaimTrieCacheHashFork::recursiveComputeMerkleHash(CClaimTrie::iterator& it)
|
||||
extern const uint256 one;
|
||||
|
||||
bool CClaimTrieHashFork::checkConsistency(const uint256& rootHash) const
|
||||
{
|
||||
if (nNextHeight < Params().GetConsensus().nAllClaimsInMerkleForkHeight)
|
||||
return CClaimTrie::checkConsistency(rootHash);
|
||||
|
||||
CClaimTrieDataNode node;
|
||||
if (!find({}, node) || node.hash != rootHash) {
|
||||
if (rootHash == one)
|
||||
return true;
|
||||
|
||||
return error("Mismatched root claim trie hashes. This may happen when there is not a clean process shutdown. Please run with -reindex.");
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
recurseNodes({}, node, [&success, this](const std::string& name, const CClaimTrieData& data, const std::vector<std::string>& children) {
|
||||
if (!success) return;
|
||||
|
||||
iCbType<const std::string> callback = [&success, &name, this](const std::string& child) -> uint256 {
|
||||
auto key = name + child;
|
||||
CClaimTrieDataNode node;
|
||||
success &= find(key, node);
|
||||
return node.hash;
|
||||
};
|
||||
|
||||
success &= !data.hash.IsNull();
|
||||
success &= data.hash == recursiveMerkleHash(data, children, callback);
|
||||
});
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
uint256 CClaimTrieCacheHashFork::recursiveComputeMerkleHash(CClaimPrefixTrie::iterator& it)
|
||||
{
|
||||
if (nNextHeight < Params().GetConsensus().nAllClaimsInMerkleForkHeight)
|
||||
return CClaimTrieCacheNormalizationFork::recursiveComputeMerkleHash(it);
|
||||
|
||||
using iterator = CClaimTrie::iterator;
|
||||
using iterator = CClaimPrefixTrie::iterator;
|
||||
iCbType<iterator> process = [&process](iterator& it) -> uint256 {
|
||||
if (it->hash.IsNull())
|
||||
it->hash = recursiveBinaryTreeHash(it, process);
|
||||
assert(!it->hash.IsNull());
|
||||
it->hash = recursiveMerkleHash(it.data(), it.children(), process);
|
||||
return it->hash;
|
||||
};
|
||||
return process(it);
|
||||
}
|
||||
|
||||
bool CClaimTrieCacheHashFork::recursiveCheckConsistency(CClaimTrie::const_iterator& it, std::string& failed) const
|
||||
{
|
||||
if (nNextHeight < Params().GetConsensus().nAllClaimsInMerkleForkHeight)
|
||||
return CClaimTrieCacheNormalizationFork::recursiveCheckConsistency(it, failed);
|
||||
|
||||
struct CRecursiveBreak {};
|
||||
using iterator = CClaimTrie::const_iterator;
|
||||
iCbType<iterator> process = [&failed, &process](iterator& it) -> uint256 {
|
||||
if (it->hash.IsNull() || it->hash != recursiveBinaryTreeHash(it, process)) {
|
||||
failed = it.key();
|
||||
throw CRecursiveBreak();
|
||||
}
|
||||
return it->hash;
|
||||
};
|
||||
|
||||
try {
|
||||
process(it);
|
||||
} catch (const CRecursiveBreak&) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<uint256> ComputeMerklePath(const std::vector<uint256>& hashes, uint32_t idx)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
|
@ -404,7 +426,7 @@ bool CClaimTrieCacheHashFork::getProofForName(const std::string& name, CClaimTri
|
|||
cacheData(name, false);
|
||||
getMerkleHash();
|
||||
proof = CClaimTrieProof();
|
||||
for (auto& it : static_cast<const CClaimTrie&>(nodesToAddOrUpdate).nodes(name)) {
|
||||
for (auto& it : static_cast<const CClaimPrefixTrie&>(nodesToAddOrUpdate).nodes(name)) {
|
||||
std::vector<uint256> childHashes;
|
||||
uint32_t nextCurrentIdx = 0;
|
||||
for (auto& child : it.children()) {
|
||||
|
@ -447,12 +469,15 @@ bool CClaimTrieCacheHashFork::getProofForName(const std::string& name, CClaimTri
|
|||
|
||||
void CClaimTrieCacheHashFork::copyAllBaseToCache()
|
||||
{
|
||||
for (auto it = base->cbegin(); it != base->cend(); ++it)
|
||||
if (nodesAlreadyCached.insert(it.key()).second)
|
||||
nodesToAddOrUpdate.insert(it.key(), it.data());
|
||||
recurseNodes({}, [this](const std::string& name, const CClaimTrieData& data) {
|
||||
if (nodesAlreadyCached.insert(name).second)
|
||||
nodesToAddOrUpdate.insert(name, data);
|
||||
});
|
||||
|
||||
for (auto it = nodesToAddOrUpdate.begin(); it != nodesToAddOrUpdate.end(); ++it)
|
||||
for (auto it = nodesToAddOrUpdate.begin(); it != nodesToAddOrUpdate.end(); ++it) {
|
||||
it->hash.SetNull();
|
||||
it->flags |= CClaimTrieDataFlags::HASH_DIRTY;
|
||||
}
|
||||
}
|
||||
|
||||
void CClaimTrieCacheHashFork::initializeIncrement()
|
||||
|
@ -474,8 +499,3 @@ bool CClaimTrieCacheHashFork::finalizeDecrement(std::vector<std::pair<std::strin
|
|||
copyAllBaseToCache();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CClaimTrieCacheHashFork::allowSupportMetadata() const
|
||||
{
|
||||
return nNextHeight >= Params().GetConsensus().nAllClaimsInMerkleForkHeight;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include <util.h>
|
||||
#include <utilmoneystr.h>
|
||||
#include <utilstrencodings.h>
|
||||
#include <nameclaim.h>
|
||||
|
||||
UniValue ValueFromAmount(const CAmount& amount)
|
||||
{
|
||||
|
@ -148,20 +147,12 @@ void ScriptToUniv(const CScript& script, UniValue& out, bool include_address)
|
|||
out.pushKV("hex", HexStr(script.begin(), script.end()));
|
||||
|
||||
std::vector<std::vector<unsigned char>> solns;
|
||||
txnouttype type; int claimOp;
|
||||
auto stripped = StripClaimScriptPrefix(script, claimOp);
|
||||
Solver(stripped, type, solns);
|
||||
if (claimOp >= 0) {
|
||||
out.pushKV("isclaim", UniValue(claimOp == OP_CLAIM_NAME || claimOp == OP_UPDATE_CLAIM));
|
||||
out.pushKV("issupport", UniValue(claimOp == OP_SUPPORT_CLAIM));
|
||||
out.pushKV("subtype", GetTxnOutputType(type));
|
||||
out.pushKV("type", GetTxnOutputType(TX_NONSTANDARD)); // trying to keep backwards compatibility
|
||||
}
|
||||
else
|
||||
out.pushKV("type", GetTxnOutputType(type)); // trying to keep backwards compatibility
|
||||
txnouttype type;
|
||||
Solver(script, type, solns);
|
||||
out.pushKV("type", GetTxnOutputType(type));
|
||||
|
||||
CTxDestination address;
|
||||
if (include_address && ExtractDestination(stripped, address)) {
|
||||
if (include_address && ExtractDestination(script, address)) {
|
||||
out.pushKV("address", EncodeDestination(address));
|
||||
}
|
||||
}
|
||||
|
@ -177,28 +168,19 @@ void ScriptPubKeyToUniv(const CScript& scriptPubKey,
|
|||
if (fIncludeHex)
|
||||
out.pushKV("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end()));
|
||||
|
||||
int claimOp;
|
||||
auto stripped = StripClaimScriptPrefix(scriptPubKey, claimOp);
|
||||
auto extracted = ExtractDestinations(stripped, type, addresses, nRequired);
|
||||
if (extracted)
|
||||
out.pushKV("reqSigs", nRequired);
|
||||
|
||||
if (claimOp >= 0) {
|
||||
out.pushKV("isclaim", UniValue(claimOp == OP_CLAIM_NAME || claimOp == OP_UPDATE_CLAIM));
|
||||
out.pushKV("issupport", UniValue(claimOp == OP_SUPPORT_CLAIM));
|
||||
out.pushKV("subtype", GetTxnOutputType(type));
|
||||
out.pushKV("type", GetTxnOutputType(TX_NONSTANDARD));
|
||||
}
|
||||
else
|
||||
if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) {
|
||||
out.pushKV("type", GetTxnOutputType(type));
|
||||
|
||||
if (extracted) {
|
||||
UniValue a(UniValue::VARR);
|
||||
for (const CTxDestination &addr : addresses) {
|
||||
a.push_back(EncodeDestination(addr));
|
||||
}
|
||||
out.pushKV("addresses", a);
|
||||
return;
|
||||
}
|
||||
|
||||
out.pushKV("reqSigs", nRequired);
|
||||
out.pushKV("type", GetTxnOutputType(type));
|
||||
|
||||
UniValue a(UniValue::VARR);
|
||||
for (const CTxDestination& addr : addresses) {
|
||||
a.push_back(EncodeDestination(addr));
|
||||
}
|
||||
out.pushKV("addresses", a);
|
||||
}
|
||||
|
||||
void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex, int serialize_flags)
|
||||
|
|
|
@ -188,9 +188,6 @@ bool CDBWrapper::Sync() {
|
|||
|
||||
bool CDBWrapper::WriteBatch(CDBBatch& batch, bool fSync)
|
||||
{
|
||||
if (!pdb)
|
||||
return false;
|
||||
|
||||
const bool log_memory = LogAcceptCategory(BCLog::LEVELDB);
|
||||
double mem_before = 0;
|
||||
if (log_memory) {
|
||||
|
|
|
@ -151,7 +151,7 @@ public:
|
|||
* with a zero'd byte array.
|
||||
*/
|
||||
CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false, bool obfuscate = false);
|
||||
virtual ~CDBWrapper();
|
||||
~CDBWrapper();
|
||||
|
||||
CDBWrapper(const CDBWrapper&) = delete;
|
||||
/* CDBWrapper& operator=(const CDBWrapper&) = delete; */
|
||||
|
@ -159,7 +159,6 @@ public:
|
|||
template <typename K, typename V>
|
||||
bool Read(const K& key, V& value) const
|
||||
{
|
||||
assert(ssKey.empty());
|
||||
ssKey << key;
|
||||
leveldb::Slice slKey(ssKey.data(), ssKey.size());
|
||||
|
||||
|
|
|
@ -28,8 +28,6 @@ protected:
|
|||
DB(const fs::path& path, size_t n_cache_size,
|
||||
bool f_memory = false, bool f_wipe = false, bool f_obfuscate = false);
|
||||
|
||||
~DB() override {}
|
||||
|
||||
/// Read block locator of the chain that the txindex is in sync with.
|
||||
bool ReadBestBlock(CBlockLocator& locator) const;
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ class TxIndex::DB : public BaseIndex::DB
|
|||
{
|
||||
public:
|
||||
explicit DB(size_t n_cache_size, bool f_memory = false, bool f_wipe = false);
|
||||
~DB() override {}
|
||||
|
||||
/// Read the disk location of the transaction data with the given hash. Returns false if the
|
||||
/// transaction hash is not indexed.
|
||||
|
|
12
src/init.cpp
12
src/init.cpp
|
@ -22,7 +22,6 @@
|
|||
#include <httprpc.h>
|
||||
#include <index/txindex.h>
|
||||
#include <key.h>
|
||||
#include <lbry.h>
|
||||
#include <validation.h>
|
||||
#include <miner.h>
|
||||
#include <netbase.h>
|
||||
|
@ -399,7 +398,6 @@ void SetupServerArgs()
|
|||
hidden_args.emplace_back("-sysperms");
|
||||
#endif
|
||||
gArgs.AddArg("-txindex", strprintf("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)", DEFAULT_TXINDEX), false, OptionsCategory::OPTIONS);
|
||||
gArgs.AddArg("-memfile=<GiB>", "Use a memory mapped file for the claimtrie allocations (default: use RAM instead)", false, OptionsCategory::OPTIONS);
|
||||
|
||||
gArgs.AddArg("-addnode=<ip>", "Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info). This option can be specified multiple times to add multiple nodes.", false, OptionsCategory::CONNECTION);
|
||||
gArgs.AddArg("-banscore=<n>", strprintf("Threshold for disconnecting misbehaving peers (default: %u)", DEFAULT_BANSCORE_THRESHOLD), false, OptionsCategory::CONNECTION);
|
||||
|
@ -486,6 +484,7 @@ void SetupServerArgs()
|
|||
CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MAXFEE)), false, OptionsCategory::DEBUG_TEST);
|
||||
gArgs.AddArg("-printpriority", strprintf("Log transaction fee per kB when mining blocks (default: %u)", DEFAULT_PRINTPRIORITY), true, OptionsCategory::DEBUG_TEST);
|
||||
gArgs.AddArg("-printtoconsole", "Send trace/debug info to console (default: 1 when no -daemon. To disable logging to file, set -nodebuglogfile)", false, OptionsCategory::DEBUG_TEST);
|
||||
gArgs.AddArg("-shrinkdebugfile", "Shrink debug.log file on client startup (default: 1 when no -debug)", false, OptionsCategory::DEBUG_TEST);
|
||||
gArgs.AddArg("-uacomment=<cmt>", "Append comment to the user agent string", false, OptionsCategory::DEBUG_TEST);
|
||||
|
||||
SetupChainParamsBaseOptions();
|
||||
|
@ -1235,6 +1234,11 @@ bool AppInitMain()
|
|||
CreatePidFile(GetPidFile(), getpid());
|
||||
#endif
|
||||
if (g_logger->m_print_to_file) {
|
||||
if (gArgs.GetBoolArg("-shrinkdebugfile", g_logger->DefaultShrinkDebugFile())) {
|
||||
// Do this first since it both loads a bunch of debug.log into memory,
|
||||
// and because this needs to happen before any other debug.log printing
|
||||
g_logger->ShrinkDebugFile();
|
||||
}
|
||||
if (!g_logger->OpenDebugLog()) {
|
||||
return InitError(strprintf("Could not open debug log file %s",
|
||||
g_logger->m_file_path.string()));
|
||||
|
@ -1437,8 +1441,6 @@ bool AppInitMain()
|
|||
LogPrintf("* Using %.1fMiB for chain state database\n", nCoinDBCache * (1.0 / 1024 / 1024));
|
||||
LogPrintf("* Using %.1fMiB for in-memory UTXO set (plus up to %.1fMiB of unused mempool space)\n", nCoinCacheUsage * (1.0 / 1024 / 1024), nMempoolSizeMax * (1.0 / 1024 / 1024));
|
||||
|
||||
g_memfileSize = gArgs.GetArg("-memfile", 0u);
|
||||
|
||||
bool fLoaded = false;
|
||||
while (!fLoaded && !ShutdownRequested()) {
|
||||
bool fReset = fReindex;
|
||||
|
@ -1463,7 +1465,7 @@ bool AppInitMain()
|
|||
int64_t trieCacheMB = gArgs.GetArg("-claimtriecache", nDefaultDbCache);
|
||||
trieCacheMB = std::min(trieCacheMB, nMaxDbCache);
|
||||
trieCacheMB = std::max(trieCacheMB, nMinDbCache);
|
||||
pclaimTrie = new CClaimTrie(false, fReindex || fReindexChainState, 32, trieCacheMB);
|
||||
pclaimTrie = new CClaimTrieHashFork(false, fReindex || fReindexChainState, 32, trieCacheMB);
|
||||
|
||||
if (fReset) {
|
||||
pblocktree->WriteReindexing(true);
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
#include <cstdio>
|
||||
|
||||
uint32_t g_memfileSize = 0;
|
||||
|
||||
unsigned int CalculateLbryNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
|
||||
{
|
||||
if (params.fPowNoRetargeting)
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include <chain.h>
|
||||
#include <chainparams.h>
|
||||
|
||||
extern uint32_t g_memfileSize;
|
||||
unsigned int CalculateLbryNextWorkRequired(const CBlockIndex* pindexLast, int64_t nLastRetargetTime, const Consensus::Params& params);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -37,12 +37,6 @@ bool BCLog::Logger::OpenDebugLog()
|
|||
assert(m_fileout == nullptr);
|
||||
assert(!m_file_path.empty());
|
||||
|
||||
if (fs::exists(m_file_path)) {
|
||||
fs::path old_file_path(m_file_path);
|
||||
old_file_path += ".old";
|
||||
fs::rename(m_file_path, old_file_path);
|
||||
}
|
||||
|
||||
m_fileout = fsbridge::fopen(m_file_path, "a");
|
||||
if (!m_fileout) {
|
||||
return false;
|
||||
|
@ -89,6 +83,11 @@ bool BCLog::Logger::WillLogCategory(BCLog::LogFlags category) const
|
|||
return (m_categories.load(std::memory_order_relaxed) & category) != 0;
|
||||
}
|
||||
|
||||
bool BCLog::Logger::DefaultShrinkDebugFile() const
|
||||
{
|
||||
return m_categories == BCLog::NONE;
|
||||
}
|
||||
|
||||
struct CLogCategoryDesc
|
||||
{
|
||||
BCLog::LogFlags flag;
|
||||
|
@ -232,3 +231,44 @@ void BCLog::Logger::LogPrintStr(const std::string &str)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BCLog::Logger::ShrinkDebugFile()
|
||||
{
|
||||
// Amount of debug.log to save at end when shrinking (must fit in memory)
|
||||
constexpr size_t RECENT_DEBUG_HISTORY_SIZE = 10 * 1000000;
|
||||
|
||||
assert(!m_file_path.empty());
|
||||
|
||||
// Scroll debug.log if it's getting too big
|
||||
FILE* file = fsbridge::fopen(m_file_path, "r");
|
||||
|
||||
// Special files (e.g. device nodes) may not have a size.
|
||||
size_t log_size = 0;
|
||||
try {
|
||||
log_size = fs::file_size(m_file_path);
|
||||
} catch (boost::filesystem::filesystem_error &) {}
|
||||
|
||||
// If debug.log file is more than 10% bigger the RECENT_DEBUG_HISTORY_SIZE
|
||||
// trim it down by saving only the last RECENT_DEBUG_HISTORY_SIZE bytes
|
||||
if (file && log_size > 11 * (RECENT_DEBUG_HISTORY_SIZE / 10))
|
||||
{
|
||||
// Restart the file with some of the end
|
||||
std::vector<char> vch(RECENT_DEBUG_HISTORY_SIZE, 0);
|
||||
if (fseek(file, -((long)vch.size()), SEEK_END)) {
|
||||
LogPrintf("Failed to shrink debug log file: fseek(...) failed\n");
|
||||
fclose(file);
|
||||
return;
|
||||
}
|
||||
int nBytes = fread(vch.data(), 1, vch.size(), file);
|
||||
fclose(file);
|
||||
|
||||
file = fsbridge::fopen(m_file_path, "w");
|
||||
if (file)
|
||||
{
|
||||
fwrite(vch.data(), 1, nBytes, file);
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
else if (file != nullptr)
|
||||
fclose(file);
|
||||
}
|
||||
|
|
|
@ -93,6 +93,7 @@ namespace BCLog {
|
|||
bool Enabled() const { return m_print_to_console || m_print_to_file; }
|
||||
|
||||
bool OpenDebugLog();
|
||||
void ShrinkDebugFile();
|
||||
|
||||
uint32_t GetCategoryMask() const { return m_categories.load(); }
|
||||
|
||||
|
@ -102,6 +103,8 @@ namespace BCLog {
|
|||
bool DisableCategory(const std::string& str);
|
||||
|
||||
bool WillLogCategory(LogFlags category) const;
|
||||
|
||||
bool DefaultShrinkDebugFile() const;
|
||||
};
|
||||
|
||||
} // namespace BCLog
|
||||
|
|
|
@ -208,7 +208,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
|
|||
CValidationState state;
|
||||
if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) {
|
||||
if (!trieCache.empty())
|
||||
trieCache.dumpToLog(trieCache.find({}));
|
||||
trieCache.dumpToLog(trieCache.begin());
|
||||
throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state)));
|
||||
}
|
||||
int64_t nTime2 = GetTimeMicros();
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#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)
|
||||
{
|
||||
|
@ -18,7 +21,7 @@ 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\n", __func__);
|
||||
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];
|
||||
|
@ -34,17 +37,11 @@ CScript ClaimNameScript(std::string name, std::string value, bool fakeSuffix)
|
|||
return ret;
|
||||
}
|
||||
|
||||
CScript SupportClaimScript(std::string name, uint160 claimId, std::string value, bool fakeSuffix)
|
||||
CScript SupportClaimScript(std::string name, uint160 claimId, bool fakeSuffix)
|
||||
{
|
||||
std::vector<unsigned char> vchName(name.begin(), name.end());
|
||||
std::vector<unsigned char> vchClaimId(claimId.begin(), claimId.end());
|
||||
CScript ret;
|
||||
if (value.empty())
|
||||
ret = CScript() << OP_SUPPORT_CLAIM << vchName << vchClaimId << OP_2DROP << OP_DROP;
|
||||
else {
|
||||
std::vector<unsigned char> vchValue(value.begin(), value.end());
|
||||
ret = CScript() << OP_SUPPORT_CLAIM << vchName << vchClaimId << vchValue << OP_2DROP << OP_2DROP;
|
||||
}
|
||||
auto ret = CScript() << OP_SUPPORT_CLAIM << vchName << vchClaimId << OP_2DROP << OP_DROP;
|
||||
if (fakeSuffix) ret.push_back(OP_TRUE);
|
||||
return ret;
|
||||
}
|
||||
|
@ -57,15 +54,14 @@ CScript UpdateClaimScript(std::string name, uint160 claimId, std::string value)
|
|||
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, bool allowSupportMetadata)
|
||||
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, allowSupportMetadata);
|
||||
return DecodeClaimScript(scriptIn, op, vvchParams, pc);
|
||||
}
|
||||
|
||||
bool DecodeClaimScript(const CScript& scriptIn, int& op, std::vector<std::vector<unsigned char> >& vvchParams, CScript::const_iterator& pc, bool allowSupportMetadata)
|
||||
bool DecodeClaimScript(const CScript& scriptIn, int& op, std::vector<std::vector<unsigned char> >& vvchParams, CScript::const_iterator& pc)
|
||||
{
|
||||
op = -1;
|
||||
opcodetype opcode;
|
||||
if (!scriptIn.GetOp(pc, opcode))
|
||||
{
|
||||
|
@ -86,7 +82,6 @@ bool DecodeClaimScript(const CScript& scriptIn, int& op, std::vector<std::vector
|
|||
// 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
|
||||
// OP_SUPPORT_CLAIM vchName vchClaimId vchValue OP_2DROP OP_2DROP pubkeyscript
|
||||
// All others are invalid.
|
||||
|
||||
if (!scriptIn.GetOp(pc, opcode, vchParam1) || opcode < 0 || opcode > OP_PUSHDATA4)
|
||||
|
@ -104,42 +99,35 @@ bool DecodeClaimScript(const CScript& scriptIn, int& op, std::vector<std::vector
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!scriptIn.GetOp(pc, opcode, vchParam3))
|
||||
if (op == OP_UPDATE_CLAIM)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
auto last_drop = OP_DROP;
|
||||
if (opcode >= 0 && opcode <= OP_PUSHDATA4 && op != OP_CLAIM_NAME)
|
||||
{
|
||||
if (!scriptIn.GetOp(pc, opcode))
|
||||
if (!scriptIn.GetOp(pc, opcode, vchParam3) || opcode < 0 || opcode > OP_PUSHDATA4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
last_drop = OP_2DROP;
|
||||
}
|
||||
else if (op == OP_UPDATE_CLAIM)
|
||||
if (!scriptIn.GetOp(pc, opcode) || opcode != OP_2DROP)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (opcode != OP_2DROP)
|
||||
if (!scriptIn.GetOp(pc, opcode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!scriptIn.GetOp(pc, opcode) || opcode != last_drop)
|
||||
if ((op == OP_CLAIM_NAME || op == OP_SUPPORT_CLAIM) && opcode != OP_DROP)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (op == OP_SUPPORT_CLAIM && last_drop == OP_2DROP && !allowSupportMetadata)
|
||||
else if ((op == OP_UPDATE_CLAIM) && opcode != OP_2DROP)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
vvchParams.push_back(std::move(vchParam1));
|
||||
vvchParams.push_back(std::move(vchParam2));
|
||||
if (last_drop == OP_2DROP)
|
||||
vvchParams.push_back(vchParam1);
|
||||
vvchParams.push_back(vchParam2);
|
||||
if (op == OP_UPDATE_CLAIM)
|
||||
{
|
||||
vvchParams.push_back(std::move(vchParam3));
|
||||
vvchParams.push_back(vchParam3);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -200,7 +188,7 @@ CAmount CalcMinClaimTrieFee(const CTransaction& tx, const CAmount &minFeePerName
|
|||
}
|
||||
|
||||
CAmount min_fee = 0;
|
||||
for (const CTxOut& txout: tx.vout)
|
||||
BOOST_FOREACH(const CTxOut& txout, tx.vout)
|
||||
{
|
||||
int op;
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
// 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 character is assigned a trie node regardless of whether it contains
|
||||
// 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.
|
||||
|
@ -26,10 +26,10 @@
|
|||
#define MAX_CLAIM_NAME_SIZE 255
|
||||
|
||||
CScript ClaimNameScript(std::string name, std::string value, bool fakeSuffix=true);
|
||||
CScript SupportClaimScript(std::string name, uint160 claimId, std::string value="", bool fakeSuffix=true);
|
||||
CScript SupportClaimScript(std::string name, uint160 claimId, bool fakeSuffix=true);
|
||||
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 allowSupportMetadata=true);
|
||||
bool DecodeClaimScript(const CScript& scriptIn, int& op, std::vector<std::vector<unsigned char> >& vvchParams, CScript::const_iterator& pc, bool allowSupportMetadata=true);
|
||||
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);
|
||||
|
|
|
@ -115,7 +115,7 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason)
|
|||
unsigned int nDataOut = 0;
|
||||
txnouttype whichType;
|
||||
for (const CTxOut& txout : tx.vout) {
|
||||
if (!::IsStandard(StripClaimScriptPrefix(txout.scriptPubKey), whichType)) {
|
||||
if (!::IsStandard(txout.scriptPubKey, whichType)) {
|
||||
reason = "scriptpubkey";
|
||||
return false;
|
||||
}
|
||||
|
@ -168,7 +168,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:
|
||||
if (!Solver(StripClaimScriptPrefix(prev.scriptPubKey), whichType, vSolutions))
|
||||
if (!Solver(prev.scriptPubKey, whichType, vSolutions))
|
||||
return false;
|
||||
|
||||
if (whichType == TX_SCRIPTHASH)
|
||||
|
|
|
@ -45,7 +45,7 @@ static const unsigned int MAX_STANDARD_P2WSH_SCRIPT_SIZE = 3600;
|
|||
* standard and should be done with care and ideally rarely. It makes sense to
|
||||
* only increase the dust limit after prior releases were already not creating
|
||||
* outputs below the new threshold */
|
||||
static const unsigned int DUST_RELAY_TX_FEE = 1000;
|
||||
static const unsigned int DUST_RELAY_TX_FEE = 3000;
|
||||
/**
|
||||
* Standard script verification flags that standard transactions will comply
|
||||
* with. However scripts violating these flags may still be present in valid
|
||||
|
|
|
@ -1,79 +1,6 @@
|
|||
|
||||
#include <claimtrie.h>
|
||||
#include <fs.h>
|
||||
#include <lbry.h>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <prefixtrie.h>
|
||||
|
||||
#include <boost/interprocess/allocators/private_node_allocator.hpp>
|
||||
#include <boost/interprocess/indexes/null_index.hpp>
|
||||
#include <boost/interprocess/managed_mapped_file.hpp>
|
||||
|
||||
namespace bip = boost::interprocess;
|
||||
|
||||
typedef bip::basic_managed_mapped_file <
|
||||
char,
|
||||
bip::rbtree_best_fit<bip::null_mutex_family, bip::offset_ptr<void>>,
|
||||
bip::null_index
|
||||
> managed_mapped_file;
|
||||
|
||||
template <typename T>
|
||||
using node_allocator = bip::private_node_allocator<T, managed_mapped_file::segment_manager>;
|
||||
|
||||
static managed_mapped_file::segment_manager* segmentManager()
|
||||
{
|
||||
struct CSharedMemoryFile
|
||||
{
|
||||
CSharedMemoryFile() : file(GetDataDir() / "shared.mem")
|
||||
{
|
||||
fs::remove(file);
|
||||
auto size = (uint64_t)g_memfileSize * 1024ULL * 1024ULL * 1024ULL;
|
||||
// using string() to remove w_char filename encoding on Windows
|
||||
menaged_file.reset(new managed_mapped_file(bip::create_only, file.string().c_str(), size));
|
||||
}
|
||||
~CSharedMemoryFile()
|
||||
{
|
||||
menaged_file.reset();
|
||||
fs::remove(file);
|
||||
}
|
||||
managed_mapped_file::segment_manager* segmentManager()
|
||||
{
|
||||
return menaged_file->get_segment_manager();
|
||||
}
|
||||
const fs::path file;
|
||||
std::unique_ptr<managed_mapped_file> menaged_file;
|
||||
};
|
||||
static CSharedMemoryFile shem;
|
||||
return shem.segmentManager();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static node_allocator<T>& nodeAllocator()
|
||||
{
|
||||
static node_allocator<T> allocator(segmentManager());
|
||||
return allocator;
|
||||
}
|
||||
|
||||
template <typename T, class... Args>
|
||||
static std::shared_ptr<T> nodeAllocate(Args&&... args)
|
||||
{
|
||||
return std::allocate_shared<T>(nodeAllocator<T>(), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, class... Args>
|
||||
static std::shared_ptr<T> allocateShared(Args&&... args)
|
||||
{
|
||||
static auto allocate = g_memfileSize ? nodeAllocate<T, Args...> : std::make_shared<T, Args...>;
|
||||
try {
|
||||
return allocate(std::forward<Args>(args)...);
|
||||
}
|
||||
catch (const bip::bad_alloc&) {
|
||||
allocate = std::make_shared<T, Args...>; // in case we fill up the memfile
|
||||
LogPrint(BCLog::BENCH, "WARNING: The memfile is full; reverting to the RAM allocator for %s.\n", typeid(T).name());
|
||||
return allocate(std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
#include "prefixtrie.h"
|
||||
#include "claimtrie.h"
|
||||
|
||||
template <typename TKey, typename TData>
|
||||
template <bool IsConst>
|
||||
|
@ -91,7 +18,7 @@ typename CPrefixTrie<TKey, TData>::template Iterator<IsConst>& CPrefixTrie<TKey,
|
|||
stack.clear();
|
||||
stack.reserve(o.stack.size());
|
||||
for (auto& i : o.stack)
|
||||
stack.push_back(Bookmark{i.name, i.it, i.end});
|
||||
stack.push_back(Bookmark{i.name, i.parent, i.it, i.end});
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -121,7 +48,7 @@ typename CPrefixTrie<TKey, TData>::template Iterator<IsConst>& CPrefixTrie<TKey,
|
|||
if (!shared->children.empty()) {
|
||||
auto& children = shared->children;
|
||||
auto it = children.begin();
|
||||
stack.emplace_back(Bookmark{name, it, children.end()});
|
||||
stack.emplace_back(Bookmark{name, shared, it, children.end()});
|
||||
auto& postfix = it->first;
|
||||
name.insert(name.end(), postfix.begin(), postfix.end());
|
||||
node = it->second;
|
||||
|
@ -179,30 +106,20 @@ bool CPrefixTrie<TKey, TData>::Iterator<IsConst>::operator!=(const Iterator& o)
|
|||
|
||||
template <typename TKey, typename TData>
|
||||
template <bool IsConst>
|
||||
typename CPrefixTrie<TKey, TData>::template Iterator<IsConst>::reference CPrefixTrie<TKey, TData>::Iterator<IsConst>::operator*()
|
||||
typename CPrefixTrie<TKey, TData>::template Iterator<IsConst>::reference CPrefixTrie<TKey, TData>::Iterator<IsConst>::operator*() const
|
||||
{
|
||||
return reference{name, data()};
|
||||
auto shared = node.lock();
|
||||
assert(shared);
|
||||
return TPair(name, *(shared->data));
|
||||
}
|
||||
|
||||
template <typename TKey, typename TData>
|
||||
template <bool IsConst>
|
||||
typename CPrefixTrie<TKey, TData>::template Iterator<IsConst>::const_reference CPrefixTrie<TKey, TData>::Iterator<IsConst>::operator*() const
|
||||
typename CPrefixTrie<TKey, TData>::template Iterator<IsConst>::pointer CPrefixTrie<TKey, TData>::Iterator<IsConst>::operator->() const
|
||||
{
|
||||
return const_reference{name, data()};
|
||||
}
|
||||
|
||||
template <typename TKey, typename TData>
|
||||
template <bool IsConst>
|
||||
typename CPrefixTrie<TKey, TData>::template Iterator<IsConst>::pointer CPrefixTrie<TKey, TData>::Iterator<IsConst>::operator->()
|
||||
{
|
||||
return &(data());
|
||||
}
|
||||
|
||||
template <typename TKey, typename TData>
|
||||
template <bool IsConst>
|
||||
typename CPrefixTrie<TKey, TData>::template Iterator<IsConst>::const_pointer CPrefixTrie<TKey, TData>::Iterator<IsConst>::operator->() const
|
||||
{
|
||||
return &(data());
|
||||
auto shared = node.lock();
|
||||
assert(shared);
|
||||
return shared->data.get();
|
||||
}
|
||||
|
||||
template <typename TKey, typename TData>
|
||||
|
@ -214,7 +131,7 @@ const TKey& CPrefixTrie<TKey, TData>::Iterator<IsConst>::key() const
|
|||
|
||||
template <typename TKey, typename TData>
|
||||
template <bool IsConst>
|
||||
typename CPrefixTrie<TKey, TData>::template Iterator<IsConst>::data_reference CPrefixTrie<TKey, TData>::Iterator<IsConst>::data()
|
||||
typename CPrefixTrie<TKey, TData>::template Iterator<IsConst>::TDataRef CPrefixTrie<TKey, TData>::Iterator<IsConst>::data()
|
||||
{
|
||||
auto shared = node.lock();
|
||||
assert(shared);
|
||||
|
@ -327,7 +244,7 @@ std::shared_ptr<typename CPrefixTrie<TKey, TData>::Node>& CPrefixTrie<TKey, TDat
|
|||
}
|
||||
if (count == 0) {
|
||||
++size;
|
||||
it = children.emplace(key, allocateShared<Node>()).first;
|
||||
it = children.emplace(key, std::make_shared<Node>()).first;
|
||||
return it->second;
|
||||
}
|
||||
if (count < it->first.size()) {
|
||||
|
@ -336,11 +253,11 @@ std::shared_ptr<typename CPrefixTrie<TKey, TData>::Node>& CPrefixTrie<TKey, TDat
|
|||
auto nodes = std::move(it->second);
|
||||
children.erase(it);
|
||||
++size;
|
||||
it = children.emplace(std::move(prefix), allocateShared<Node>()).first;
|
||||
it = children.emplace(std::move(prefix), std::make_shared<Node>()).first;
|
||||
it->second->children.emplace(std::move(postfix), std::move(nodes));
|
||||
if (key.size() == count)
|
||||
return it->second;
|
||||
it->second->data = allocateShared<TData>();
|
||||
it->second->data = std::make_shared<TData>();
|
||||
}
|
||||
return insert(TKey(key.begin() + count, key.end()), it->second);
|
||||
}
|
||||
|
@ -357,7 +274,7 @@ void CPrefixTrie<TKey, TData>::erase(const TKey& key, std::shared_ptr<Node>& nod
|
|||
if (!find(key, node, cb))
|
||||
return;
|
||||
|
||||
nodes.back().second->data = allocateShared<TData>();
|
||||
nodes.back().second->data = std::make_shared<TData>();
|
||||
for (; nodes.size() > 1; nodes.pop_back()) {
|
||||
// if we have only one child and no data ourselves, bring them up to our level
|
||||
auto& cNode = nodes.back().second;
|
||||
|
@ -388,9 +305,9 @@ void CPrefixTrie<TKey, TData>::erase(const TKey& key, std::shared_ptr<Node>& nod
|
|||
}
|
||||
|
||||
template <typename TKey, typename TData>
|
||||
CPrefixTrie<TKey, TData>::CPrefixTrie() : size(0), root(allocateShared<Node>())
|
||||
CPrefixTrie<TKey, TData>::CPrefixTrie() : size(0), root(std::make_shared<Node>())
|
||||
{
|
||||
root->data = allocateShared<TData>();
|
||||
root->data = std::make_shared<TData>();
|
||||
}
|
||||
|
||||
template <typename TKey, typename TData>
|
||||
|
@ -398,17 +315,19 @@ template <typename TDataUni>
|
|||
typename CPrefixTrie<TKey, TData>::iterator CPrefixTrie<TKey, TData>::insert(const TKey& key, TDataUni&& data)
|
||||
{
|
||||
auto& node = key.empty() ? root : insert(key, root);
|
||||
node->data = allocateShared<TData>(std::forward<TDataUni>(data));
|
||||
node->data = std::make_shared<TData>(std::forward<TDataUni>(data));
|
||||
return key.empty() ? begin() : iterator{key, node};
|
||||
}
|
||||
|
||||
template <typename TKey, typename TData>
|
||||
typename CPrefixTrie<TKey, TData>::iterator CPrefixTrie<TKey, TData>::copy(CPrefixTrie<TKey, TData>::const_iterator it)
|
||||
typename CPrefixTrie<TKey, TData>::iterator CPrefixTrie<TKey, TData>::copy(CPrefixTrie<TKey, TData>::const_iterator it, bool wipeChildren)
|
||||
{
|
||||
auto& key = it.key();
|
||||
auto& node = key.empty() ? root : insert(key, root);
|
||||
node->data = it.node.lock()->data;
|
||||
return key.empty() ? begin() : iterator{key, node};
|
||||
if (wipeChildren)
|
||||
node->children.clear();
|
||||
return iterator{key, node};
|
||||
}
|
||||
|
||||
template <typename TKey, typename TData>
|
||||
|
@ -422,9 +341,9 @@ typename CPrefixTrie<TKey, TData>::iterator CPrefixTrie<TKey, TData>::insert(CPr
|
|||
auto name = it.key();
|
||||
name.insert(name.end(), key.begin(), key.end());
|
||||
auto& node = insert(key, shared);
|
||||
copy = iterator{std::move(name), node};
|
||||
copy = iterator{name, node};
|
||||
}
|
||||
copy.node.lock()->data = allocateShared<TData>(std::forward<TDataUni>(data));
|
||||
copy.node.lock()->data = std::make_shared<TData>(std::forward<TDataUni>(data));
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
@ -493,7 +412,7 @@ bool CPrefixTrie<TKey, TData>::erase(const TKey& key)
|
|||
{
|
||||
auto size_was = height();
|
||||
if (key.empty()) {
|
||||
root->data = allocateShared<TData>();
|
||||
root->data = std::make_shared<TData>();
|
||||
} else {
|
||||
erase(key, root);
|
||||
}
|
||||
|
@ -504,7 +423,7 @@ template <typename TKey, typename TData>
|
|||
void CPrefixTrie<TKey, TData>::clear()
|
||||
{
|
||||
size = 0;
|
||||
root->data = allocateShared<TData>();
|
||||
root->data = std::make_shared<TData>();
|
||||
root->children.clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ class CPrefixTrie
|
|||
Node() = default;
|
||||
Node(const Node&) = delete;
|
||||
Node(Node&& o) noexcept = default;
|
||||
Node& operator=(Node&&) noexcept = default;
|
||||
Node& operator=(Node&& o) noexcept = default;
|
||||
Node& operator=(const Node&) = delete;
|
||||
std::shared_ptr<TData> data;
|
||||
};
|
||||
|
@ -41,16 +41,17 @@ class CPrefixTrie
|
|||
friend class Iterator;
|
||||
friend class CPrefixTrie<TKey, TData>;
|
||||
|
||||
using TKeyRef = std::reference_wrapper<const TKey>;
|
||||
using TDataRef = std::reference_wrapper<typename std::conditional<IsConst, const TData, TData>::type>;
|
||||
using TPair = std::pair<TKeyRef, TDataRef>;
|
||||
using ConstTPair = std::pair<TKeyRef, const TData>;
|
||||
using TDataRef = typename std::conditional<IsConst, const TData&, TData&>::type;
|
||||
using TKeyWrap = std::reference_wrapper<const TKey>;
|
||||
using TDataWrap = std::reference_wrapper<TData>;
|
||||
using TPair = std::pair<TKeyWrap, TDataWrap>;
|
||||
|
||||
TKey name;
|
||||
std::weak_ptr<Node> node;
|
||||
|
||||
struct Bookmark {
|
||||
TKey name;
|
||||
std::weak_ptr<Node> parent;
|
||||
typename TChildren::iterator it;
|
||||
typename TChildren::iterator end;
|
||||
};
|
||||
|
@ -60,11 +61,8 @@ class CPrefixTrie
|
|||
public:
|
||||
// Iterator traits
|
||||
using value_type = TPair;
|
||||
using const_pointer = const TData* const;
|
||||
using const_reference = ConstTPair;
|
||||
using data_reference = typename std::conditional<IsConst, const TData&, TData&>::type;
|
||||
using pointer = typename std::conditional<IsConst, const TData* const, TData* const>::type;
|
||||
using reference = typename std::conditional<IsConst, ConstTPair, TPair>::type;
|
||||
using reference = typename std::conditional<IsConst, const TPair, TPair>::type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
|
||||
|
@ -92,15 +90,12 @@ class CPrefixTrie
|
|||
bool operator==(const Iterator& o) const;
|
||||
bool operator!=(const Iterator& o) const;
|
||||
|
||||
reference operator*();
|
||||
const_reference operator*() const;
|
||||
|
||||
pointer operator->();
|
||||
const_pointer operator->() const;
|
||||
reference operator*() const;
|
||||
pointer operator->() const;
|
||||
|
||||
const TKey& key() const;
|
||||
|
||||
data_reference data();
|
||||
TDataRef data();
|
||||
const TData& data() const;
|
||||
|
||||
std::size_t depth() const;
|
||||
|
@ -138,7 +133,7 @@ public:
|
|||
template <typename TDataUni>
|
||||
iterator insert(iterator& it, const TKey& key, TDataUni&& data);
|
||||
|
||||
iterator copy(const_iterator it);
|
||||
iterator copy(const_iterator it, bool wipeChildren);
|
||||
|
||||
iterator find(const TKey& key);
|
||||
const_iterator find(const TKey& key) const;
|
||||
|
|
|
@ -17,7 +17,7 @@ static const struct {
|
|||
} network_styles[] = {
|
||||
{"lbrycrd", QAPP_APP_NAME_DEFAULT, 0, 0, ""},
|
||||
{"lbrycrdtest", QAPP_APP_NAME_TESTNET, 70, 30, QT_TRANSLATE_NOOP("SplashScreen", "[testnet]")},
|
||||
{"lbrycrdreg", QAPP_APP_NAME_REGTEST, 160, 30, "[regtest]"}
|
||||
{"regtest", QAPP_APP_NAME_REGTEST, 160, 30, "[regtest]"}
|
||||
};
|
||||
static const unsigned network_styles_count = sizeof(network_styles)/sizeof(*network_styles);
|
||||
|
||||
|
|
|
@ -228,11 +228,11 @@ void PaymentServer::ipcParseCommandLine(interfaces::Node& node, int argc, char*
|
|||
PaymentRequestPlus request;
|
||||
if (readPaymentRequestFromFile(arg, request))
|
||||
{
|
||||
if (request.getDetails().network() == CBaseChainParams::MAIN)
|
||||
if (request.getDetails().network() == "lbrycrd")
|
||||
{
|
||||
node.selectParams(CBaseChainParams::MAIN);
|
||||
}
|
||||
else if (request.getDetails().network() == CBaseChainParams::TESTNET)
|
||||
else if (request.getDetails().network() == "lbrycrdtest")
|
||||
{
|
||||
node.selectParams(CBaseChainParams::TESTNET);
|
||||
}
|
||||
|
|
|
@ -1310,18 +1310,16 @@ static UniValue getchaintips(const JSONRPCRequest& request)
|
|||
"\nResult:\n"
|
||||
"[\n"
|
||||
" {\n"
|
||||
" \"height\": xxxx, (numeric) height of the chain tip\n"
|
||||
" \"hash\": \"xxxx\", (string) block hash of the tip\n"
|
||||
" \"branchlen\": 0 (numeric) zero for main chain\n"
|
||||
" \"status\": \"active\" (string) \"active\" for the main chain\n"
|
||||
" \"height\": xxxx, (numeric) height of the chain tip\n"
|
||||
" \"hash\": \"xxxx\", (string) block hash of the tip\n"
|
||||
" \"branchlen\": 0 (numeric) zero for main chain\n"
|
||||
" \"status\": \"active\" (string) \"active\" for the main chain\n"
|
||||
" },\n"
|
||||
" {\n"
|
||||
" \"height\": xxxx,\n"
|
||||
" \"hash\": \"xxxx\",\n"
|
||||
" \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n"
|
||||
" \"branchhash\": \"xxxx\", (string) hash of the historical block where we branched\n"
|
||||
" \"branchhashNext\": \"xxxx\", (string) block hash of the first block down this chain\n"
|
||||
" \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n"
|
||||
" \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n"
|
||||
" \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n"
|
||||
" }\n"
|
||||
"]\n"
|
||||
"Possible values for status:\n"
|
||||
|
@ -1374,19 +1372,8 @@ static UniValue getchaintips(const JSONRPCRequest& request)
|
|||
obj.pushKV("height", block->nHeight);
|
||||
obj.pushKV("hash", block->phashBlock->GetHex());
|
||||
|
||||
// not use ForkAt method because we need the previous one as well
|
||||
const CBlockIndex *forkAt = block, *forkPrev = block;
|
||||
while (forkAt && !chainActive.Contains(forkAt)) {
|
||||
forkPrev = forkAt;
|
||||
forkAt = forkAt->pprev;
|
||||
}
|
||||
|
||||
const int branchLen = block->nHeight - forkAt->nHeight;
|
||||
const int branchLen = block->nHeight - chainActive.FindFork(block)->nHeight;
|
||||
obj.pushKV("branchlen", branchLen);
|
||||
if (forkAt != forkPrev) {
|
||||
obj.pushKV("branchhash", forkAt->phashBlock->GetHex());
|
||||
obj.pushKV("branchhashNext", forkPrev->phashBlock->GetHex());
|
||||
}
|
||||
|
||||
std::string status;
|
||||
if (chainActive.Contains(block)) {
|
||||
|
|
|
@ -128,7 +128,7 @@ S3(" ", T_LASTTAKEOVERHEIGHT, " (numeric) the last height at which owners
|
|||
static const char* const rpc_help[] = {
|
||||
|
||||
// GETCLAIMSINTRIE
|
||||
S1("getclaimsintrie ( \"" T_BLOCKHASH R"(" )
|
||||
S1(R"(getclaimsintrie
|
||||
Return all claims in the name trie. Deprecated
|
||||
Arguments:)")
|
||||
S3("1. ", T_BLOCKHASH, BLOCKHASH_TEXT)
|
||||
|
@ -148,7 +148,7 @@ S1(" ]")
|
|||
"]",
|
||||
|
||||
// GETNAMESINTRIE
|
||||
S1("getnamesintrie ( \"" T_BLOCKHASH R"(" )
|
||||
S1(R"(getnamesintrie
|
||||
Return all claim names in the trie.
|
||||
Arguments:)")
|
||||
S3("1. ", T_BLOCKHASH, BLOCKHASH_TEXT)
|
||||
|
@ -157,7 +157,7 @@ S3(" ", T_NAMES, " all names in the trie that have claims")
|
|||
"]",
|
||||
|
||||
// GETVALUEFORNAME
|
||||
S1("getvalueforname \"" T_NAME "\" ( \"" T_BLOCKHASH "\" \"" T_CLAIMID R"(" )
|
||||
S1(R"(getvalueforname
|
||||
Return the winning or specified by claimId value associated with a name
|
||||
Arguments:)")
|
||||
S3("1. ", T_NAME, NAME_TEXT)
|
||||
|
@ -168,7 +168,7 @@ CLAIM_OUTPUT
|
|||
"]",
|
||||
|
||||
// GETCLAIMSFORNAME
|
||||
S1("getclaimsforname \"" T_NAME "\" ( \"" T_BLOCKHASH R"(" )
|
||||
S1(R"(getclaimsforname
|
||||
Return all claims and supports for a name
|
||||
Arguments:)")
|
||||
S3("1. ", T_NAME, NAME_TEXT)
|
||||
|
@ -210,7 +210,7 @@ S1(" ]")
|
|||
"]",
|
||||
|
||||
// GETCLAIMBYID
|
||||
S1("getclaimbyid \"" T_CLAIMID R"("
|
||||
S1(R"(getclaimbyid
|
||||
Get a claim by claim id
|
||||
Arguments:)")
|
||||
S3("1. ", T_CLAIMID, " (string) the claimId of this claim or patial id (at least 3 chars)")
|
||||
|
@ -235,7 +235,7 @@ S3(" ", T_TOTALCLAIMS, " (numeric) the total number of active clai
|
|||
,
|
||||
|
||||
// GETTOTALVALUEOFCLAIMS
|
||||
S1("gettotalvalueofclaims ( " T_CONTROLLINGONLY R"( )
|
||||
S1(R"(gettotalvalueofclaims
|
||||
Return the total value of the claims in the trie
|
||||
Arguments:)")
|
||||
S3("1. ", T_CONTROLLINGONLY, " (boolean) only include the value of controlling claims")
|
||||
|
@ -244,7 +244,7 @@ S3(" ", T_TOTALVALUE, " (numeric) the total value of the claims i
|
|||
,
|
||||
|
||||
// GETCLAIMSFORTX
|
||||
S1("getclaimsfortx \"" T_TXID R"("
|
||||
S1(R"(getclaimsfortx
|
||||
Return any claims or supports found in a transaction
|
||||
Arguments:)")
|
||||
S3("1. ", T_TXID, " (string) the txid of the transaction to check for unspent claims")
|
||||
|
@ -263,7 +263,7 @@ S3(" ", T_BLOCKSTOVALID, " (numeric) if in a queue, the number of bl
|
|||
"]",
|
||||
|
||||
// GETNAMEPROOF
|
||||
S1("getnameproof \"" T_NAME "\" ( \"" T_BLOCKHASH "\" \"" T_CLAIMID R"(" )
|
||||
S1(R"(getnameproof
|
||||
Return the cryptographic proof that a name maps to a value or doesn't.
|
||||
Arguments:)")
|
||||
S3("1. ", T_NAME, NAME_TEXT)
|
||||
|
@ -275,7 +275,7 @@ PROOF_OUTPUT
|
|||
"]",
|
||||
|
||||
// CHECKNORMALIZATION
|
||||
S1("checknormalization \"" T_NAME R"("
|
||||
S1(R"(checknormalization
|
||||
Given an unnormalized name of a claim, return normalized version of it
|
||||
Arguments:)")
|
||||
S3("1. ", T_NAME, " (string) the name to normalize")
|
||||
|
@ -284,51 +284,51 @@ S3(" ", T_NORMALIZEDNAME, " (string) normalized name")
|
|||
,
|
||||
|
||||
// GETCLAIMBYBID
|
||||
S1("getclaimbybid \"" T_NAME "\" ( " T_BID " \"" T_BLOCKHASH R"(" )
|
||||
S1(R"(getclaimbybid
|
||||
Get a claim by bid
|
||||
Arguments:)")
|
||||
S3("1. ", T_NAME, NAME_TEXT)
|
||||
S3("2. ", T_BID, " (numeric, optional) bid number")
|
||||
S3("2. ", T_BID, " (numeric) bid number")
|
||||
S3("3. ", T_BLOCKHASH, BLOCKHASH_TEXT)
|
||||
S1("Result: [")
|
||||
CLAIM_OUTPUT
|
||||
"]",
|
||||
|
||||
// GETCLAIMBYSEQ
|
||||
S1("getclaimbyseq \"" T_NAME "\" ( " T_SEQUENCE " \"" T_BLOCKHASH R"(" )
|
||||
S1(R"(getclaimbyseq
|
||||
Get a claim by sequence
|
||||
Arguments:)")
|
||||
S3("1. ", T_NAME, NAME_TEXT)
|
||||
S3("2. ", T_SEQUENCE, " (numeric, optional) sequence number")
|
||||
S3("2. ", T_SEQUENCE, " (numeric) sequence number")
|
||||
S3("3. ", T_BLOCKHASH, BLOCKHASH_TEXT)
|
||||
S1("Result: [")
|
||||
CLAIM_OUTPUT
|
||||
"]",
|
||||
|
||||
// GETCLAIMPROOFBYBID
|
||||
S1("getclaimproofbyid \"" T_NAME "\" ( " T_BID " \"" T_BLOCKHASH R"(" )
|
||||
S1(R"(getclaimproofbyid
|
||||
Return the cryptographic proof that a name maps to a value or doesn't by a bid.
|
||||
Arguments:)")
|
||||
S3("1. ", T_NAME, NAME_TEXT)
|
||||
S3("2. ", T_BID, " (numeric, optional) bid number")
|
||||
S3("2. ", T_BID, " (numeric) bid number")
|
||||
S3("3. ", T_BLOCKHASH, BLOCKHASH_TEXT)
|
||||
S1("Result: [")
|
||||
PROOF_OUTPUT
|
||||
"]",
|
||||
|
||||
// GETCLAIMPROOFBYSEQ
|
||||
S1("getclaimproofbyseq \"" T_NAME "\" ( " T_SEQUENCE " \"" T_BLOCKHASH R"(" )
|
||||
S1(R"(getclaimproofbyseq
|
||||
Return the cryptographic proof that a name maps to a value or doesn't by a sequence.
|
||||
Arguments:)")
|
||||
S3("1. ", T_NAME, NAME_TEXT)
|
||||
S3("2. ", T_SEQUENCE, " (numeric, optional) sequence number")
|
||||
S3("2. ", T_SEQUENCE, " (numeric) sequence number")
|
||||
S3("3. ", T_BLOCKHASH, BLOCKHASH_TEXT)
|
||||
S1("Result: [")
|
||||
PROOF_OUTPUT
|
||||
"]",
|
||||
|
||||
// GETCHANGESINBLOCK
|
||||
S1("getchangesinblock ( \"" T_BLOCKHASH R"(" )
|
||||
S1(R"(getchangesinblock
|
||||
Return the list of claims added, updated, and removed as pulled from the queued work for that block."
|
||||
Use this method to determine which claims or supports went live on a given block."
|
||||
Arguments:)")
|
||||
|
|
|
@ -111,7 +111,7 @@ std::string escapeNonUtf8(const std::string& name)
|
|||
static bool extractValue(const CScript& scriptPubKey, std::string& sValue)
|
||||
{
|
||||
int op;
|
||||
std::vector<std::vector<unsigned char>> vvchParams;
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
if (!DecodeClaimScript(scriptPubKey, op, vvchParams))
|
||||
return false;
|
||||
|
||||
|
@ -307,7 +307,7 @@ static UniValue getclaimsintrie(const JSONRPCRequest& request)
|
|||
}
|
||||
|
||||
UniValue ret(UniValue::VARR);
|
||||
trieCache.iterate([&ret, &trieCache, &coinsCache] (const std::string& name, const CClaimTrieData& data) {
|
||||
trieCache.recurseNodes({}, [&ret, &trieCache, &coinsCache] (const std::string& name, const CClaimTrieData& data) {
|
||||
if (ShutdownRequested())
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Shutdown requested");
|
||||
|
||||
|
@ -348,7 +348,7 @@ static UniValue getnamesintrie(const JSONRPCRequest& request)
|
|||
}
|
||||
|
||||
UniValue ret(UniValue::VARR);
|
||||
trieCache.iterate([&ret](const std::string &name, const CClaimTrieData &data) {
|
||||
trieCache.recurseNodes({}, [&ret](const std::string &name, const CClaimTrieData &data) {
|
||||
if (!data.empty())
|
||||
ret.push_back(escapeNonUtf8(name));
|
||||
if (ShutdownRequested())
|
||||
|
@ -910,8 +910,8 @@ static const CRPCCommand commands[] =
|
|||
{ "hidden", "getclaimtrie", &getclaimtrie, { } },
|
||||
{ "Claimtrie", "getvalueforname", &getvalueforname, { T_NAME,T_BLOCKHASH,T_CLAIMID } },
|
||||
{ "Claimtrie", "getclaimsforname", &getclaimsforname, { T_NAME,T_BLOCKHASH } },
|
||||
{ "Claimtrie", "gettotalclaimednames", &gettotalclaimednames, { } },
|
||||
{ "Claimtrie", "gettotalclaims", &gettotalclaims, { } },
|
||||
{ "Claimtrie", "gettotalclaimednames", &gettotalclaimednames, { "" } },
|
||||
{ "Claimtrie", "gettotalclaims", &gettotalclaims, { "" } },
|
||||
{ "Claimtrie", "gettotalvalueofclaims", &gettotalvalueofclaims, { T_CONTROLLINGONLY } },
|
||||
{ "Claimtrie", "getclaimsfortx", &getclaimsfortx, { T_TXID } },
|
||||
{ "Claimtrie", "getnameproof", &getnameproof, { T_NAME,T_BLOCKHASH,T_CLAIMID } },
|
||||
|
|
|
@ -80,7 +80,6 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||
{ "scantxoutset", 1, "scanobjects" },
|
||||
{ "addmultisigaddress", 0, "nrequired" },
|
||||
{ "addmultisigaddress", 1, "keys" },
|
||||
{ "addtimelockedaddress", 0, "timelock" },
|
||||
{ "createmultisig", 0, "nrequired" },
|
||||
{ "createmultisig", 1, "keys" },
|
||||
{ "listunspent", 0, "minconf" },
|
||||
|
@ -180,7 +179,6 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||
{ "getclaimproofbybid", 1, "bid"},
|
||||
{ "getclaimproofbyseq", 1, "sequence"},
|
||||
{ "supportclaim", 4, "isTip"},
|
||||
{ "gettotalvalueofclaims", 0, "controlling_only"},
|
||||
};
|
||||
|
||||
class CRPCConvertTable
|
||||
|
|
|
@ -451,7 +451,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
|
|||
if (strMode != "template")
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
|
||||
|
||||
if (Params().NetworkIDString() == CBaseChainParams::MAIN)
|
||||
if (Params().NetworkIDString() != "lbrycrdreg") // who should own this constant?
|
||||
{
|
||||
if (!g_connman)
|
||||
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
|
||||
|
@ -567,8 +567,6 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
|
|||
|
||||
// NOTE: If at some point we support pre-segwit miners post-segwit-activation, this needs to take segwit support into consideration
|
||||
const bool fPreSegWit = (ThresholdState::ACTIVE != VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache));
|
||||
if (!fPreSegWit && !fSupportsSegwit)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Segwit support is now required. Please include \"segwit\" in the client's rules.");
|
||||
|
||||
UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
|
||||
UniValue result(UniValue::VOBJ);
|
||||
|
@ -623,6 +621,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
|
|||
aMutable.push_back("time");
|
||||
aMutable.push_back("transactions");
|
||||
aMutable.push_back("prevblock");
|
||||
aMutable.push_back("submit/coinbase");
|
||||
|
||||
result.pushKV("capabilities", aCaps);
|
||||
|
||||
|
|
|
@ -549,15 +549,14 @@ static UniValue decoderawtransaction(const JSONRPCRequest& request)
|
|||
" ],\n"
|
||||
" \"vout\" : [ (array of json objects)\n"
|
||||
" {\n"
|
||||
" \"value\" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + "\n"
|
||||
" \"n\" : n, (numeric) index\n"
|
||||
" \"scriptPubKey\" : { (json object)\n"
|
||||
" \"asm\" : \"asm\", (string) the asm\n"
|
||||
" \"hex\" : \"hex\", (string) the hex\n"
|
||||
" \"reqSigs\" : n, (numeric) The required sigs\n"
|
||||
" \"subtype\" : \"pubkeyhash\", (numeric) For claims and supports, this represents the type of suffix\n"
|
||||
" \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
|
||||
" \"addresses\" : [ (json array of string)\n"
|
||||
" \"value\" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + "\n"
|
||||
" \"n\" : n, (numeric) index\n"
|
||||
" \"scriptPubKey\" : { (json object)\n"
|
||||
" \"asm\" : \"asm\", (string) the asm\n"
|
||||
" \"hex\" : \"hex\", (string) the hex\n"
|
||||
" \"reqSigs\" : n, (numeric) The required sigs\n"
|
||||
" \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n"
|
||||
" \"addresses\" : [ (json array of string)\n"
|
||||
" \"12tvKAXCxZjSmdNbao16dKXC8tRWfcF5oc\" (string) lbry address\n"
|
||||
" ,...\n"
|
||||
" ]\n"
|
||||
|
|
|
@ -64,20 +64,8 @@ void CScheduler::serviceQueue()
|
|||
// Explicitly use a template here to avoid hitting that overload.
|
||||
while (!shouldStop() && !taskQueue.empty()) {
|
||||
boost::chrono::system_clock::time_point timeToWaitFor = taskQueue.begin()->first;
|
||||
try {
|
||||
if (newTaskScheduled.wait_until<>(lock, timeToWaitFor) == boost::cv_status::timeout) {
|
||||
break; // Exit loop after timeout, it means we reached the time of the event
|
||||
}
|
||||
} catch (boost::thread_interrupted) {
|
||||
// We need to make sure we don't ignore this, or the thread won't end
|
||||
throw;
|
||||
} catch (...) {
|
||||
// Some boost versions have a bug that can cause a time prior to system boot (or wake from sleep) to throw an exception instead of return timeout
|
||||
// See https://github.com/boostorg/thread/issues/308
|
||||
// Check if the time has passed and, if so, break gracefully
|
||||
if (timeToWaitFor <= boost::chrono::system_clock::now()) break;
|
||||
throw;
|
||||
}
|
||||
if (newTaskScheduled.wait_until<>(lock, timeToWaitFor) == boost::cv_status::timeout)
|
||||
break; // Exit loop after timeout, it means we reached the time of the event
|
||||
}
|
||||
#endif
|
||||
// If there are multiple threads, the queue can empty while we're waiting (another
|
||||
|
|
|
@ -1491,11 +1491,6 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C
|
|||
return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY);
|
||||
}
|
||||
|
||||
int claimOp;
|
||||
const CScript& strippedScriptPubKey = StripClaimScriptPrefix(scriptPubKey, claimOp);
|
||||
if (claimOp >= 0) // lbryum used to violate this rule with an off-by-1 at len == 255 (and its not very important)
|
||||
flags &= ~SCRIPT_VERIFY_MINIMALDATA;
|
||||
|
||||
std::vector<std::vector<unsigned char> > stack, stackCopy;
|
||||
if (!EvalScript(stack, scriptSig, flags, checker, SigVersion::BASE, serror))
|
||||
// serror is set
|
||||
|
@ -1512,6 +1507,8 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C
|
|||
|
||||
// Bare witness programs
|
||||
|
||||
const CScript& strippedScriptPubKey = StripClaimScriptPrefix(scriptPubKey);
|
||||
|
||||
int witnessversion;
|
||||
std::vector<unsigned char> witnessprogram;
|
||||
if (flags & SCRIPT_VERIFY_WITNESS) {
|
||||
|
|
|
@ -133,9 +133,9 @@ const char* GetOpName(opcodetype opcode)
|
|||
case OP_CHECKSEQUENCEVERIFY : return "OP_CHECKSEQUENCEVERIFY";
|
||||
case OP_NOP4 : return "OP_NOP4";
|
||||
case OP_NOP5 : return "OP_NOP5";
|
||||
case OP_NOP6 : return "OP_CLAIM_NAME";
|
||||
case OP_NOP7 : return "OP_SUPPORT_CLAIM";
|
||||
case OP_NOP8 : return "OP_UPDATE_CLAIM";
|
||||
case OP_NOP6 : return "OP_NOP6";
|
||||
case OP_NOP7 : return "OP_NOP7";
|
||||
case OP_NOP8 : return "OP_NOP8";
|
||||
case OP_NOP9 : return "OP_NOP9";
|
||||
case OP_NOP10 : return "OP_NOP10";
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include <script/sign.h>
|
||||
|
||||
#include <key.h>
|
||||
#include <nameclaim.h>
|
||||
#include <policy/policy.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <script/standard.h>
|
||||
|
@ -87,21 +86,6 @@ static bool CreateSig(const BaseSignatureCreator& creator, SignatureData& sigdat
|
|||
return false;
|
||||
}
|
||||
|
||||
static CScript StripTimelockPrefix(const CScript& script) {
|
||||
auto it = script.begin();
|
||||
opcodetype op;
|
||||
if (!script.GetOp(it, op))
|
||||
return script;
|
||||
|
||||
if (!script.GetOp(it, op) || (op != OP_CHECKLOCKTIMEVERIFY && op != OP_CHECKSEQUENCEVERIFY))
|
||||
return script;
|
||||
|
||||
if (!script.GetOp(it, op) || op != OP_DROP)
|
||||
return script;
|
||||
|
||||
return CScript(it, script.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign scriptPubKey using signature made with creator.
|
||||
* Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed),
|
||||
|
@ -117,9 +101,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
|
|||
std::vector<unsigned char> sig;
|
||||
|
||||
std::vector<valtype> vSolutions;
|
||||
auto stripped = StripClaimScriptPrefix(scriptPubKey);
|
||||
stripped = StripTimelockPrefix(stripped);
|
||||
if (!Solver(stripped, whichTypeRet, vSolutions))
|
||||
if (!Solver(scriptPubKey, whichTypeRet, vSolutions))
|
||||
return false;
|
||||
|
||||
switch (whichTypeRet)
|
||||
|
@ -367,7 +349,7 @@ SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nI
|
|||
// Get scripts
|
||||
txnouttype script_type;
|
||||
std::vector<std::vector<unsigned char>> solutions;
|
||||
Solver(StripClaimScriptPrefix(txout.scriptPubKey), script_type, solutions);
|
||||
Solver(txout.scriptPubKey, script_type, solutions);
|
||||
SigVersion sigversion = SigVersion::BASE;
|
||||
CScript next_script = txout.scriptPubKey;
|
||||
|
||||
|
|
|
@ -91,19 +91,21 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::v
|
|||
{
|
||||
vSolutionsRet.clear();
|
||||
|
||||
auto strippedPubKey = StripClaimScriptPrefix(scriptPubKey);
|
||||
|
||||
// Shortcut for pay-to-script-hash, which are more constrained than the other types:
|
||||
// it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
|
||||
if (scriptPubKey.IsPayToScriptHash())
|
||||
if (strippedPubKey.IsPayToScriptHash())
|
||||
{
|
||||
typeRet = TX_SCRIPTHASH;
|
||||
std::vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
|
||||
std::vector<unsigned char> hashBytes(strippedPubKey.begin()+2, strippedPubKey.begin()+22);
|
||||
vSolutionsRet.push_back(hashBytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
int witnessversion;
|
||||
std::vector<unsigned char> witnessprogram;
|
||||
if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
|
||||
if (strippedPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
|
||||
if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_KEYHASH_SIZE) {
|
||||
typeRet = TX_WITNESS_V0_KEYHASH;
|
||||
vSolutionsRet.push_back(witnessprogram);
|
||||
|
@ -129,19 +131,19 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::v
|
|||
// So long as script passes the IsUnspendable() test and all but the first
|
||||
// byte passes the IsPushOnly() test we don't care what exactly is in the
|
||||
// script.
|
||||
if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
|
||||
if (strippedPubKey.size() >= 1 && strippedPubKey[0] == OP_RETURN && strippedPubKey.IsPushOnly(strippedPubKey.begin()+1)) {
|
||||
typeRet = TX_NULL_DATA;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> data;
|
||||
if (MatchPayToPubkey(scriptPubKey, data)) {
|
||||
if (MatchPayToPubkey(strippedPubKey, data)) {
|
||||
typeRet = TX_PUBKEY;
|
||||
vSolutionsRet.push_back(std::move(data));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (MatchPayToPubkeyHash(scriptPubKey, data)) {
|
||||
if (MatchPayToPubkeyHash(strippedPubKey, data)) {
|
||||
typeRet = TX_PUBKEYHASH;
|
||||
vSolutionsRet.push_back(std::move(data));
|
||||
return true;
|
||||
|
@ -149,7 +151,7 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::v
|
|||
|
||||
unsigned int required;
|
||||
std::vector<std::vector<unsigned char>> keys;
|
||||
if (MatchMultisig(scriptPubKey, required, keys)) {
|
||||
if (MatchMultisig(strippedPubKey, required, keys)) {
|
||||
typeRet = TX_MULTISIG;
|
||||
vSolutionsRet.push_back({static_cast<unsigned char>(required)}); // safe as required is in range 1..16
|
||||
vSolutionsRet.insert(vSolutionsRet.end(), keys.begin(), keys.end());
|
||||
|
@ -166,7 +168,7 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
|
|||
{
|
||||
std::vector<valtype> vSolutions;
|
||||
txnouttype whichType;
|
||||
if (!Solver(StripClaimScriptPrefix(scriptPubKey), whichType, vSolutions))
|
||||
if (!Solver(scriptPubKey, whichType, vSolutions))
|
||||
return false;
|
||||
|
||||
if (whichType == TX_PUBKEY)
|
||||
|
@ -214,8 +216,9 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::
|
|||
addressRet.clear();
|
||||
typeRet = TX_NONSTANDARD;
|
||||
std::vector<valtype> vSolutions;
|
||||
auto solved = Solver(scriptPubKey, typeRet, vSolutions);
|
||||
if (!solved || typeRet == TX_NULL_DATA){
|
||||
if (!Solver(scriptPubKey, typeRet, vSolutions))
|
||||
return false;
|
||||
if (typeRet == TX_NULL_DATA){
|
||||
// This is data, not addresses
|
||||
return false;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -3,7 +3,6 @@
|
|||
#include <uint256.h>
|
||||
#include <validation.h>
|
||||
|
||||
#include <test/claimtriefixture.h>
|
||||
#include <test/test_bitcoin.h>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/scope_exit.hpp>
|
||||
|
@ -37,12 +36,29 @@ public:
|
|||
return nodesToAddOrUpdate.height();
|
||||
}
|
||||
|
||||
CClaimTrie::iterator getCache(const std::string& key)
|
||||
CClaimPrefixTrie::iterator getCache(const std::string& key)
|
||||
{
|
||||
return nodesToAddOrUpdate.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)
|
||||
|
@ -108,7 +124,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
|
|||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK_EQUAL(ntState.getMerkleHash(), hash2);
|
||||
BOOST_CHECK(ntState.checkConsistency());
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency(hash2));
|
||||
|
||||
CClaimTrieCacheTest ntState1(pclaimTrie);
|
||||
ntState1.removeClaimFromTrie(std::string("test"), tx1OutPoint, unused, true);
|
||||
|
@ -128,7 +144,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
|
|||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK_EQUAL(ntState2.getMerkleHash(), hash3);
|
||||
BOOST_CHECK(ntState2.checkConsistency());
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency(hash3));
|
||||
|
||||
CClaimTrieCacheTest ntState3(pclaimTrie);
|
||||
ntState3.insertClaimIntoTrie(std::string("test"), CClaimValue(tx1OutPoint, hash160, 50, 100, 200), true);
|
||||
|
@ -136,7 +152,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
|
|||
ntState3.flush();
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK_EQUAL(ntState3.getMerkleHash(), hash4);
|
||||
BOOST_CHECK(ntState3.checkConsistency());
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency(hash4));
|
||||
|
||||
CClaimTrieCacheTest ntState4(pclaimTrie);
|
||||
ntState4.removeClaimFromTrie(std::string("abab"), tx6OutPoint, unused, true);
|
||||
|
@ -144,7 +160,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
|
|||
ntState4.flush();
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK_EQUAL(ntState4.getMerkleHash(), hash2);
|
||||
BOOST_CHECK(ntState4.checkConsistency());
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency(hash2));
|
||||
|
||||
CClaimTrieCacheTest ntState5(pclaimTrie);
|
||||
ntState5.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused, true);
|
||||
|
@ -153,7 +169,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
|
|||
ntState5.flush();
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK_EQUAL(ntState5.getMerkleHash(), hash2);
|
||||
BOOST_CHECK(ntState5.checkConsistency());
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency(hash2));
|
||||
|
||||
CClaimTrieCacheTest ntState6(pclaimTrie);
|
||||
ntState6.insertClaimIntoTrie(std::string("test"), CClaimValue(tx3OutPoint, hash160, 50, 101, 201), true);
|
||||
|
@ -162,7 +178,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
|
|||
ntState6.flush();
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK_EQUAL(ntState6.getMerkleHash(), hash2);
|
||||
BOOST_CHECK(ntState6.checkConsistency());
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency(hash2));
|
||||
|
||||
CClaimTrieCacheTest ntState7(pclaimTrie);
|
||||
ntState7.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused, true);
|
||||
|
@ -174,7 +190,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
|
|||
ntState7.flush();
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
BOOST_CHECK_EQUAL(ntState7.getMerkleHash(), hash0);
|
||||
BOOST_CHECK(ntState7.checkConsistency());
|
||||
BOOST_CHECK(pclaimTrie->checkConsistency(hash0));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(basic_insertion_info_test)
|
||||
|
@ -281,12 +297,14 @@ BOOST_AUTO_TEST_CASE(iteratetrie_test)
|
|||
ctc.insertClaimIntoTrie("test", claimVal, true);
|
||||
BOOST_CHECK(ctc.flush());
|
||||
|
||||
auto hit = pclaimTrie->find("");
|
||||
BOOST_CHECK(hit);
|
||||
BOOST_CHECK_EQUAL(hit.children().size(), 1U);
|
||||
BOOST_CHECK(hit = pclaimTrie->find("test"));
|
||||
BOOST_CHECK_EQUAL(hit.children().size(), 0U);
|
||||
BOOST_CHECK_EQUAL(hit.data().claims.size(), 1);
|
||||
CClaimTrieDataNode node;
|
||||
BOOST_CHECK(pclaimTrie->find("", node));
|
||||
BOOST_CHECK_EQUAL(node.children.size(), 1U);
|
||||
BOOST_CHECK(pclaimTrie->find("test", node));
|
||||
BOOST_CHECK_EQUAL(node.children.size(), 0U);
|
||||
CClaimTrieData data;
|
||||
BOOST_CHECK(pclaimTrie->find("test", data));
|
||||
BOOST_CHECK_EQUAL(data.claims.size(), 1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(trie_stays_consistent_test)
|
||||
|
@ -303,13 +321,13 @@ BOOST_AUTO_TEST_CASE(trie_stays_consistent_test)
|
|||
BOOST_CHECK(cache.insertClaimIntoTrie(name, value, false));
|
||||
|
||||
cache.flush();
|
||||
BOOST_CHECK(cache.checkConsistency());
|
||||
BOOST_CHECK(trie.checkConsistency(cache.getMerkleHash()));
|
||||
|
||||
for (auto& name: names) {
|
||||
CClaimValue temp;
|
||||
BOOST_CHECK(cache.removeClaimFromTrie(name, COutPoint(), temp, false));
|
||||
cache.flush();
|
||||
BOOST_CHECK(cache.checkConsistency());
|
||||
BOOST_CHECK(trie.checkConsistency(cache.getMerkleHash()));
|
||||
}
|
||||
BOOST_CHECK(trie.empty());
|
||||
}
|
||||
|
@ -382,69 +400,7 @@ BOOST_AUTO_TEST_CASE(verify_basic_serialization)
|
|||
ssData >> cv2;
|
||||
|
||||
BOOST_CHECK_EQUAL(cv, cv2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(claimtrienode_serialize_unserialize)
|
||||
{
|
||||
CDataStream ss(SER_DISK, 0);
|
||||
|
||||
uint160 hash160;
|
||||
|
||||
CClaimTrieData n1;
|
||||
CClaimTrieData n2;
|
||||
CClaimValue throwaway;
|
||||
|
||||
ss << n1;
|
||||
ss >> n2;
|
||||
BOOST_CHECK_EQUAL(n1, n2);
|
||||
|
||||
CClaimValue v1(COutPoint(uint256S("0000000000000000000000000000000000000000000000000000000000000001"), 0), hash160, 50, 0, 100);
|
||||
CClaimValue v2(COutPoint(uint256S("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), 1), hash160, 100, 1, 101);
|
||||
|
||||
n1.insertClaim(v1);
|
||||
BOOST_CHECK(n1 != n2);
|
||||
ss << n1;
|
||||
ss >> n2;
|
||||
BOOST_CHECK_EQUAL(n1, n2);
|
||||
|
||||
n1.insertClaim(v2);
|
||||
BOOST_CHECK(n1 != n2);
|
||||
ss << n1;
|
||||
ss >> n2;
|
||||
BOOST_CHECK_EQUAL(n1, n2);
|
||||
|
||||
n1.removeClaim(v1.outPoint, throwaway);
|
||||
BOOST_CHECK(n1 != n2);
|
||||
ss << n1;
|
||||
ss >> n2;
|
||||
BOOST_CHECK_EQUAL(n1, n2);
|
||||
|
||||
n1.removeClaim(v2.outPoint, throwaway);
|
||||
BOOST_CHECK(n1 != n2);
|
||||
ss << n1;
|
||||
ss >> n2;
|
||||
BOOST_CHECK_EQUAL(n1, n2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(claimtrienode_remove_invalid_claim)
|
||||
{
|
||||
uint160 hash160;
|
||||
|
||||
CClaimTrieData n1;
|
||||
CClaimTrieData n2;
|
||||
CClaimValue throwaway;
|
||||
|
||||
CClaimValue v1(COutPoint(uint256S("0000000000000000000000000000000000000000000000000000000000000001"), 0), hash160, 50, 0, 100);
|
||||
CClaimValue v2(COutPoint(uint256S("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), 1), hash160, 100, 1, 101);
|
||||
|
||||
n1.insertClaim(v1);
|
||||
n2.insertClaim(v2);
|
||||
|
||||
bool invalidClaim = n2.removeClaim(v1.outPoint, throwaway);
|
||||
BOOST_CHECK_EQUAL(invalidClaim, false);
|
||||
|
||||
invalidClaim = n1.removeClaim(v2.outPoint, throwaway);
|
||||
BOOST_CHECK_EQUAL(invalidClaim, false);
|
||||
BOOST_CHECK_EQUAL(cv.nEffectiveAmount, cv2.nEffectiveAmount);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
|
@ -1,803 +0,0 @@
|
|||
// Copyright (c) 2015-2019 The LBRY Foundation
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://opensource.org/licenses/mit-license.php
|
||||
|
||||
#include <test/claimtriefixture.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(claimtrieexpirationfork_tests, RegTestingSetup)
|
||||
|
||||
/*
|
||||
expiration
|
||||
check claims expire and loses claim
|
||||
check claims expire and is not updateable (may be changed in future soft fork)
|
||||
check supports expire and can cause supported bid to lose claim
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(claimtrie_expire_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
fixture.setExpirationForkHeight(1000000, 5, 1000000);
|
||||
|
||||
// check claims expire and loses claim
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test", "one", 2);
|
||||
fixture.IncrementBlocks(fixture.expirationTime());
|
||||
BOOST_CHECK(fixture.is_best_claim("test", tx1));
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test", "one", 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("test", tx2));
|
||||
|
||||
fixture.DecrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("test", tx1));
|
||||
fixture.DecrementBlocks(fixture.expirationTime());
|
||||
|
||||
// check claims expire and is not updateable (may be changed in future soft fork)
|
||||
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test", "one", 2);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("test", tx3));
|
||||
fixture.IncrementBlocks(fixture.expirationTime());
|
||||
CMutableTransaction u1 = fixture.MakeUpdate(tx3, "test", "two", ClaimIdHash(tx3.GetHash(), 0), 2);
|
||||
BOOST_CHECK(!fixture.is_best_claim("test",u1));
|
||||
|
||||
fixture.DecrementBlocks(fixture.expirationTime());
|
||||
BOOST_CHECK(fixture.is_best_claim("test", tx3));
|
||||
fixture.DecrementBlocks(1);
|
||||
|
||||
// check supports expire and can cause supported bid to lose claim
|
||||
CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1);
|
||||
CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2);
|
||||
CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx4, "test", 2);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("test",tx4));
|
||||
CMutableTransaction u2 = fixture.MakeUpdate(tx4, "test", "two", ClaimIdHash(tx4.GetHash(),0), 1);
|
||||
CMutableTransaction u3 = fixture.MakeUpdate(tx5, "test", "two", ClaimIdHash(tx5.GetHash(),0), 2);
|
||||
fixture.IncrementBlocks(fixture.expirationTime());
|
||||
BOOST_CHECK(fixture.is_best_claim("test", u3));
|
||||
fixture.DecrementBlocks(fixture.expirationTime());
|
||||
BOOST_CHECK(fixture.is_best_claim("test", tx4));
|
||||
fixture.DecrementBlocks(1);
|
||||
|
||||
// check updated claims will extend expiration
|
||||
CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("test", tx6));
|
||||
CMutableTransaction u4 = fixture.MakeUpdate(tx6, "test", "two", ClaimIdHash(tx6.GetHash(), 0), 2);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("test", u4));
|
||||
fixture.IncrementBlocks(fixture.expirationTime()-1);
|
||||
BOOST_CHECK(fixture.is_best_claim("test", u4));
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(!fixture.is_best_claim("test", u4));
|
||||
fixture.DecrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("test", u4));
|
||||
fixture.DecrementBlocks(fixture.expirationTime());
|
||||
BOOST_CHECK(fixture.is_best_claim("test", tx6));
|
||||
}
|
||||
|
||||
/*
|
||||
claim expiration for hard fork
|
||||
check claims do not expire post ExpirationForkHeight
|
||||
check supports work post ExpirationForkHeight
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(hardfork_claim_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
fixture.setExpirationForkHeight(7, 3, 6);
|
||||
|
||||
// First create a claim and make sure it expires pre-fork
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",3);
|
||||
fixture.IncrementBlocks(4);
|
||||
BOOST_CHECK(!fixture.is_best_claim("test",tx1));
|
||||
fixture.DecrementBlocks(3);
|
||||
BOOST_CHECK(fixture.is_best_claim("test",tx1));
|
||||
fixture.IncrementBlocks(3);
|
||||
BOOST_CHECK(!fixture.is_best_claim("test",tx1));
|
||||
|
||||
// Create a claim 1 block before the fork height that will expire after the fork height
|
||||
fixture.IncrementBlocks(1);
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test2","one",3);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK_EQUAL(fixture.expirationTime(), 3);
|
||||
|
||||
// Disable future expirations and fast-forward past the fork height
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK_EQUAL(fixture.expirationTime(), 6);
|
||||
// make sure decrementing to before the fork height will apppropriately set back the
|
||||
// expiration time to the original expiraiton time
|
||||
fixture.DecrementBlocks(1);
|
||||
BOOST_CHECK_EQUAL(fixture.expirationTime(), 3);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK_EQUAL(fixture.expirationTime(), 6);
|
||||
|
||||
// make sure that claim created 1 block before the fork expires as expected
|
||||
// at the extended expiration times
|
||||
BOOST_CHECK(fixture.is_best_claim("test2", tx2));
|
||||
fixture.IncrementBlocks(5);
|
||||
BOOST_CHECK(!fixture.is_best_claim("test2", tx2));
|
||||
fixture.DecrementBlocks(5);
|
||||
BOOST_CHECK(fixture.is_best_claim("test2", tx2));
|
||||
|
||||
// This first claim is still expired since it's pre-fork, even
|
||||
// after fork activation
|
||||
BOOST_CHECK(!fixture.is_best_claim("test", tx1));
|
||||
|
||||
// This new claim created at the fork height cannot expire at original expiration
|
||||
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1);
|
||||
fixture.IncrementBlocks(1);
|
||||
fixture.IncrementBlocks(3);
|
||||
BOOST_CHECK(fixture.is_best_claim("test",tx3));
|
||||
BOOST_CHECK(!fixture.is_best_claim("test",tx1));
|
||||
fixture.DecrementBlocks(3);
|
||||
|
||||
// but it expires at the extended expiration, and not a single block below
|
||||
fixture.IncrementBlocks(6);
|
||||
BOOST_CHECK(!fixture.is_best_claim("test",tx3));
|
||||
fixture.DecrementBlocks(6);
|
||||
fixture.IncrementBlocks(5);
|
||||
BOOST_CHECK(fixture.is_best_claim("test",tx3));
|
||||
fixture.DecrementBlocks(5);
|
||||
|
||||
// Ensure that we cannot update the original pre-fork expired claim
|
||||
CMutableTransaction u1 = fixture.MakeUpdate(tx1,"test","two",ClaimIdHash(tx1.GetHash(),0), 3);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(!fixture.is_best_claim("test",u1));
|
||||
|
||||
// Ensure that supports for the expired claim don't support it
|
||||
CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),u1,"test",10);
|
||||
BOOST_CHECK(!fixture.is_best_claim("test",u1));
|
||||
|
||||
// Ensure that we can update the new post-fork claim
|
||||
CMutableTransaction u2 = fixture.MakeUpdate(tx3,"test","two",ClaimIdHash(tx3.GetHash(),0), 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("test",u2));
|
||||
|
||||
// Ensure that supports for the new post-fork claim
|
||||
CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(),u2,"test",3);
|
||||
BOOST_CHECK(fixture.is_best_claim("test",u2));
|
||||
}
|
||||
|
||||
/*
|
||||
support expiration for hard fork
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(hardfork_support_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
fixture.setExpirationForkHeight(2, 2, 4);
|
||||
|
||||
// Create claim and support it before the fork height
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1);
|
||||
CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 2);
|
||||
// this claim will win without the support
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2);
|
||||
fixture.IncrementBlocks(2);
|
||||
|
||||
// check that the claim expires as expected at the extended time, as does the support
|
||||
fixture.IncrementBlocks(2);
|
||||
BOOST_CHECK(fixture.is_best_claim("test",tx1));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("test",3));
|
||||
fixture.DecrementBlocks(2);
|
||||
fixture.IncrementBlocks(3);
|
||||
BOOST_CHECK(!fixture.is_best_claim("test",tx1));
|
||||
fixture.DecrementBlocks(3);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("test",tx1));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("test",3));
|
||||
fixture.DecrementBlocks(1);
|
||||
|
||||
// update the claims at fork
|
||||
fixture.DecrementBlocks(1);
|
||||
CMutableTransaction u1 = fixture.MakeUpdate(tx1, "test", "two", ClaimIdHash(tx1.GetHash(),0), 1);
|
||||
CMutableTransaction u2 = fixture.MakeUpdate(tx2, "test", "two", ClaimIdHash(tx2.GetHash(),0), 2);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK_EQUAL(Params().GetConsensus().nExtendedClaimExpirationForkHeight, chainActive.Height());
|
||||
|
||||
BOOST_CHECK(fixture.is_best_claim("test", u1));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("test",3));
|
||||
BOOST_CHECK(!fixture.is_claim_in_queue("test", tx1));
|
||||
BOOST_CHECK(!fixture.is_claim_in_queue("test", tx2));
|
||||
|
||||
// check that the support expires as expected
|
||||
fixture.IncrementBlocks(3);
|
||||
BOOST_CHECK(fixture.is_best_claim("test", u2));
|
||||
fixture.DecrementBlocks(3);
|
||||
fixture.IncrementBlocks(2);
|
||||
BOOST_CHECK(fixture.is_best_claim("test",u1));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("test",3));
|
||||
}
|
||||
|
||||
/*
|
||||
activation_fall_through and supports_fall_through
|
||||
Tests for where claims/supports in queues would be undone properly in a decrement.
|
||||
See https://github.com/lbryio/lbrycrd/issues/243 for more details
|
||||
*/
|
||||
|
||||
BOOST_AUTO_TEST_CASE(activations_fall_through)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 1);
|
||||
fixture.IncrementBlocks(3);
|
||||
BOOST_CHECK_EQUAL(fixture.proportionalDelayFactor(), 1);
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "2", 3);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
BOOST_CHECK(fixture.is_best_claim("A", tx1));
|
||||
fixture.IncrementBlocks(3);
|
||||
BOOST_CHECK(fixture.is_best_claim("A", tx2));
|
||||
fixture.DecrementBlocks(3);
|
||||
fixture.Spend(tx1); // this will trigger early activation on tx2 claim
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("A", tx2));
|
||||
fixture.DecrementBlocks(1); //reorg the early activation
|
||||
BOOST_CHECK(fixture.is_best_claim("A", tx1));
|
||||
fixture.Spend(tx1);
|
||||
fixture.IncrementBlocks(1); // this should not cause tx2 to activate again and crash
|
||||
BOOST_CHECK(fixture.is_best_claim("A", tx2));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(supports_fall_through)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 3);
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "2", 1);
|
||||
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "3", 2);
|
||||
fixture.IncrementBlocks(3);
|
||||
BOOST_CHECK_EQUAL(fixture.proportionalDelayFactor(), 1);
|
||||
CMutableTransaction sx2 = fixture.MakeSupport(fixture.GetCoinbase(), tx2, "A", 3);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
BOOST_CHECK(fixture.is_best_claim("A", tx1));
|
||||
fixture.IncrementBlocks(3);
|
||||
BOOST_CHECK(fixture.is_best_claim("A", tx2));
|
||||
fixture.DecrementBlocks(3);
|
||||
fixture.Spend(tx1); // this will trigger early activation
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("A", tx2));
|
||||
fixture.DecrementBlocks(1); // reorg the early activation
|
||||
BOOST_CHECK(fixture.is_best_claim("A", tx1));
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("A", tx1)); //tx2 support should not be active
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("A", tx1)); //tx2 support should not be active
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("A", tx2)); //tx2 support should be active now
|
||||
}
|
||||
|
||||
/*
|
||||
claim/support expiration for hard fork, but with checks for disk procedures
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(hardfork_disk_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
fixture.setExpirationForkHeight(7, 3, 6);
|
||||
|
||||
// Check that incrementing to fork height, reseting to disk will get proper expiration time
|
||||
BOOST_CHECK_EQUAL(fixture.expirationTime(), 3);
|
||||
fixture.IncrementBlocks(7, true);
|
||||
BOOST_CHECK_EQUAL(fixture.expirationTime(), 6);
|
||||
fixture.ReadFromDisk(chainActive.Tip());
|
||||
BOOST_CHECK_EQUAL(fixture.expirationTime(), 6);
|
||||
|
||||
// Create a claim and support 1 block before the fork height that will expire after the fork height.
|
||||
// Reset to disk, increment past the fork height and make sure we get
|
||||
// proper behavior
|
||||
fixture.DecrementBlocks(2);
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1);
|
||||
CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
fixture.ReadFromDisk(chainActive.Tip());
|
||||
BOOST_CHECK_EQUAL(fixture.expirationTime(), 3);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK_EQUAL(fixture.expirationTime(), 6);
|
||||
BOOST_CHECK(fixture.is_best_claim("test", tx1));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("test",2));
|
||||
fixture.IncrementBlocks(2);
|
||||
BOOST_CHECK(fixture.is_best_claim("test", tx1));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("test",2));
|
||||
fixture.DecrementBlocks(2);
|
||||
fixture.IncrementBlocks(5);
|
||||
BOOST_CHECK(!fixture.is_best_claim("test", tx1));
|
||||
|
||||
// Create a claim and support before the fork height, reset to disk, update the claim
|
||||
// increment past the fork height and make sure we get proper behavior
|
||||
fixture.DecrementBlocks();
|
||||
fixture.setExpirationForkHeight(3, 5, 6);
|
||||
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test2","one",1);
|
||||
CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(),tx2,"test2",1);
|
||||
fixture.IncrementBlocks(1);
|
||||
fixture.ReadFromDisk(chainActive.Tip());
|
||||
CMutableTransaction u2 = fixture.MakeUpdate(tx2, "test2", "two", ClaimIdHash(tx2.GetHash(), 0), 1);
|
||||
// increment to fork
|
||||
fixture.IncrementBlocks(2);
|
||||
BOOST_CHECK(fixture.is_best_claim("test2", u2));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("test2",2));
|
||||
// increment to original expiration, should not be expired
|
||||
fixture.IncrementBlocks(2);
|
||||
BOOST_CHECK(fixture.is_best_claim("test2", u2));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("test2", 2));
|
||||
fixture.DecrementBlocks(2);
|
||||
// increment to extended expiration, should be expired and not one block before
|
||||
fixture.IncrementBlocks(5);
|
||||
BOOST_CHECK(!fixture.is_best_claim("test2", u2));
|
||||
fixture.DecrementBlocks(5);
|
||||
fixture.IncrementBlocks(4);
|
||||
BOOST_CHECK(fixture.is_best_claim("test2", u2));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("test2", 1)); // the support expires one block before
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(claim_expiration_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
|
||||
std::string sName("atest");
|
||||
std::string sValue("testa");
|
||||
|
||||
int nThrowaway;
|
||||
|
||||
// set expiration time to 80 blocks after the block is created
|
||||
fixture.setExpirationForkHeight(1000000, 80, 1000000);
|
||||
|
||||
// create a claim. verify the expiration event has been scheduled.
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue, 10);
|
||||
COutPoint tx1OutPoint(tx1.GetHash(), 0);
|
||||
fixture.IncrementBlocks(1, true);
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||
|
||||
// advance until the expiration event occurs. verify the expiration event occurs on time.
|
||||
|
||||
fixture.IncrementBlocks(79); // 80
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||
|
||||
fixture.IncrementBlocks(1); // 81
|
||||
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(fixture.expirationQueueEmpty());
|
||||
|
||||
// roll forward a bit and then roll back to before the expiration event. verify the claim is reinserted. verify the expiration event is scheduled again.
|
||||
fixture.IncrementBlocks(20); // 101
|
||||
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(fixture.expirationQueueEmpty());
|
||||
|
||||
fixture.DecrementBlocks(21); // 80
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||
|
||||
// advance until the expiration event occurs. verify the expiration event occurs on time.
|
||||
fixture.IncrementBlocks(1); // 81
|
||||
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(fixture.expirationQueueEmpty());
|
||||
|
||||
// roll back to before the expiration event. verify the claim is reinserted. verify the expiration event is scheduled again.
|
||||
fixture.DecrementBlocks(2); // 79
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||
|
||||
// roll back some more.
|
||||
fixture.DecrementBlocks(39); // 40
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||
|
||||
// spend the claim. verify the expiration event is removed.
|
||||
CMutableTransaction tx2 = fixture.Spend(tx1);
|
||||
fixture.IncrementBlocks(1); // 41
|
||||
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(fixture.expirationQueueEmpty());
|
||||
|
||||
// roll back the spend. verify the expiration event is returned.
|
||||
fixture.DecrementBlocks(1); // 40
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||
|
||||
// advance until the expiration event occurs. verify the event occurs on time.
|
||||
fixture.IncrementBlocks(40); // 80
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||
|
||||
fixture.IncrementBlocks(1); // 81
|
||||
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(fixture.expirationQueueEmpty());
|
||||
|
||||
// spend the expired claim
|
||||
fixture.CommitTx(tx2);
|
||||
fixture.IncrementBlocks(1); // 82
|
||||
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(fixture.expirationQueueEmpty());
|
||||
|
||||
// undo the spend. verify everything remains empty.
|
||||
fixture.DecrementBlocks(1); // 81
|
||||
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(fixture.expirationQueueEmpty());
|
||||
|
||||
// roll back to before the expiration event. verify the claim is reinserted. verify the expiration event is scheduled again.
|
||||
fixture.DecrementBlocks(1); // 80
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||
|
||||
// verify the expiration event happens at the right time again
|
||||
fixture.IncrementBlocks(1); // 81
|
||||
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(fixture.expirationQueueEmpty());
|
||||
|
||||
// roll back to before the expiration event. verify it gets reinserted and expiration gets scheduled.
|
||||
fixture.DecrementBlocks(1); // 80
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||
|
||||
// roll all the way back. verify the claim is removed and the expiration event is removed.
|
||||
fixture.DecrementBlocks(); // 0
|
||||
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(fixture.expirationQueueEmpty());
|
||||
|
||||
// Make sure that when a claim expires, a lesser claim for the same name takes over
|
||||
|
||||
CClaimValue val;
|
||||
|
||||
// create one claim for the name
|
||||
fixture.CommitTx(tx1);
|
||||
fixture.IncrementBlocks(1, true); // 1
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||
|
||||
// advance a little while and insert the second claim
|
||||
fixture.IncrementBlocks(4); // 5
|
||||
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue, 5);
|
||||
COutPoint tx3OutPoint(tx3.GetHash(), 0);
|
||||
fixture.IncrementBlocks(1); // 6
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(!fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||
|
||||
// advance until tx3 is valid, ensure tx1 is winning
|
||||
fixture.IncrementBlocks(4); // 10
|
||||
|
||||
BOOST_CHECK(!fixture.queueEmpty());
|
||||
BOOST_CHECK(fixture.haveClaimInQueue(sName, tx3OutPoint, nThrowaway));
|
||||
|
||||
fixture.IncrementBlocks(1); // 11
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||
BOOST_CHECK_EQUAL(val.outPoint, tx1OutPoint);
|
||||
uint256 tx1MerkleHash = fixture.getMerkleHash();
|
||||
|
||||
// roll back to before tx3 is valid
|
||||
fixture.DecrementBlocks(1); // 10
|
||||
|
||||
// advance again until tx is valid
|
||||
fixture.IncrementBlocks(1); // 11
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||
BOOST_CHECK_EQUAL(val.outPoint, tx1OutPoint);
|
||||
BOOST_CHECK_EQUAL(tx1MerkleHash, fixture.getMerkleHash());
|
||||
|
||||
// advance until the expiration event occurs. verify the expiration event occurs on time.
|
||||
fixture.IncrementBlocks(69, true); // 80
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||
|
||||
fixture.IncrementBlocks(1); // 81
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||
BOOST_CHECK_EQUAL(val.outPoint, tx3OutPoint);
|
||||
BOOST_CHECK(tx1MerkleHash != fixture.getMerkleHash());
|
||||
|
||||
// spend tx1
|
||||
fixture.CommitTx(tx2);
|
||||
fixture.IncrementBlocks(1); // 82
|
||||
|
||||
// roll back to when tx1 and tx3 are in the trie and tx1 is winning
|
||||
fixture.DecrementBlocks(); // 11
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||
BOOST_CHECK_EQUAL(val.outPoint, tx1OutPoint);
|
||||
BOOST_CHECK_EQUAL(tx1MerkleHash, fixture.getMerkleHash());
|
||||
|
||||
// roll all the way back
|
||||
fixture.DecrementBlocks();
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(fixture.expirationQueueEmpty());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(expiring_supports_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
|
||||
std::string sName("atest");
|
||||
std::string sValue1("testa");
|
||||
std::string sValue2("testb");
|
||||
|
||||
CClaimValue val;
|
||||
std::vector<uint256> blocks_to_invalidate;
|
||||
|
||||
fixture.setExpirationForkHeight(1000000, 80, 1000000);
|
||||
|
||||
// to be active bid must have: a higher block number and current block >= (current height - block number) / 32
|
||||
|
||||
// Verify that supports expire
|
||||
|
||||
// Create a 1 LBC claim (tx1)
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue1, 1);
|
||||
fixture.IncrementBlocks(1); // 1, expires at 81
|
||||
|
||||
BOOST_CHECK(pcoinsTip->HaveCoin(COutPoint(tx1.GetHash(), 0)));
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(fixture.supportEmpty());
|
||||
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||
|
||||
// Create a 5 LBC support (tx3)
|
||||
CMutableTransaction tx3 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, sName, 5);
|
||||
fixture.IncrementBlocks(1); // 2, expires at 82
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.supportEmpty());
|
||||
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||
|
||||
// Advance some, then insert 5 LBC claim (tx2)
|
||||
fixture.IncrementBlocks(19); // 21
|
||||
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue2, 5);
|
||||
fixture.IncrementBlocks(1); // 22, activating in (22 - 2) / 1 = 20block (but not then active because support still holds tx1 up)
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(!fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.supportEmpty());
|
||||
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||
uint256 rootMerkleHash = fixture.getMerkleHash();
|
||||
|
||||
// Advance until tx2 is valid
|
||||
fixture.IncrementBlocks(20); // 42
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(!fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.supportEmpty());
|
||||
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||
BOOST_CHECK_EQUAL(rootMerkleHash, fixture.getMerkleHash());
|
||||
|
||||
fixture.IncrementBlocks(1); // 43
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.supportEmpty());
|
||||
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||
BOOST_CHECK_EQUAL(val.outPoint.hash, tx1.GetHash());
|
||||
rootMerkleHash = fixture.getMerkleHash();
|
||||
|
||||
// Update tx1 so that it expires after tx3 expires
|
||||
uint160 claimId = ClaimIdHash(tx1.GetHash(), 0);
|
||||
CMutableTransaction tx4 = fixture.MakeUpdate(tx1, sName, sValue1, claimId, tx1.vout[0].nValue);
|
||||
|
||||
fixture.IncrementBlocks(1); // 104
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.supportEmpty());
|
||||
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||
BOOST_CHECK_EQUAL(val.outPoint.hash, tx4.GetHash());
|
||||
BOOST_CHECK(rootMerkleHash != fixture.getMerkleHash());
|
||||
|
||||
// Advance until the support expires
|
||||
fixture.IncrementBlocks(37); // 81
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.supportEmpty());
|
||||
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||
rootMerkleHash = fixture.getMerkleHash();
|
||||
|
||||
fixture.IncrementBlocks(1); // 82
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(fixture.supportEmpty());
|
||||
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||
BOOST_CHECK_EQUAL(val.outPoint.hash, tx2.GetHash());
|
||||
BOOST_CHECK(rootMerkleHash != fixture.getMerkleHash());
|
||||
rootMerkleHash = fixture.getMerkleHash();
|
||||
|
||||
// undo the block, make sure control goes back
|
||||
fixture.DecrementBlocks(1); // 81
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.supportEmpty());
|
||||
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||
BOOST_CHECK_EQUAL(val.outPoint.hash, tx4.GetHash());
|
||||
BOOST_CHECK(rootMerkleHash != fixture.getMerkleHash());
|
||||
|
||||
// redo the block, make sure it expires again
|
||||
fixture.IncrementBlocks(1); // 82
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(fixture.supportEmpty());
|
||||
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||
BOOST_CHECK_EQUAL(val.outPoint.hash, tx2.GetHash());
|
||||
rootMerkleHash = fixture.getMerkleHash();
|
||||
|
||||
// roll back some, spend the support, and make sure nothing unexpected
|
||||
// happens at the time the support should have expired
|
||||
|
||||
fixture.DecrementBlocks(19); // 63
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.supportEmpty());
|
||||
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||
BOOST_CHECK_EQUAL(val.outPoint.hash, tx4.GetHash());
|
||||
BOOST_CHECK(rootMerkleHash != fixture.getMerkleHash());
|
||||
|
||||
fixture.Spend(tx3);
|
||||
fixture.IncrementBlocks(1); // 64
|
||||
|
||||
blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash());
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(fixture.supportEmpty());
|
||||
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||
BOOST_CHECK_EQUAL(val.outPoint.hash, tx2.GetHash());
|
||||
|
||||
fixture.IncrementBlocks(20); // 84
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(fixture.supportEmpty());
|
||||
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||
BOOST_CHECK_EQUAL(val.outPoint.hash, tx2.GetHash());
|
||||
|
||||
//undo the spend, and make sure it still expires on time
|
||||
|
||||
fixture.DecrementBlocks(21); // 63
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.supportEmpty());
|
||||
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||
BOOST_CHECK_EQUAL(val.outPoint.hash, tx4.GetHash());
|
||||
|
||||
fixture.IncrementBlocks(18); // 81
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(!fixture.supportEmpty());
|
||||
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||
BOOST_CHECK_EQUAL(val.outPoint.hash, tx4.GetHash());
|
||||
|
||||
fixture.IncrementBlocks(1); // 82
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(fixture.supportEmpty());
|
||||
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||
BOOST_CHECK_EQUAL(val.outPoint.hash, tx2.GetHash());
|
||||
|
||||
// roll all the way back
|
||||
fixture.DecrementBlocks(82);
|
||||
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(fixture.supportEmpty());
|
||||
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(get_claim_by_id_test_3)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
fixture.setExpirationForkHeight(1000000, 5, 1000000);
|
||||
const std::string name = "test";
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 1);
|
||||
uint160 claimId = ClaimIdHash(tx1.GetHash(), 0);
|
||||
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
CClaimValue claimValue;
|
||||
std::string claimName;
|
||||
BOOST_CHECK(getClaimById(claimId, claimName, &claimValue));
|
||||
BOOST_CHECK_EQUAL(claimName, name);
|
||||
BOOST_CHECK_EQUAL(claimValue.claimId, claimId);
|
||||
// make second claim with activation delay 1
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 2);
|
||||
uint160 claimId2 = ClaimIdHash(tx2.GetHash(), 0);
|
||||
|
||||
fixture.IncrementBlocks(1);
|
||||
// second claim is not activated yet, but can still access by claim id
|
||||
BOOST_CHECK(fixture.is_best_claim(name, tx1));
|
||||
BOOST_CHECK(getClaimById(claimId2, claimName, &claimValue));
|
||||
BOOST_CHECK_EQUAL(claimName, name);
|
||||
BOOST_CHECK_EQUAL(claimValue.claimId, claimId2);
|
||||
|
||||
fixture.IncrementBlocks(1);
|
||||
// second claim has activated
|
||||
BOOST_CHECK(fixture.is_best_claim(name, tx2));
|
||||
BOOST_CHECK(getClaimById(claimId2, claimName, &claimValue));
|
||||
BOOST_CHECK_EQUAL(claimName, name);
|
||||
BOOST_CHECK_EQUAL(claimValue.claimId, claimId2);
|
||||
|
||||
|
||||
fixture.DecrementBlocks(1);
|
||||
// second claim has been deactivated via decrement
|
||||
// should still be accesible via claim id
|
||||
BOOST_CHECK(fixture.is_best_claim(name, tx1));
|
||||
BOOST_CHECK(getClaimById(claimId2, claimName, &claimValue));
|
||||
BOOST_CHECK_EQUAL(claimName, name);
|
||||
BOOST_CHECK_EQUAL(claimValue.claimId, claimId2);
|
||||
|
||||
fixture.IncrementBlocks(1);
|
||||
// second claim should have been re activated via increment
|
||||
BOOST_CHECK(fixture.is_best_claim(name, tx2));
|
||||
BOOST_CHECK(getClaimById(claimId2, claimName, &claimValue));
|
||||
BOOST_CHECK_EQUAL(claimName, name);
|
||||
BOOST_CHECK_EQUAL(claimValue.claimId, claimId2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
|
@ -1,419 +0,0 @@
|
|||
// Copyright (c) 2015-2019 The LBRY Foundation
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://opensource.org/licenses/mit-license.php
|
||||
|
||||
#include <functional>
|
||||
#include <test/claimtriefixture.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(claimtriefixture_tests, RegTestingSetup)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(claimtriefixture_noop)
|
||||
{
|
||||
BOOST_REQUIRE(true);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
CMutableTransaction BuildTransaction(const CTransaction& prev, uint32_t prevout, unsigned int numOutputs, int locktime)
|
||||
{
|
||||
CMutableTransaction tx;
|
||||
tx.nVersion = CTransaction::CURRENT_VERSION;
|
||||
tx.vin.resize(1);
|
||||
tx.vout.resize(numOutputs);
|
||||
tx.vin[0].prevout.hash = prev.GetHash();
|
||||
tx.vin[0].prevout.n = prevout;
|
||||
tx.vin[0].scriptSig = CScript();
|
||||
if (locktime != 0) {
|
||||
// Use a relative locktime for validity X blocks in the future
|
||||
tx.nLockTime = chainActive.Height() + locktime;
|
||||
tx.vin[0].nSequence = 0xffffffff - 1;
|
||||
} else {
|
||||
tx.nLockTime = 1 << 31; // Disable BIP68
|
||||
tx.vin[0].nSequence = std::numeric_limits<unsigned int>::max();
|
||||
}
|
||||
CAmount valuePerOutput = prev.vout[prevout].nValue;
|
||||
unsigned int numOutputsCopy = numOutputs;
|
||||
while ((numOutputsCopy = numOutputsCopy >> 1) > 0)
|
||||
valuePerOutput = valuePerOutput >> 1;
|
||||
|
||||
for (unsigned int i = 0; i < numOutputs; ++i) {
|
||||
tx.vout[i].scriptPubKey = CScript();
|
||||
tx.vout[i].nValue = valuePerOutput;
|
||||
}
|
||||
return tx;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
BlockAssembler AssemblerForTest()
|
||||
{
|
||||
BlockAssembler::Options options;
|
||||
options.nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT;
|
||||
options.blockMinFeeRate = CFeeRate(0);
|
||||
return BlockAssembler(Params(), options);
|
||||
}
|
||||
|
||||
ClaimTrieChainFixture::ClaimTrieChainFixture() : CClaimTrieCache(pclaimTrie),
|
||||
unique_block_counter(0), normalization_original(-1), expirationForkHeight(-1), forkhash_original(-1)
|
||||
{
|
||||
fRequireStandard = false;
|
||||
BOOST_CHECK_EQUAL(nNextHeight, chainActive.Height() + 1);
|
||||
setNormalizationForkHeight(1000000);
|
||||
|
||||
gArgs.ForceSetArg("-limitancestorcount", "1000000");
|
||||
gArgs.ForceSetArg("-limitancestorsize", "1000000");
|
||||
gArgs.ForceSetArg("-limitdescendantcount", "1000000");
|
||||
gArgs.ForceSetArg("-limitdescendantsize", "1000000");
|
||||
|
||||
num_txs_for_next_block = 0;
|
||||
coinbase_txs_used = 0;
|
||||
unique_block_counter = 0;
|
||||
added_unchecked = false;
|
||||
// generate coinbases to spend
|
||||
CreateCoinbases(40, coinbase_txs);
|
||||
}
|
||||
|
||||
ClaimTrieChainFixture::~ClaimTrieChainFixture()
|
||||
{
|
||||
added_unchecked = false;
|
||||
DecrementBlocks(chainActive.Height());
|
||||
auto& consensus = const_cast<Consensus::Params&>(Params().GetConsensus());
|
||||
if (normalization_original >= 0)
|
||||
consensus.nNormalizedNameForkHeight = normalization_original;
|
||||
|
||||
if (expirationForkHeight >= 0) {
|
||||
consensus.nExtendedClaimExpirationForkHeight = expirationForkHeight;
|
||||
consensus.nExtendedClaimExpirationTime = extendedExpiration;
|
||||
consensus.nOriginalClaimExpirationTime = originalExpiration;
|
||||
}
|
||||
if (forkhash_original >= 0)
|
||||
consensus.nAllClaimsInMerkleForkHeight = forkhash_original;
|
||||
}
|
||||
|
||||
void ClaimTrieChainFixture::setExpirationForkHeight(int targetMinusCurrent, int64_t preForkExpirationTime, int64_t postForkExpirationTime)
|
||||
{
|
||||
int target = chainActive.Height() + targetMinusCurrent;
|
||||
auto& consensus = const_cast<Consensus::Params&>(Params().GetConsensus());
|
||||
if (expirationForkHeight < 0) {
|
||||
expirationForkHeight = consensus.nExtendedClaimExpirationForkHeight;
|
||||
originalExpiration = consensus.nOriginalClaimExpirationTime;
|
||||
extendedExpiration = consensus.nExtendedClaimExpirationTime;
|
||||
}
|
||||
consensus.nExtendedClaimExpirationForkHeight = target;
|
||||
consensus.nExtendedClaimExpirationTime = postForkExpirationTime;
|
||||
consensus.nOriginalClaimExpirationTime = preForkExpirationTime;
|
||||
setExpirationTime(targetMinusCurrent >= 0 ? preForkExpirationTime : postForkExpirationTime);
|
||||
}
|
||||
|
||||
void ClaimTrieChainFixture::setNormalizationForkHeight(int targetMinusCurrent)
|
||||
{
|
||||
int target = chainActive.Height() + targetMinusCurrent;
|
||||
auto& consensus = const_cast<Consensus::Params&>(Params().GetConsensus());
|
||||
if (normalization_original < 0)
|
||||
normalization_original = consensus.nNormalizedNameForkHeight;
|
||||
consensus.nNormalizedNameForkHeight = target;
|
||||
}
|
||||
|
||||
void ClaimTrieChainFixture::setHashForkHeight(int targetMinusCurrent)
|
||||
{
|
||||
int target = chainActive.Height() + targetMinusCurrent;
|
||||
auto& consensus = const_cast<Consensus::Params&>(Params().GetConsensus());
|
||||
if (forkhash_original < 0)
|
||||
forkhash_original = consensus.nAllClaimsInMerkleForkHeight;
|
||||
consensus.nAllClaimsInMerkleForkHeight = target;
|
||||
}
|
||||
|
||||
bool ClaimTrieChainFixture::CreateBlock(const std::unique_ptr<CBlockTemplate>& pblocktemplate)
|
||||
{
|
||||
CBlock* pblock = &pblocktemplate->block;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
pblock->nVersion = 5;
|
||||
pblock->hashPrevBlock = chainActive.Tip()->GetBlockHash();
|
||||
pblock->nTime = chainActive.Tip()->GetBlockTime() + Params().GetConsensus().nPowTargetSpacing;
|
||||
CMutableTransaction txCoinbase(*pblock->vtx[0]);
|
||||
txCoinbase.vin[0].scriptSig = CScript() << int(chainActive.Height() + 1) << int(++unique_block_counter);
|
||||
txCoinbase.vout[0].nValue = GetBlockSubsidy(chainActive.Height() + 1, Params().GetConsensus());
|
||||
pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));
|
||||
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
|
||||
for (uint32_t i = 0;; ++i) {
|
||||
pblock->nNonce = i;
|
||||
if (CheckProofOfWork(pblock->GetPoWHash(), pblock->nBits, Params().GetConsensus()))
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto success = ProcessNewBlock(Params(), std::make_shared<const CBlock>(*pblock), true, nullptr);
|
||||
return success && pblock->GetHash() == chainActive.Tip()->GetBlockHash();
|
||||
}
|
||||
|
||||
bool ClaimTrieChainFixture::CreateCoinbases(unsigned int num_coinbases, std::vector<CTransaction>& coinbases)
|
||||
{
|
||||
std::unique_ptr<CBlockTemplate> pblocktemplate;
|
||||
coinbases.clear();
|
||||
BOOST_CHECK(pblocktemplate = AssemblerForTest().CreateNewBlock(CScript() << OP_TRUE));
|
||||
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 1);
|
||||
for (unsigned int i = 0; i < 100 + num_coinbases; ++i) {
|
||||
BOOST_CHECK(CreateBlock(pblocktemplate));
|
||||
if (coinbases.size() < num_coinbases)
|
||||
coinbases.push_back(std::move(*pblocktemplate->block.vtx[0]));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClaimTrieChainFixture::CommitTx(const CMutableTransaction &tx, bool has_locktime)
|
||||
{
|
||||
num_txs_for_next_block++;
|
||||
if (has_locktime) {
|
||||
added_unchecked = true;
|
||||
TestMemPoolEntryHelper entry;
|
||||
LOCK(mempool.cs);
|
||||
mempool.addUnchecked(tx.GetHash(), entry.Fee(0).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
|
||||
} else {
|
||||
CValidationState state;
|
||||
CAmount txFeeRate = CAmount(0);
|
||||
LOCK(cs_main);
|
||||
BOOST_CHECK_EQUAL(AcceptToMemoryPool(mempool, state, MakeTransactionRef(tx), nullptr, nullptr, false, txFeeRate, false), true);
|
||||
}
|
||||
}
|
||||
|
||||
// spend a bid into some non claimtrie related unspent
|
||||
CMutableTransaction ClaimTrieChainFixture::Spend(const CTransaction &prev)
|
||||
{
|
||||
CMutableTransaction tx = BuildTransaction(prev, 0);
|
||||
tx.vout[0].scriptPubKey = CScript() << OP_TRUE;
|
||||
tx.vout[0].nValue = prev.vout[0].nValue;
|
||||
|
||||
CommitTx(tx);
|
||||
return tx;
|
||||
}
|
||||
|
||||
// make claim at the current block
|
||||
CMutableTransaction ClaimTrieChainFixture::MakeClaim(const CTransaction& prev, const std::string& name, const std::string& value, CAmount quantity, int locktime)
|
||||
{
|
||||
uint32_t prevout = prev.vout.size() - 1;
|
||||
while (prevout > 0 && prev.vout[prevout].nValue < quantity)
|
||||
--prevout;
|
||||
CMutableTransaction tx = BuildTransaction(prev, prevout, prev.vout[prevout].nValue > quantity ? 2 : 1, locktime);
|
||||
tx.vout[0].scriptPubKey = ClaimNameScript(name, value);
|
||||
tx.vout[0].nValue = quantity;
|
||||
if (tx.vout.size() > 1) {
|
||||
tx.vout[1].scriptPubKey = CScript() << OP_TRUE;
|
||||
tx.vout[1].nValue = prev.vout[prevout].nValue - quantity;
|
||||
}
|
||||
|
||||
CommitTx(tx, locktime != 0);
|
||||
return tx;
|
||||
}
|
||||
|
||||
CMutableTransaction ClaimTrieChainFixture::MakeClaim(const CTransaction& prev, const std::string& name, const std::string& value)
|
||||
{
|
||||
return MakeClaim(prev, name, value, prev.vout[0].nValue, 0);
|
||||
}
|
||||
|
||||
// make support at the current block
|
||||
CMutableTransaction ClaimTrieChainFixture::MakeSupport(const CTransaction &prev, const CTransaction &claimtx, const std::string& name, CAmount quantity)
|
||||
{
|
||||
uint32_t prevout = prev.vout.size() - 1;
|
||||
while (prevout > 0 && prev.vout[prevout].nValue < quantity)
|
||||
--prevout;
|
||||
|
||||
CMutableTransaction tx = BuildTransaction(prev, prevout, prev.vout[prevout].nValue > quantity ? 2 : 1);
|
||||
tx.vout[0].scriptPubKey = SupportClaimScript(name, ClaimIdHash(claimtx.GetHash(), 0));
|
||||
tx.vout[0].nValue = quantity;
|
||||
if (tx.vout.size() > 1) {
|
||||
tx.vout[1].scriptPubKey = CScript() << OP_TRUE;
|
||||
tx.vout[1].nValue = prev.vout[prevout].nValue - quantity;
|
||||
}
|
||||
|
||||
CommitTx(tx);
|
||||
return tx;
|
||||
}
|
||||
|
||||
// make update at the current block
|
||||
CMutableTransaction ClaimTrieChainFixture::MakeUpdate(const CTransaction &prev, const std::string& name, const std::string& value, const uint160& claimId, CAmount quantity)
|
||||
{
|
||||
CMutableTransaction tx = BuildTransaction(prev, 0);
|
||||
tx.vout[0].scriptPubKey = UpdateClaimScript(name, claimId, value);
|
||||
tx.vout[0].nValue = quantity;
|
||||
|
||||
CommitTx(tx);
|
||||
return tx;
|
||||
}
|
||||
|
||||
CTransaction ClaimTrieChainFixture::GetCoinbase()
|
||||
{
|
||||
return coinbase_txs.at(coinbase_txs_used++);
|
||||
}
|
||||
|
||||
// create i blocks
|
||||
void ClaimTrieChainFixture::IncrementBlocks(int num_blocks, bool mark)
|
||||
{
|
||||
if (mark)
|
||||
marks.push_back(chainActive.Height());
|
||||
|
||||
clear(); // clears the internal cache
|
||||
for (int i = 0; i < num_blocks; ++i) {
|
||||
CScript coinbase_scriptpubkey;
|
||||
coinbase_scriptpubkey << CScriptNum(chainActive.Height());
|
||||
std::unique_ptr<CBlockTemplate> pblocktemplate = AssemblerForTest().CreateNewBlock(coinbase_scriptpubkey);
|
||||
BOOST_CHECK(pblocktemplate != nullptr);
|
||||
if (!added_unchecked)
|
||||
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), num_txs_for_next_block + 1);
|
||||
BOOST_CHECK_EQUAL(CreateBlock(pblocktemplate), true);
|
||||
num_txs_for_next_block = 0;
|
||||
nNextHeight = chainActive.Height() + 1;
|
||||
}
|
||||
setExpirationTime(Params().GetConsensus().GetExpirationTime(nNextHeight - 1));
|
||||
}
|
||||
|
||||
// disconnect i blocks from tip
|
||||
void ClaimTrieChainFixture::DecrementBlocks(int num_blocks)
|
||||
{
|
||||
clear(); // clears the internal cache
|
||||
CValidationState state;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
CBlockIndex* pblockindex = chainActive[chainActive.Height() - num_blocks + 1];
|
||||
BOOST_CHECK_EQUAL(InvalidateBlock(state, Params(), pblockindex), true);
|
||||
}
|
||||
BOOST_CHECK_EQUAL(state.IsValid(), true);
|
||||
BOOST_CHECK_EQUAL(ActivateBestChain(state, Params()), true);
|
||||
mempool.clear();
|
||||
num_txs_for_next_block = 0;
|
||||
nNextHeight = chainActive.Height() + 1;
|
||||
setExpirationTime(Params().GetConsensus().GetExpirationTime(nNextHeight - 1));
|
||||
}
|
||||
|
||||
// decrement back to last mark
|
||||
void ClaimTrieChainFixture::DecrementBlocks()
|
||||
{
|
||||
int mark = marks.back();
|
||||
marks.pop_back();
|
||||
DecrementBlocks(chainActive.Height() - mark);
|
||||
}
|
||||
|
||||
template <typename K>
|
||||
bool ClaimTrieChainFixture::keyTypeEmpty(uint8_t keyType)
|
||||
{
|
||||
boost::scoped_ptr<CDBIterator> pcursor(base->db->NewIterator());
|
||||
pcursor->SeekToFirst();
|
||||
|
||||
while (pcursor->Valid()) {
|
||||
std::pair<uint8_t, K> key;
|
||||
if (pcursor->GetKey(key))
|
||||
if (key.first == keyType)
|
||||
return false;
|
||||
pcursor->Next();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClaimTrieChainFixture::queueEmpty()
|
||||
{
|
||||
for (const auto& claimQueue: claimQueueCache)
|
||||
if (!claimQueue.second.empty())
|
||||
return false;
|
||||
return keyTypeEmpty<int>(CLAIM_QUEUE_ROW);
|
||||
}
|
||||
|
||||
bool ClaimTrieChainFixture::expirationQueueEmpty()
|
||||
{
|
||||
for (const auto& expirationQueue: expirationQueueCache)
|
||||
if (!expirationQueue.second.empty())
|
||||
return false;
|
||||
return keyTypeEmpty<int>(CLAIM_EXP_QUEUE_ROW);
|
||||
}
|
||||
|
||||
bool ClaimTrieChainFixture::supportEmpty()
|
||||
{
|
||||
for (const auto& entry: supportCache)
|
||||
if (!entry.second.empty())
|
||||
return false;
|
||||
return supportCache.empty() && keyTypeEmpty<std::string>(SUPPORT);
|
||||
}
|
||||
|
||||
bool ClaimTrieChainFixture::supportQueueEmpty()
|
||||
{
|
||||
for (const auto& support: supportQueueCache)
|
||||
if (!support.second.empty())
|
||||
return false;
|
||||
return keyTypeEmpty<int>(SUPPORT_QUEUE_ROW);
|
||||
}
|
||||
|
||||
int ClaimTrieChainFixture::proportionalDelayFactor()
|
||||
{
|
||||
return base->nProportionalDelayFactor;
|
||||
}
|
||||
|
||||
boost::test_tools::predicate_result negativeResult(const std::function<void(boost::wrap_stringstream&)>& callback)
|
||||
{
|
||||
boost::test_tools::predicate_result res(false);
|
||||
callback(res.message());
|
||||
return res;
|
||||
}
|
||||
|
||||
boost::test_tools::predicate_result negativeResult(const std::string& message)
|
||||
{
|
||||
return negativeResult([&message](boost::wrap_stringstream& stream) {
|
||||
stream << message;
|
||||
});
|
||||
}
|
||||
|
||||
// is a claim in queue
|
||||
boost::test_tools::predicate_result ClaimTrieChainFixture::is_claim_in_queue(const std::string& name, const CTransaction &tx)
|
||||
{
|
||||
COutPoint outPoint(tx.GetHash(), 0);
|
||||
int validAtHeight;
|
||||
if (haveClaimInQueue(name, outPoint, validAtHeight))
|
||||
return true;
|
||||
return negativeResult("Is not a claim in queue");
|
||||
}
|
||||
|
||||
// check if tx is best claim based on outpoint
|
||||
boost::test_tools::predicate_result ClaimTrieChainFixture::is_best_claim(const std::string& name, const CTransaction &tx)
|
||||
{
|
||||
CClaimValue val;
|
||||
COutPoint outPoint(tx.GetHash(), 0);
|
||||
bool have_claim = haveClaim(name, outPoint);
|
||||
bool have_info = getInfoForName(name, val);
|
||||
if (have_claim && have_info && val.outPoint == outPoint)
|
||||
return true;
|
||||
return negativeResult("Is not best claim");
|
||||
}
|
||||
|
||||
// check effective quantity of best claim
|
||||
boost::test_tools::predicate_result ClaimTrieChainFixture::best_claim_effective_amount_equals(const std::string& name, CAmount amount)
|
||||
{
|
||||
CClaimValue val;
|
||||
bool have_info = getInfoForName(name, val);
|
||||
if (!have_info)
|
||||
return negativeResult("No claim found");
|
||||
CAmount effective_amount = getClaimsForName(name).find(val.claimId).effectiveAmount;
|
||||
if (effective_amount != amount)
|
||||
return negativeResult([amount, effective_amount](boost::wrap_stringstream& stream) {
|
||||
stream << amount << " != " << effective_amount;
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
std::size_t ClaimTrieChainFixture::getTotalNamesInTrie() const
|
||||
{
|
||||
return base->getTotalNamesInTrie();
|
||||
}
|
|
@ -1,124 +0,0 @@
|
|||
// Copyright (c) 2015-2019 The LBRY Foundation
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://opensource.org/licenses/mit-license.php
|
||||
|
||||
#ifndef _CLAIMTRIEFIXTURE_H_
|
||||
#define _CLAIMTRIEFIXTURE_H_
|
||||
|
||||
#include <chainparams.h>
|
||||
#include <claimtrie.h>
|
||||
#include <coins.h>
|
||||
#include <consensus/merkle.h>
|
||||
#include <consensus/validation.h>
|
||||
#include <miner.h>
|
||||
#include <nameclaim.h>
|
||||
#include <policy/policy.h>
|
||||
#include <pow.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <random.h>
|
||||
#include <rpc/claimrpchelp.h>
|
||||
#include <rpc/server.h>
|
||||
#include <streams.h>
|
||||
#include <test/test_bitcoin.h>
|
||||
#include <txmempool.h>
|
||||
#include <validation.h>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <iostream>
|
||||
|
||||
extern ::CChainState g_chainstate;
|
||||
extern ::ArgsManager gArgs;
|
||||
extern std::vector<std::string> random_strings(std::size_t count);
|
||||
extern bool getClaimById(const uint160&, std::string&, CClaimValue*);
|
||||
|
||||
CMutableTransaction BuildTransaction(const uint256& prevhash);
|
||||
CMutableTransaction BuildTransaction(const CTransaction& prev, uint32_t prevout=0, unsigned int numOutputs=1, int locktime=0);
|
||||
|
||||
BlockAssembler AssemblerForTest();
|
||||
|
||||
// Test Fixtures
|
||||
struct ClaimTrieChainFixture: public CClaimTrieCache
|
||||
{
|
||||
std::vector<CTransaction> coinbase_txs;
|
||||
std::vector<int> marks;
|
||||
int coinbase_txs_used;
|
||||
int unique_block_counter;
|
||||
int normalization_original;
|
||||
unsigned int num_txs_for_next_block;
|
||||
bool added_unchecked;
|
||||
|
||||
int64_t expirationForkHeight;
|
||||
int64_t originalExpiration;
|
||||
int64_t extendedExpiration;
|
||||
int64_t forkhash_original;
|
||||
|
||||
using CClaimTrieCache::getSupportsForName;
|
||||
|
||||
ClaimTrieChainFixture();
|
||||
|
||||
~ClaimTrieChainFixture();
|
||||
|
||||
void setExpirationForkHeight(int targetMinusCurrent, int64_t preForkExpirationTime, int64_t postForkExpirationTime);
|
||||
|
||||
void setNormalizationForkHeight(int targetMinusCurrent);
|
||||
|
||||
void setHashForkHeight(int targetMinusCurrent);
|
||||
|
||||
bool CreateBlock(const std::unique_ptr<CBlockTemplate>& pblocktemplate);
|
||||
|
||||
bool CreateCoinbases(unsigned int num_coinbases, std::vector<CTransaction>& coinbases);
|
||||
|
||||
void CommitTx(const CMutableTransaction &tx, bool has_locktime=false);
|
||||
|
||||
// spend a bid into some non claimtrie related unspent
|
||||
CMutableTransaction Spend(const CTransaction &prev);
|
||||
|
||||
// make claim at the current block
|
||||
CMutableTransaction MakeClaim(const CTransaction& prev, const std::string& name, const std::string& value, CAmount quantity, int locktime=0);
|
||||
|
||||
CMutableTransaction MakeClaim(const CTransaction& prev, const std::string& name, const std::string& value);
|
||||
|
||||
// make support at the current block
|
||||
CMutableTransaction MakeSupport(const CTransaction &prev, const CTransaction &claimtx, const std::string& name, CAmount quantity);
|
||||
|
||||
// make update at the current block
|
||||
CMutableTransaction MakeUpdate(const CTransaction &prev, const std::string& name, const std::string& value, const uint160& claimId, CAmount quantity);
|
||||
|
||||
CTransaction GetCoinbase();
|
||||
|
||||
// create i blocks
|
||||
void IncrementBlocks(int num_blocks, bool mark = false);
|
||||
|
||||
// disconnect i blocks from tip
|
||||
void DecrementBlocks(int num_blocks);
|
||||
|
||||
// decrement back to last mark
|
||||
void DecrementBlocks();
|
||||
|
||||
bool queueEmpty();
|
||||
|
||||
bool expirationQueueEmpty();
|
||||
|
||||
bool supportEmpty();
|
||||
|
||||
bool supportQueueEmpty();
|
||||
|
||||
int proportionalDelayFactor();
|
||||
|
||||
// is a claim in queue
|
||||
boost::test_tools::predicate_result is_claim_in_queue(const std::string& name, const CTransaction &tx);
|
||||
|
||||
// check if tx is best claim based on outpoint
|
||||
boost::test_tools::predicate_result is_best_claim(const std::string& name, const CTransaction &tx);
|
||||
|
||||
// check effective quantity of best claim
|
||||
boost::test_tools::predicate_result best_claim_effective_amount_equals(const std::string& name, CAmount amount);
|
||||
|
||||
std::size_t getTotalNamesInTrie() const;
|
||||
|
||||
private:
|
||||
template <typename K>
|
||||
bool keyTypeEmpty(uint8_t keyType);
|
||||
};
|
||||
|
||||
#endif // _CLAIMTRIEFIXTURE_H_
|
|
@ -1,390 +0,0 @@
|
|||
// Copyright (c) 2015-2019 The LBRY Foundation
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://opensource.org/licenses/mit-license.php
|
||||
|
||||
#include <test/claimtriefixture.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void ValidatePairs(CClaimTrieCache& cache, const std::vector<std::pair<bool, uint256>>& pairs, uint256 claimHash)
|
||||
{
|
||||
for (auto& pair : pairs)
|
||||
if (pair.first) // we're on the right because we were an odd index number
|
||||
claimHash = Hash(pair.second.begin(), pair.second.end(), claimHash.begin(), claimHash.end());
|
||||
else
|
||||
claimHash = Hash(claimHash.begin(), claimHash.end(), pair.second.begin(), pair.second.end());
|
||||
|
||||
BOOST_CHECK_EQUAL(cache.getMerkleHash(), claimHash);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(claimtriehashfork_tests, RegTestingSetup)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(hash_includes_all_claims_rollback_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
fixture.setHashForkHeight(5);
|
||||
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
uint256 currentRoot = fixture.getMerkleHash();
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK_EQUAL(currentRoot, fixture.getMerkleHash());
|
||||
fixture.IncrementBlocks(3);
|
||||
BOOST_CHECK_NE(currentRoot, fixture.getMerkleHash());
|
||||
fixture.DecrementBlocks(3);
|
||||
BOOST_CHECK_EQUAL(currentRoot, fixture.getMerkleHash());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(hash_includes_all_claims_single_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
fixture.setHashForkHeight(2);
|
||||
fixture.IncrementBlocks(4);
|
||||
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
COutPoint outPoint(tx1.GetHash(), 0);
|
||||
uint160 claimId = ClaimIdHash(tx1.GetHash(), 0);
|
||||
|
||||
CClaimTrieProof proof;
|
||||
BOOST_CHECK(fixture.getProofForName("test", proof, [&claimId](const CClaimValue& claim) {
|
||||
return claim.claimId == claimId;
|
||||
}));
|
||||
BOOST_CHECK(proof.hasValue);
|
||||
BOOST_CHECK_EQUAL(proof.outPoint, outPoint);
|
||||
auto claimHash = getValueHash(outPoint, proof.nHeightOfLastTakeover);
|
||||
ValidatePairs(fixture, proof.pairs, claimHash);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(hash_includes_all_claims_triple_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
fixture.setHashForkHeight(2);
|
||||
fixture.IncrementBlocks(4);
|
||||
|
||||
std::string names[] = {"test", "tester", "tester2"};
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), names[0], "one", 1);
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), names[0], "two", 2);
|
||||
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), names[0], "thr", 3);
|
||||
CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(), names[0], "for", 4);
|
||||
CMutableTransaction tx8 = fixture.MakeClaim(fixture.GetCoinbase(), names[0], "fiv", 5);
|
||||
CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), names[1], "two", 2);
|
||||
CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), names[1], "thr", 3);
|
||||
CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(), names[2], "one", 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
for (const auto& name : names) {
|
||||
for (auto& claimSupports : fixture.getClaimsForName(name).claimsNsupports) {
|
||||
CClaimTrieProof proof;
|
||||
auto& claim = claimSupports.claim;
|
||||
BOOST_CHECK(fixture.getProofForName(name, proof, [&claim](const CClaimValue& value) {
|
||||
return claim.claimId == value.claimId;
|
||||
}));
|
||||
BOOST_CHECK(proof.hasValue);
|
||||
BOOST_CHECK_EQUAL(proof.outPoint, claim.outPoint);
|
||||
uint256 claimHash = getValueHash(claim.outPoint, proof.nHeightOfLastTakeover);
|
||||
ValidatePairs(fixture, proof.pairs, claimHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(hash_includes_all_claims_branched_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
fixture.setHashForkHeight(2);
|
||||
fixture.IncrementBlocks(4);
|
||||
|
||||
std::string names[] = {"test", "toast", "tot", "top", "toa", "toad"};
|
||||
for (const auto& name : names)
|
||||
fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 1);
|
||||
|
||||
fixture.MakeClaim(fixture.GetCoinbase(), "toa", "two", 2);
|
||||
fixture.MakeClaim(fixture.GetCoinbase(), "toa", "tre", 3);
|
||||
fixture.MakeClaim(fixture.GetCoinbase(), "toa", "qua", 4);
|
||||
fixture.MakeClaim(fixture.GetCoinbase(), "toa", "cin", 5);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
for (const auto& name : names) {
|
||||
for (auto& claimSupports : fixture.getClaimsForName(name).claimsNsupports) {
|
||||
CClaimTrieProof proof;
|
||||
auto& claim = claimSupports.claim;
|
||||
BOOST_CHECK(fixture.getProofForName(name, proof, [&claim](const CClaimValue& value) {
|
||||
return claim.claimId == value.claimId;
|
||||
}));
|
||||
BOOST_CHECK(proof.hasValue);
|
||||
BOOST_CHECK_EQUAL(proof.outPoint, claim.outPoint);
|
||||
uint256 claimHash = getValueHash(claim.outPoint, proof.nHeightOfLastTakeover);
|
||||
ValidatePairs(fixture, proof.pairs, claimHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(hash_claims_children_fuzzer_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
fixture.setHashForkHeight(2);
|
||||
fixture.IncrementBlocks(4);
|
||||
|
||||
std::size_t i = 0;
|
||||
auto names = random_strings(300);
|
||||
auto lastTx = MakeTransactionRef(fixture.GetCoinbase());
|
||||
for (const auto& name : names) {
|
||||
auto tx = fixture.MakeClaim(*lastTx, name, "one", 1);
|
||||
lastTx = MakeTransactionRef(std::move(tx));
|
||||
if (++i % 5 == 0)
|
||||
for (std::size_t j = 0; j < (i / 5); ++j) {
|
||||
auto tx = fixture.MakeClaim(*lastTx, name, "one", 1);
|
||||
lastTx = MakeTransactionRef(std::move(tx));
|
||||
}
|
||||
fixture.IncrementBlocks(1);
|
||||
}
|
||||
|
||||
for (const auto& name : names) {
|
||||
for (auto& claimSupports : fixture.getClaimsForName(name).claimsNsupports) {
|
||||
CClaimTrieProof proof;
|
||||
auto& claim = claimSupports.claim;
|
||||
BOOST_CHECK(fixture.getProofForName(name, proof, [&claim](const CClaimValue& value) {
|
||||
return claim.claimId == value.claimId;
|
||||
}));
|
||||
BOOST_CHECK(proof.hasValue);
|
||||
BOOST_CHECK_EQUAL(proof.outPoint, claim.outPoint);
|
||||
uint256 claimHash = getValueHash(claim.outPoint, proof.nHeightOfLastTakeover);
|
||||
ValidatePairs(fixture, proof.pairs, claimHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool verify_proof(const CClaimTrieProof proof, uint256 rootHash, const std::string& name)
|
||||
{
|
||||
uint256 previousComputedHash;
|
||||
std::string computedReverseName;
|
||||
bool verifiedValue = false;
|
||||
|
||||
for (auto itNodes = proof.nodes.rbegin(); itNodes != proof.nodes.rend(); ++itNodes) {
|
||||
bool foundChildInChain = false;
|
||||
std::vector<unsigned char> vchToHash;
|
||||
for (auto itChildren = itNodes->children.begin(); itChildren != itNodes->children.end(); ++itChildren) {
|
||||
vchToHash.push_back(itChildren->first);
|
||||
uint256 childHash;
|
||||
if (itChildren->second.IsNull()) {
|
||||
if (previousComputedHash.IsNull()) {
|
||||
return false;
|
||||
}
|
||||
if (foundChildInChain) {
|
||||
return false;
|
||||
}
|
||||
foundChildInChain = true;
|
||||
computedReverseName += itChildren->first;
|
||||
childHash = previousComputedHash;
|
||||
} else {
|
||||
childHash = itChildren->second;
|
||||
}
|
||||
vchToHash.insert(vchToHash.end(), childHash.begin(), childHash.end());
|
||||
}
|
||||
if (itNodes != proof.nodes.rbegin() && !foundChildInChain) {
|
||||
return false;
|
||||
}
|
||||
if (itNodes->hasValue) {
|
||||
uint256 valHash;
|
||||
if (itNodes->valHash.IsNull()) {
|
||||
if (itNodes != proof.nodes.rbegin()) {
|
||||
return false;
|
||||
}
|
||||
if (!proof.hasValue) {
|
||||
return false;
|
||||
}
|
||||
valHash = getValueHash(proof.outPoint,
|
||||
proof.nHeightOfLastTakeover);
|
||||
|
||||
verifiedValue = true;
|
||||
} else {
|
||||
valHash = itNodes->valHash;
|
||||
}
|
||||
vchToHash.insert(vchToHash.end(), valHash.begin(), valHash.end());
|
||||
} else if (proof.hasValue && itNodes == proof.nodes.rbegin()) {
|
||||
return false;
|
||||
}
|
||||
CHash256 hasher;
|
||||
std::vector<unsigned char> vchHash(hasher.OUTPUT_SIZE);
|
||||
hasher.Write(vchToHash.data(), vchToHash.size());
|
||||
hasher.Finalize(&(vchHash[0]));
|
||||
uint256 calculatedHash(vchHash);
|
||||
previousComputedHash = calculatedHash;
|
||||
}
|
||||
if (previousComputedHash != rootHash) {
|
||||
return false;
|
||||
}
|
||||
if (proof.hasValue && !verifiedValue) {
|
||||
return false;
|
||||
}
|
||||
std::string::reverse_iterator itComputedName = computedReverseName.rbegin();
|
||||
std::string::const_iterator itName = name.begin();
|
||||
for (; itName != name.end() && itComputedName != computedReverseName.rend(); ++itName, ++itComputedName) {
|
||||
if (*itName != *itComputedName) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return (!proof.hasValue || itName == name.end());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(value_proof_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
|
||||
std::string sName1("a");
|
||||
std::string sValue1("testa");
|
||||
|
||||
std::string sName2("abc");
|
||||
std::string sValue2("testabc");
|
||||
|
||||
std::string sName3("abd");
|
||||
std::string sValue3("testabd");
|
||||
|
||||
std::string sName4("zyx");
|
||||
std::string sValue4("testzyx");
|
||||
|
||||
std::string sName5("zyxa");
|
||||
std::string sName6("omg");
|
||||
std::string sName7("");
|
||||
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1);
|
||||
COutPoint tx1OutPoint(tx1.GetHash(), 0);
|
||||
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName2, sValue2);
|
||||
COutPoint tx2OutPoint(tx2.GetHash(), 0);
|
||||
|
||||
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), sName3, sValue3);
|
||||
COutPoint tx3OutPoint(tx3.GetHash(), 0);
|
||||
|
||||
CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), sName4, sValue4);
|
||||
COutPoint tx4OutPoint(tx4.GetHash(), 0);
|
||||
CClaimValue val;
|
||||
|
||||
// create a claim. verify the expiration event has been scheduled.
|
||||
fixture.IncrementBlocks(5, true);
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
BOOST_CHECK(fixture.getInfoForName(sName1, val));
|
||||
BOOST_CHECK_EQUAL(val.outPoint, tx1OutPoint);
|
||||
BOOST_CHECK(fixture.getInfoForName(sName2, val));
|
||||
BOOST_CHECK_EQUAL(val.outPoint, tx2OutPoint);
|
||||
BOOST_CHECK(fixture.getInfoForName(sName3, val));
|
||||
BOOST_CHECK_EQUAL(val.outPoint, tx3OutPoint);
|
||||
BOOST_CHECK(fixture.getInfoForName(sName4, val));
|
||||
BOOST_CHECK_EQUAL(val.outPoint, tx4OutPoint);
|
||||
|
||||
CClaimTrieProof proof;
|
||||
|
||||
BOOST_CHECK(fixture.getProofForName(sName1, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName1));
|
||||
BOOST_CHECK_EQUAL(proof.outPoint, tx1OutPoint);
|
||||
|
||||
BOOST_CHECK(fixture.getProofForName(sName2, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName2));
|
||||
BOOST_CHECK_EQUAL(proof.outPoint, tx2OutPoint);
|
||||
|
||||
BOOST_CHECK(fixture.getProofForName(sName3, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName3));
|
||||
BOOST_CHECK_EQUAL(proof.outPoint, tx3OutPoint);
|
||||
|
||||
BOOST_CHECK(fixture.getProofForName(sName4, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName4));
|
||||
BOOST_CHECK_EQUAL(proof.outPoint, tx4OutPoint);
|
||||
|
||||
BOOST_CHECK(fixture.getProofForName(sName5, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName5));
|
||||
BOOST_CHECK_EQUAL(proof.hasValue, false);
|
||||
|
||||
BOOST_CHECK(fixture.getProofForName(sName6, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName6));
|
||||
BOOST_CHECK_EQUAL(proof.hasValue, false);
|
||||
|
||||
BOOST_CHECK(fixture.getProofForName(sName7, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName7));
|
||||
BOOST_CHECK_EQUAL(proof.hasValue, false);
|
||||
|
||||
CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), sName7, sValue4);
|
||||
COutPoint tx5OutPoint(tx5.GetHash(), 0);
|
||||
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
BOOST_CHECK(fixture.getInfoForName(sName7, val));
|
||||
BOOST_CHECK_EQUAL(val.outPoint, tx5OutPoint);
|
||||
|
||||
BOOST_CHECK(fixture.getProofForName(sName1, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName1));
|
||||
BOOST_CHECK_EQUAL(proof.outPoint, tx1OutPoint);
|
||||
|
||||
BOOST_CHECK(fixture.getProofForName(sName2, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName2));
|
||||
BOOST_CHECK_EQUAL(proof.outPoint, tx2OutPoint);
|
||||
|
||||
BOOST_CHECK(fixture.getProofForName(sName3, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName3));
|
||||
BOOST_CHECK_EQUAL(proof.outPoint, tx3OutPoint);
|
||||
|
||||
BOOST_CHECK(fixture.getProofForName(sName4, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName4));
|
||||
BOOST_CHECK_EQUAL(proof.outPoint, tx4OutPoint);
|
||||
|
||||
BOOST_CHECK(fixture.getProofForName(sName5, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName5));
|
||||
BOOST_CHECK_EQUAL(proof.hasValue, false);
|
||||
|
||||
BOOST_CHECK(fixture.getProofForName(sName6, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName6));
|
||||
BOOST_CHECK_EQUAL(proof.hasValue, false);
|
||||
|
||||
BOOST_CHECK(fixture.getProofForName(sName7, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName7));
|
||||
BOOST_CHECK_EQUAL(proof.outPoint, tx5OutPoint);
|
||||
|
||||
fixture.DecrementBlocks();
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
BOOST_CHECK(fixture.queueEmpty());
|
||||
}
|
||||
|
||||
// Check that blocks with bogus calimtrie hash is rejected
|
||||
BOOST_AUTO_TEST_CASE(bogus_claimtrie_hash_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
std::string sName("test");
|
||||
std::string sValue1("test");
|
||||
|
||||
int orig_chain_height = chainActive.Height();
|
||||
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue1, 1);
|
||||
|
||||
std::unique_ptr<CBlockTemplate> pblockTemp;
|
||||
BOOST_CHECK(pblockTemp = AssemblerForTest().CreateNewBlock(tx1.vout[0].scriptPubKey));
|
||||
pblockTemp->block.hashPrevBlock = chainActive.Tip()->GetBlockHash();
|
||||
pblockTemp->block.nVersion = 5;
|
||||
pblockTemp->block.nTime = chainActive.Tip()->GetBlockTime() + Params().GetConsensus().nPowTargetSpacing;
|
||||
CMutableTransaction txCoinbase(*pblockTemp->block.vtx[0]);
|
||||
txCoinbase.vin[0].scriptSig = CScript() << int(chainActive.Height() + 1) << 1;
|
||||
txCoinbase.vout[0].nValue = GetBlockSubsidy(chainActive.Height() + 1, Params().GetConsensus());
|
||||
pblockTemp->block.vtx[0] = MakeTransactionRef(std::move(txCoinbase));
|
||||
pblockTemp->block.hashMerkleRoot = BlockMerkleRoot(pblockTemp->block);
|
||||
//create bogus hash
|
||||
|
||||
uint256 bogusHashClaimTrie;
|
||||
bogusHashClaimTrie.SetHex("aaa");
|
||||
pblockTemp->block.hashClaimTrie = bogusHashClaimTrie;
|
||||
|
||||
for (uint32_t i = 0;; ++i) {
|
||||
pblockTemp->block.nNonce = i;
|
||||
if (CheckProofOfWork(pblockTemp->block.GetPoWHash(), pblockTemp->block.nBits, Params().GetConsensus())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool success = ProcessNewBlock(Params(), std::make_shared<const CBlock>(pblockTemp->block), true, nullptr);
|
||||
// will process , but will not be connected
|
||||
BOOST_CHECK(success);
|
||||
BOOST_CHECK(pblockTemp->block.GetHash() != chainActive.Tip()->GetBlockHash());
|
||||
BOOST_CHECK_EQUAL(orig_chain_height, chainActive.Height());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
|
@ -1,494 +0,0 @@
|
|||
// Copyright (c) 2015-2019 The LBRY Foundation
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://opensource.org/licenses/mit-license.php
|
||||
|
||||
#include <test/claimtriefixture.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(claimtrienormalization_tests, RegTestingSetup)
|
||||
|
||||
/*
|
||||
normalization
|
||||
test normalization function indpendent from rest of the code
|
||||
*/
|
||||
|
||||
BOOST_AUTO_TEST_CASE(normalization_only)
|
||||
{
|
||||
CClaimTrieCache ccache(pclaimTrie);
|
||||
|
||||
// basic ASCII casing tests
|
||||
BOOST_CHECK_EQUAL("test", ccache.normalizeClaimName("TESt", true));
|
||||
BOOST_CHECK_EQUAL("test", ccache.normalizeClaimName("tesT", true));
|
||||
BOOST_CHECK_EQUAL("test", ccache.normalizeClaimName("TesT", true));
|
||||
BOOST_CHECK_EQUAL("test", ccache.normalizeClaimName("test", true));
|
||||
BOOST_CHECK_EQUAL("test this", ccache.normalizeClaimName("Test This", true));
|
||||
|
||||
// test invalid utf8 bytes are returned as is
|
||||
BOOST_CHECK_EQUAL("\xFF", ccache.normalizeClaimName("\xFF", true));
|
||||
BOOST_CHECK_EQUAL("\xC3\x28", ccache.normalizeClaimName("\xC3\x28", true));
|
||||
|
||||
// ohm sign unicode code point \x2126 should be transformed to equivalent
|
||||
// unicode code point \x03C9 , greek small letter omega
|
||||
BOOST_CHECK_EQUAL("\xCF\x89", ccache.normalizeClaimName("\xE2\x84\xA6", true));
|
||||
|
||||
// cyrillic capital ef code point \x0424 should be transformed to lower case
|
||||
// \x0444
|
||||
BOOST_CHECK_EQUAL("\xD1\x84", ccache.normalizeClaimName("\xD0\xA4", true));
|
||||
|
||||
// armenian capital ben code point \x0532 should be transformed to lower case
|
||||
// \x0562
|
||||
BOOST_CHECK_EQUAL("\xD5\xA2", ccache.normalizeClaimName("\xD4\xB2", true));
|
||||
|
||||
// japanese pbu code point \x3076 should be transformed by NFD decomposition
|
||||
// into \x3075 and \x3099
|
||||
BOOST_CHECK_EQUAL("\xE3\x81\xB5\xE3\x82\x99",
|
||||
ccache.normalizeClaimName("\xE3\x81\xB6", true));
|
||||
|
||||
// hangul ggwalg unicode code point \xAF51 should be transformed by NFD
|
||||
// decomposition into unicode code points \x1101 \x116A \x11B0
|
||||
// source: http://unicode.org/L2/L2009/09052-tr47.html
|
||||
BOOST_CHECK_EQUAL("\xE1\x84\x81\xE1\x85\xAA\xE1\x86\xB0",
|
||||
ccache.normalizeClaimName("\xEA\xBD\x91", true));
|
||||
}
|
||||
|
||||
/*
|
||||
normalization
|
||||
check claim name normalization before the fork
|
||||
check claim name normalization after the fork
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(claimtriebranching_normalization)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
|
||||
// check claim names are not normalized
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "normalizeTest", "one", 3);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("normalizeTest", tx1));
|
||||
fixture.DecrementBlocks(1);
|
||||
BOOST_CHECK(fixture.getTotalNamesInTrie() == 0);
|
||||
fixture.CommitTx(tx1);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("normalizeTest", tx1));
|
||||
|
||||
CMutableTransaction tx2a = fixture.MakeClaim(fixture.GetCoinbase(), "Normalizetest", "one_a", 2);
|
||||
CMutableTransaction tx2 = fixture.MakeUpdate(tx2a, "Normalizetest", "one", ClaimIdHash(tx2a.GetHash(), 0), 2);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("normalizeTest", tx1));
|
||||
BOOST_CHECK(fixture.is_best_claim("Normalizetest", tx2));
|
||||
|
||||
// Activate the fork (which rebuilds the existing claimtrie and
|
||||
// cache), flattening all previously existing name clashes due to
|
||||
// the normalization
|
||||
fixture.setNormalizationForkHeight(2);
|
||||
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("normalizeTest", tx1));
|
||||
BOOST_CHECK(fixture.is_best_claim("Normalizetest", tx2));
|
||||
|
||||
fixture.IncrementBlocks(1, true);
|
||||
|
||||
// Post-fork, tx1 (the previous winning claim) assumes all name
|
||||
// variants of what it originally was ...
|
||||
BOOST_CHECK(fixture.is_best_claim("normalizetest", tx1));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("normalizetest", 3));
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->find("normalizeTest"));
|
||||
|
||||
// Check equivalence of normalized claim names
|
||||
BOOST_CHECK(fixture.is_best_claim("normalizetest", tx1)); // collapsed tx2
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "NORMALIZETEST", "one", 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(!fixture.is_best_claim("normalizetest", tx3));
|
||||
|
||||
CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "NoRmAlIzEtEsT", 2);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
// Ensure that supports work for normalized claim names
|
||||
BOOST_CHECK(fixture.is_best_claim("normalizetest", tx1)); // effective amount is 5
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("normalizetest", 5));
|
||||
|
||||
CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "foo", "bar", 1);
|
||||
CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(), tx4, "Foo", 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("foo", tx4));
|
||||
|
||||
CMutableTransaction u1 = fixture.MakeUpdate(tx4, "foo", "baz", ClaimIdHash(tx4.GetHash(), 0), 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("foo", u1));
|
||||
|
||||
CMutableTransaction u2 = fixture.MakeUpdate(tx1, "nOrmalIzEtEst", "two", ClaimIdHash(tx1.GetHash(), 0), 3);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
BOOST_CHECK(fixture.is_best_claim("normalizetest", u2));
|
||||
|
||||
// Add another set of unicode claims that will collapse after the fork
|
||||
CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), "Ame\u0301lie", "amelie", 2);
|
||||
fixture.IncrementBlocks(1);
|
||||
CClaimValue nval1;
|
||||
fixture.getInfoForName("amélie", nval1);
|
||||
BOOST_CHECK(nval1.claimId == ClaimIdHash(tx5.GetHash(), 0));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("amélie", 2));
|
||||
|
||||
// Check equivalence of normalized claim names
|
||||
BOOST_CHECK(fixture.is_best_claim("amélie", tx5));
|
||||
|
||||
CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(), "あてはまる", "jn1", 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("あてはまる", tx7));
|
||||
|
||||
CMutableTransaction tx8 = fixture.MakeClaim(fixture.GetCoinbase(), "AÑEJO", "es1", 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("añejo", tx8));
|
||||
|
||||
// Rewind to 1 block before the fork and be sure that the fork is no longer active
|
||||
fixture.DecrementBlocks();
|
||||
|
||||
// Now check that our old (non-normalized) claims are 'alive' again
|
||||
BOOST_CHECK(fixture.is_best_claim("normalizeTest", tx1));
|
||||
BOOST_CHECK(!fixture.is_best_claim("Normalizetest", tx1)); // no longer equivalent
|
||||
BOOST_CHECK(fixture.is_best_claim("Normalizetest", tx2));
|
||||
|
||||
// Create new claim
|
||||
CMutableTransaction tx9 = fixture.MakeClaim(fixture.GetCoinbase(), "blah", "blah", 1);
|
||||
std::string invalidUtf8("\xFF\xFF");
|
||||
CMutableTransaction tx10 = fixture.MakeClaim(fixture.GetCoinbase(), invalidUtf8, "blah", 1); // invalid UTF8
|
||||
|
||||
// Roll forward to fork height again and check again that we're normalized
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(chainActive.Height() == Params().GetConsensus().nNormalizedNameForkHeight);
|
||||
BOOST_CHECK(fixture.is_best_claim("normalizetest", tx1)); // collapsed tx2
|
||||
BOOST_CHECK(fixture.is_best_claim(invalidUtf8, tx10));
|
||||
|
||||
// Rewind to 1 block before the fork and be sure that the fork is
|
||||
// no longer active
|
||||
fixture.DecrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("Normalizetest", tx2));
|
||||
|
||||
// Roll forward to fork height again and check again that we're normalized
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(chainActive.Height() == Params().GetConsensus().nNormalizedNameForkHeight);
|
||||
BOOST_CHECK(fixture.is_best_claim("normalizetest", tx1)); // collapsed tx2
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(claimtriecache_normalization)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
|
||||
std::string name = "Ame\u0301lie";
|
||||
|
||||
std::string name_upper = "Amélie";
|
||||
std::string name_normd = "amélie"; // this accented e is not actually the same as the one above; this has been "normalized"
|
||||
|
||||
BOOST_CHECK(name != name_upper);
|
||||
|
||||
// Add another set of unicode claims that will collapse after the fork
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), name, "amilie", 2);
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), name_upper, "amelie", 2);
|
||||
fixture.MakeClaim(fixture.GetCoinbase(), "amelie1", "amelie", 2);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
CClaimValue lookupClaim;
|
||||
std::string lookupName;
|
||||
BOOST_CHECK(getClaimById(ClaimIdHash(tx2.GetHash(), 0), lookupName, &lookupClaim));
|
||||
CClaimValue nval1;
|
||||
BOOST_CHECK(fixture.getInfoForName("amelie1", nval1));
|
||||
// amélie is not found cause normalization still not appear
|
||||
BOOST_CHECK(!fixture.getInfoForName(name_normd, nval1));
|
||||
|
||||
// Activate the fork (which rebuilds the existing claimtrie and
|
||||
// cache), flattening all previously existing name clashes due to
|
||||
// the normalization
|
||||
fixture.setNormalizationForkHeight(1);
|
||||
int currentHeight = chainActive.Height();
|
||||
|
||||
fixture.IncrementBlocks(1);
|
||||
// Ok normalization fix the name problem
|
||||
BOOST_CHECK(fixture.getInfoForName(name_normd, nval1));
|
||||
BOOST_CHECK(nval1.nHeight == currentHeight);
|
||||
BOOST_CHECK(lookupClaim == nval1);
|
||||
|
||||
CCoinsViewCache coins(pcoinsTip.get());
|
||||
CClaimTrieCache trieCache(pclaimTrie);
|
||||
CBlockIndex* pindex = chainActive.Tip();
|
||||
CBlock block;
|
||||
int amelieValidHeight;
|
||||
BOOST_CHECK(trieCache.shouldNormalize());
|
||||
BOOST_CHECK(ReadBlockFromDisk(block, pindex, Params().GetConsensus()));
|
||||
BOOST_CHECK(g_chainstate.DisconnectBlock(block, pindex, coins, trieCache) == DisconnectResult::DISCONNECT_OK);
|
||||
BOOST_CHECK(!trieCache.shouldNormalize());
|
||||
BOOST_CHECK(!trieCache.spendClaim(name_normd, COutPoint(tx2.GetHash(), 0), currentHeight, amelieValidHeight));
|
||||
BOOST_CHECK(trieCache.spendClaim(name_upper, COutPoint(tx2.GetHash(), 0), currentHeight, amelieValidHeight));
|
||||
|
||||
BOOST_CHECK(!pclaimTrie->find(name));
|
||||
BOOST_CHECK(trieCache.getInfoForName(name, nval1));
|
||||
BOOST_CHECK(trieCache.addClaim(name, COutPoint(tx1.GetHash(), 0), ClaimIdHash(tx1.GetHash(), 0), CAmount(2), currentHeight + 1));
|
||||
BOOST_CHECK(trieCache.getInfoForName(name, nval1));
|
||||
insertUndoType insertUndo;
|
||||
claimQueueRowType expireUndo;
|
||||
insertUndoType insertSupportUndo;
|
||||
supportQueueRowType expireSupportUndo;
|
||||
std::vector<std::pair<std::string, int> > takeoverHeightUndo;
|
||||
BOOST_CHECK(trieCache.incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverHeightUndo));
|
||||
BOOST_CHECK(trieCache.shouldNormalize());
|
||||
|
||||
// we cannot use getXXXForName cause they will normalized name
|
||||
for (auto it = pclaimTrie->cbegin(); it != pclaimTrie->cend(); ++it)
|
||||
BOOST_CHECK(it.key() != name);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(undo_normalization_does_not_kill_claim_order)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
fixture.setNormalizationForkHeight(5);
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 1);
|
||||
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "a", "3", 3);
|
||||
fixture.IncrementBlocks(1);
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "2", 2);
|
||||
fixture.IncrementBlocks(2);
|
||||
BOOST_CHECK(fixture.is_best_claim("A", tx2));
|
||||
fixture.IncrementBlocks(3, true);
|
||||
BOOST_CHECK(fixture.is_best_claim("a", tx3));
|
||||
fixture.DecrementBlocks();
|
||||
BOOST_CHECK(fixture.is_best_claim("A", tx2));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(normalized_activations_fall_through)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
fixture.setNormalizationForkHeight(5);
|
||||
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "AB", "1", 1);
|
||||
fixture.IncrementBlocks(3);
|
||||
BOOST_CHECK(fixture.proportionalDelayFactor() == 1);
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "Ab", "2", 4);
|
||||
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "aB", "2", 3);
|
||||
CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "ab", "2", 2);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
BOOST_CHECK(fixture.is_best_claim("AB", tx1));
|
||||
fixture.IncrementBlocks(3);
|
||||
BOOST_CHECK(fixture.is_best_claim("ab", tx2));
|
||||
BOOST_CHECK(fixture.getClaimsForName("ab").claimsNsupports.size() == 4U);
|
||||
fixture.DecrementBlocks(3);
|
||||
fixture.Spend(tx1);
|
||||
fixture.Spend(tx2);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("ab", tx3));
|
||||
BOOST_CHECK(fixture.getClaimsForName("ab").claimsNsupports.size() == 2U);
|
||||
fixture.DecrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("AB", tx1));
|
||||
fixture.Spend(tx1);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("ab", tx2));
|
||||
|
||||
for (int i = 0; i < 7; ++i) {
|
||||
fixture.IncrementBlocks(i, true); // well into normalized teritory
|
||||
CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), "CD", "a", 1 + i);
|
||||
fixture.IncrementBlocks(3);
|
||||
CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(), "Cd", "b", 2 + i);
|
||||
CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(), "cD", "c", 3 + i);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("cd", tx5));
|
||||
fixture.Spend(tx5);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("cd", tx7));
|
||||
fixture.DecrementBlocks();
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(normalization_removal_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
fixture.setNormalizationForkHeight(2);
|
||||
fixture.IncrementBlocks(3);
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "AB", "1", 1);
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "Ab", "2", 2);
|
||||
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "aB", "3", 3);
|
||||
CMutableTransaction sx1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "AB", 1);
|
||||
CMutableTransaction sx2 = fixture.MakeSupport(fixture.GetCoinbase(), tx2, "Ab", 1);
|
||||
|
||||
CClaimTrieCache cache(pclaimTrie);
|
||||
int height = chainActive.Height() + 1;
|
||||
cache.addClaim("AB", COutPoint(tx1.GetHash(), 0), ClaimIdHash(tx1.GetHash(), 0), 1, height);
|
||||
cache.addClaim("Ab", COutPoint(tx2.GetHash(), 0), ClaimIdHash(tx2.GetHash(), 0), 2, height);
|
||||
cache.addClaim("aB", COutPoint(tx3.GetHash(), 0), ClaimIdHash(tx3.GetHash(), 0), 3, height);
|
||||
cache.addSupport("AB", COutPoint(sx1.GetHash(), 0), 1, ClaimIdHash(tx1.GetHash(), 0), height);
|
||||
cache.addSupport("Ab", COutPoint(sx2.GetHash(), 0), 1, ClaimIdHash(tx2.GetHash(), 0), height);
|
||||
insertUndoType insertUndo;
|
||||
claimQueueRowType expireUndo;
|
||||
insertUndoType insertSupportUndo;
|
||||
supportQueueRowType expireSupportUndo;
|
||||
std::vector<std::pair<std::string, int> > takeoverHeightUndo;
|
||||
BOOST_CHECK(cache.incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverHeightUndo));
|
||||
BOOST_CHECK(cache.getClaimsForName("ab").claimsNsupports.size() == 3U);
|
||||
BOOST_CHECK(cache.getClaimsForName("ab").claimsNsupports[0].supports.size() == 1U);
|
||||
BOOST_CHECK(cache.getClaimsForName("ab").claimsNsupports[1].supports.size() == 0U);
|
||||
BOOST_CHECK(cache.getClaimsForName("ab").claimsNsupports[2].supports.size() == 1U);
|
||||
BOOST_CHECK(cache.decrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo));
|
||||
BOOST_CHECK(cache.finalizeDecrement(takeoverHeightUndo));
|
||||
BOOST_CHECK(cache.undoAddSupport("AB", COutPoint(sx1.GetHash(), 0), height));
|
||||
BOOST_CHECK(cache.undoAddSupport("Ab", COutPoint(sx2.GetHash(), 0), height));
|
||||
BOOST_CHECK(cache.undoAddClaim("AB", COutPoint(tx1.GetHash(), 0), height));
|
||||
BOOST_CHECK(cache.undoAddClaim("Ab", COutPoint(tx2.GetHash(), 0), height));
|
||||
BOOST_CHECK(cache.undoAddClaim("aB", COutPoint(tx3.GetHash(), 0), height));
|
||||
BOOST_CHECK(cache.getClaimsForName("ab").claimsNsupports.size() == 0U);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(normalization_does_not_kill_supports)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
fixture.setNormalizationForkHeight(3);
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 1);
|
||||
fixture.MakeSupport(fixture.GetCoinbase(), tx1, "A", 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("A", 2));
|
||||
fixture.MakeSupport(fixture.GetCoinbase(), tx1, "A", 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("A", 3));
|
||||
fixture.MakeSupport(fixture.GetCoinbase(), tx1, "A", 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("a", 4));
|
||||
fixture.MakeSupport(fixture.GetCoinbase(), tx1, "A", 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("a", 5));
|
||||
|
||||
fixture.DecrementBlocks(1);
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("a", 4));
|
||||
fixture.DecrementBlocks(1);
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("A", 3));
|
||||
fixture.DecrementBlocks(1);
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("A", 2));
|
||||
fixture.IncrementBlocks(5);
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("a", 3));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(normalization_does_not_fail_on_spend)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
fixture.setNormalizationForkHeight(2);
|
||||
|
||||
std::string sName1("testN");
|
||||
std::string sName2("testn");
|
||||
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, "1", 3);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim(sName1, tx1));
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, "2", 2);
|
||||
CMutableTransaction tx1s = fixture.MakeSupport(fixture.GetCoinbase(), tx1, sName1, 2);
|
||||
fixture.IncrementBlocks(2, true);
|
||||
BOOST_CHECK(fixture.is_best_claim(sName2, tx1));
|
||||
|
||||
CMutableTransaction tx3 = fixture.Spend(tx1); // abandon the claim
|
||||
CMutableTransaction tx3s = fixture.Spend(tx1s);
|
||||
fixture.IncrementBlocks(2);
|
||||
BOOST_CHECK(fixture.is_best_claim(sName2, tx2));
|
||||
fixture.DecrementBlocks();
|
||||
BOOST_CHECK(fixture.is_best_claim(sName1, tx1));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(normalization_does_not_kill_sort_order)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
fixture.setNormalizationForkHeight(2);
|
||||
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 1);
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "2", 2);
|
||||
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "a", "3", 3);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("A", tx2));
|
||||
BOOST_CHECK(fixture.is_best_claim("a", tx3));
|
||||
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(!fixture.is_best_claim("A", tx2));
|
||||
BOOST_CHECK(fixture.is_best_claim("a", tx3));
|
||||
BOOST_CHECK(fixture.getClaimsForName("a").claimsNsupports.size() == 3U);
|
||||
|
||||
fixture.DecrementBlocks(1);
|
||||
BOOST_CHECK(fixture.is_best_claim("A", tx2));
|
||||
BOOST_CHECK(fixture.is_best_claim("a", tx3));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(normalization_does_not_kill_expirations)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
auto& consensus = Params().GetConsensus();
|
||||
fixture.setExpirationForkHeight(consensus.nExtendedClaimExpirationForkHeight, 3, consensus.nExtendedClaimExpirationTime);
|
||||
fixture.setNormalizationForkHeight(4);
|
||||
// need to see that claims expiring on the frame when we normalize aren't kept
|
||||
// need to see that supports expiring on the frame when we normalize aren't kept
|
||||
// need to see that claims & supports carried through the normalization fork do expire
|
||||
// and that they come back correctly when we roll backwards
|
||||
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 1);
|
||||
fixture.MakeSupport(fixture.GetCoinbase(), tx1, "A", 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("A", 2));
|
||||
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "B", "1", 1);
|
||||
fixture.MakeSupport(fixture.GetCoinbase(), tx2, "B", 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("A", 2));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("B", 2));
|
||||
|
||||
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "C", "1", 1);
|
||||
fixture.MakeSupport(fixture.GetCoinbase(), tx3, "C", 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("A", 2));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("B", 2));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("C", 2));
|
||||
|
||||
CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "D", "1", 1);
|
||||
fixture.MakeSupport(fixture.GetCoinbase(), tx4, "D", 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("a", 2));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("b", 2));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("c", 2));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("d", 2));
|
||||
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("a", 2));
|
||||
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("b", 2));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("c", 2));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("d", 2));
|
||||
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("a", 2));
|
||||
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("b", 2));
|
||||
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("c", 2));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("d", 2));
|
||||
|
||||
fixture.IncrementBlocks(1);
|
||||
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("a", 2));
|
||||
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("b", 2));
|
||||
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("c", 2));
|
||||
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("d", 2));
|
||||
|
||||
fixture.DecrementBlocks(2);
|
||||
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("a", 2));
|
||||
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("b", 2));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("c", 2));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("d", 2));
|
||||
|
||||
fixture.DecrementBlocks(1);
|
||||
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("a", 2));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("b", 2));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("c", 2));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("d", 2));
|
||||
|
||||
fixture.DecrementBlocks(1);
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("A", 2));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("B", 2));
|
||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("C", 2));
|
||||
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("d", 2));
|
||||
|
||||
fixture.IncrementBlocks(3);
|
||||
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("a", 2));
|
||||
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("b", 2));
|
||||
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("c", 2));
|
||||
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("d", 2)); // (not re-added)
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
|
@ -1,407 +0,0 @@
|
|||
// Copyright (c) 2015-2019 The LBRY Foundation
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://opensource.org/licenses/mit-license.php
|
||||
|
||||
#include <test/claimtriefixture.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
extern void ValidatePairs(CClaimTrieCache& cache, const std::vector<std::pair<bool, uint256>>& pairs, uint256 claimHash);
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(claimtrierpc_tests, RegTestingSetup)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(getnamesintrie_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
std::string sName1("test");
|
||||
std::string sValue1("test");
|
||||
|
||||
uint256 blockHash = chainActive.Tip()->GetBlockHash();
|
||||
|
||||
fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 42);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
rpcfn_type getnamesintrie = tableRPC["getnamesintrie"]->actor;
|
||||
JSONRPCRequest req;
|
||||
req.params = UniValue(UniValue::VARR);
|
||||
|
||||
UniValue results = getnamesintrie(req);
|
||||
BOOST_CHECK_EQUAL(results.size(), 1U);
|
||||
|
||||
req.params.push_back(blockHash.GetHex());
|
||||
|
||||
results = getnamesintrie(req);
|
||||
BOOST_CHECK_EQUAL(results.size(), 0U);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(getvalueforname_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
std::string sName1("testN");
|
||||
std::string sValue1("testV");
|
||||
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 2);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
uint256 blockHash = chainActive.Tip()->GetBlockHash();
|
||||
|
||||
fixture.MakeSupport(fixture.GetCoinbase(), tx1, sName1, 3);
|
||||
fixture.IncrementBlocks(10);
|
||||
|
||||
rpcfn_type getvalueforname = tableRPC["getvalueforname"]->actor;
|
||||
JSONRPCRequest req;
|
||||
req.params = UniValue(UniValue::VARR);
|
||||
req.params.push_back(UniValue(sName1));
|
||||
|
||||
UniValue results = getvalueforname(req);
|
||||
BOOST_CHECK_EQUAL(results[T_VALUE].get_str(), HexStr(sValue1));
|
||||
BOOST_CHECK_EQUAL(results[T_AMOUNT].get_int(), 2);
|
||||
BOOST_CHECK_EQUAL(results[T_EFFECTIVEAMOUNT].get_int(), 5);
|
||||
|
||||
req.params.push_back(blockHash.GetHex());
|
||||
|
||||
results = getvalueforname(req);
|
||||
BOOST_CHECK_EQUAL(results[T_AMOUNT].get_int(), 2);
|
||||
BOOST_CHECK_EQUAL(results[T_EFFECTIVEAMOUNT].get_int(), 2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(getclaimsforname_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
std::string sName1("testN");
|
||||
std::string sValue1("test1");
|
||||
std::string sValue2("test2");
|
||||
|
||||
int height = chainActive.Height();
|
||||
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 2);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
uint256 blockHash = chainActive.Tip()->GetBlockHash();
|
||||
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue2, 3);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
rpcfn_type getclaimsforname = tableRPC["getclaimsforname"]->actor;
|
||||
JSONRPCRequest req;
|
||||
req.params = UniValue(UniValue::VARR);
|
||||
req.params.push_back(UniValue(sName1));
|
||||
|
||||
UniValue results = getclaimsforname(req);
|
||||
UniValue claims = results[T_CLAIMS];
|
||||
BOOST_CHECK_EQUAL(claims.size(), 2U);
|
||||
BOOST_CHECK_EQUAL(results[T_LASTTAKEOVERHEIGHT].get_int(), height + 1);
|
||||
BOOST_CHECK_EQUAL(claims[0][T_EFFECTIVEAMOUNT].get_int(), 2);
|
||||
BOOST_CHECK_EQUAL(claims[0][T_SUPPORTS].size(), 0U);
|
||||
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
results = getclaimsforname(req);
|
||||
claims = results[T_CLAIMS];
|
||||
BOOST_CHECK_EQUAL(claims.size(), 2U);
|
||||
BOOST_CHECK_EQUAL(results[T_LASTTAKEOVERHEIGHT].get_int(), height + 3);
|
||||
BOOST_CHECK_EQUAL(claims[0][T_EFFECTIVEAMOUNT].get_int(), 3);
|
||||
BOOST_CHECK_EQUAL(claims[1][T_EFFECTIVEAMOUNT].get_int(), 2);
|
||||
BOOST_CHECK_EQUAL(claims[0][T_SUPPORTS].size(), 0U);
|
||||
BOOST_CHECK_EQUAL(claims[1][T_SUPPORTS].size(), 0U);
|
||||
|
||||
req.params.push_back(blockHash.GetHex());
|
||||
|
||||
results = getclaimsforname(req);
|
||||
claims = results[T_CLAIMS];
|
||||
BOOST_CHECK_EQUAL(claims.size(), 1U);
|
||||
BOOST_CHECK_EQUAL(results[T_LASTTAKEOVERHEIGHT].get_int(), height + 1);
|
||||
BOOST_CHECK_EQUAL(claims[0][T_EFFECTIVEAMOUNT].get_int(), 2);
|
||||
BOOST_CHECK_EQUAL(claims[0][T_SUPPORTS].size(), 0U);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(claim_rpcs_rollback2_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
std::string sName1("testN");
|
||||
std::string sValue1("test1");
|
||||
std::string sValue2("test2");
|
||||
|
||||
int height = chainActive.Height();
|
||||
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 1);
|
||||
fixture.IncrementBlocks(2);
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue2, 2);
|
||||
fixture.IncrementBlocks(3);
|
||||
|
||||
uint256 blockHash = chainActive.Tip()->GetBlockHash();
|
||||
|
||||
CMutableTransaction tx3 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, sValue1, 3);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
rpcfn_type getclaimsforname = tableRPC["getclaimsforname"]->actor;
|
||||
rpcfn_type getvalueforname = tableRPC["getvalueforname"]->actor;
|
||||
JSONRPCRequest req;
|
||||
req.params = UniValue(UniValue::VARR);
|
||||
req.params.push_back(UniValue(sName1));
|
||||
req.params.push_back(blockHash.GetHex());
|
||||
|
||||
UniValue claimsResults = getclaimsforname(req);
|
||||
BOOST_CHECK_EQUAL(claimsResults[T_LASTTAKEOVERHEIGHT].get_int(), height + 5);
|
||||
BOOST_CHECK_EQUAL(claimsResults[T_CLAIMS][0][T_SUPPORTS].size(), 0U);
|
||||
BOOST_CHECK_EQUAL(claimsResults[T_CLAIMS][1][T_SUPPORTS].size(), 0U);
|
||||
|
||||
UniValue valueResults = getvalueforname(req);
|
||||
BOOST_CHECK_EQUAL(valueResults[T_VALUE].get_str(), HexStr(sValue2));
|
||||
BOOST_CHECK_EQUAL(valueResults[T_AMOUNT].get_int(), 2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(claim_rpcs_rollback3_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
std::string sName1("testN");
|
||||
std::string sValue1("test1");
|
||||
std::string sValue2("test2");
|
||||
|
||||
int height = chainActive.Height();
|
||||
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 3);
|
||||
fixture.IncrementBlocks(1);
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue2, 2);
|
||||
fixture.IncrementBlocks(2);
|
||||
|
||||
uint256 blockHash = chainActive.Tip()->GetBlockHash();
|
||||
|
||||
CMutableTransaction tx3 = fixture.Spend(tx1); // abandon the claim
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
rpcfn_type getclaimsforname = tableRPC["getclaimsforname"]->actor;
|
||||
rpcfn_type getvalueforname = tableRPC["getvalueforname"]->actor;
|
||||
rpcfn_type getblocktemplate = tableRPC["getblocktemplate"]->actor;
|
||||
|
||||
JSONRPCRequest req;
|
||||
req.params = UniValue(UniValue::VARR);
|
||||
UniValue templateResults = getblocktemplate(req);
|
||||
BOOST_CHECK_EQUAL(templateResults["claimtrie"].get_str(), chainActive.Tip()->hashClaimTrie.GetHex());
|
||||
|
||||
req.params.push_back(UniValue(sName1));
|
||||
req.params.push_back(blockHash.GetHex());
|
||||
|
||||
UniValue claimsResults = getclaimsforname(req);
|
||||
BOOST_CHECK_EQUAL(claimsResults[T_LASTTAKEOVERHEIGHT].get_int(), height + 1);
|
||||
|
||||
UniValue valueResults = getvalueforname(req);
|
||||
BOOST_CHECK_EQUAL(valueResults[T_VALUE].get_str(), HexStr(sValue1));
|
||||
BOOST_CHECK_EQUAL(valueResults[T_AMOUNT].get_int(), 3);
|
||||
}
|
||||
|
||||
std::vector<std::pair<bool, uint256>> jsonToPairs(const UniValue& jsonPair)
|
||||
{
|
||||
std::vector<std::pair<bool, uint256>> pairs;
|
||||
for (std::size_t i = 0; i < jsonPair.size(); ++i) {
|
||||
auto& jpair = jsonPair[i];
|
||||
pairs.emplace_back(jpair[T_ODD].get_bool(), uint256S(jpair[T_HASH].get_str()));
|
||||
}
|
||||
return pairs;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(hash_bid_seq_claim_changes_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
fixture.setHashForkHeight(2);
|
||||
fixture.IncrementBlocks(4);
|
||||
|
||||
std::string name = "toa";
|
||||
std::string value1 = "one", value2 = "two", value3 = "tre", value4 = "for";
|
||||
|
||||
auto tx1 = fixture.MakeClaim(fixture.GetCoinbase(), name, value1, 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
CMutableTransaction tx2 = BuildTransaction(fixture.GetCoinbase(), 0, 2);
|
||||
tx2.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME
|
||||
<< std::vector<unsigned char>(name.begin(), name.end())
|
||||
<< std::vector<unsigned char>(value2.begin(), value2.end()) << OP_2DROP << OP_DROP << OP_TRUE;
|
||||
tx2.vout[0].nValue = 3;
|
||||
tx2.vout[1].scriptPubKey = CScript() << OP_CLAIM_NAME
|
||||
<< std::vector<unsigned char>(name.begin(), name.end())
|
||||
<< std::vector<unsigned char>(value3.begin(), value3.end()) << OP_2DROP << OP_DROP << OP_TRUE;
|
||||
tx2.vout[1].nValue = 2;
|
||||
|
||||
fixture.CommitTx(tx2);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
auto tx3 = fixture.MakeClaim(fixture.GetCoinbase(), name, value4, 4);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
int height = chainActive.Height();
|
||||
|
||||
auto claimId1 = ClaimIdHash(tx1.GetHash(), 0);
|
||||
auto claimId2 = ClaimIdHash(tx2.GetHash(), 0);
|
||||
auto claimId3 = ClaimIdHash(tx2.GetHash(), 1);
|
||||
auto claimId4 = ClaimIdHash(tx3.GetHash(), 0);
|
||||
|
||||
int claim1bid = 3, claim1seq = 0;
|
||||
int claim2bid = 1, claim2seq = 1;
|
||||
int claim3bid = 2, claim3seq = 2;
|
||||
int claim4bid = 0, claim4seq = 3;
|
||||
|
||||
auto getclaimsforname = tableRPC["getclaimsforname"]->actor;
|
||||
|
||||
JSONRPCRequest req;
|
||||
req.params = UniValue(UniValue::VARR);
|
||||
req.params.push_back(UniValue(name));
|
||||
|
||||
auto result = getclaimsforname(req);
|
||||
auto claims = result[T_CLAIMS];
|
||||
BOOST_CHECK_EQUAL(claims.size(), 4U);
|
||||
BOOST_CHECK_EQUAL(result[T_LASTTAKEOVERHEIGHT].get_int(), height);
|
||||
BOOST_CHECK_EQUAL(claims[0][T_EFFECTIVEAMOUNT].get_int(), 4);
|
||||
BOOST_CHECK_EQUAL(claims[0][T_BID].get_int(), claim4bid);
|
||||
BOOST_CHECK_EQUAL(claims[0][T_SEQUENCE].get_int(), claim4seq);
|
||||
BOOST_CHECK_EQUAL(claims[0][T_CLAIMID].get_str(), claimId4.GetHex());
|
||||
BOOST_CHECK_EQUAL(claims[1][T_EFFECTIVEAMOUNT].get_int(), 3);
|
||||
BOOST_CHECK_EQUAL(claims[1][T_BID].get_int(), claim2bid);
|
||||
BOOST_CHECK_EQUAL(claims[1][T_SEQUENCE].get_int(), claim2seq);
|
||||
BOOST_CHECK_EQUAL(claims[1][T_CLAIMID].get_str(), claimId2.GetHex());
|
||||
BOOST_CHECK_EQUAL(claims[2][T_EFFECTIVEAMOUNT].get_int(), 2);
|
||||
BOOST_CHECK_EQUAL(claims[2][T_BID].get_int(), claim3bid);
|
||||
BOOST_CHECK_EQUAL(claims[2][T_SEQUENCE].get_int(), claim3seq);
|
||||
BOOST_CHECK_EQUAL(claims[2][T_CLAIMID].get_str(), claimId3.GetHex());
|
||||
BOOST_CHECK_EQUAL(claims[3][T_EFFECTIVEAMOUNT].get_int(), 1);
|
||||
BOOST_CHECK_EQUAL(claims[3][T_BID].get_int(), claim1bid);
|
||||
BOOST_CHECK_EQUAL(claims[3][T_SEQUENCE].get_int(), claim1seq);
|
||||
BOOST_CHECK_EQUAL(claims[3][T_CLAIMID].get_str(), claimId1.GetHex());
|
||||
|
||||
auto getclaimbybid = tableRPC["getclaimbybid"]->actor;
|
||||
req.params = UniValue(UniValue::VARR);
|
||||
req.params.push_back(UniValue(name));
|
||||
req.params.push_back(UniValue(claim3bid));
|
||||
|
||||
result = getclaimbybid(req);
|
||||
BOOST_CHECK_EQUAL(result[T_LASTTAKEOVERHEIGHT].get_int(), height);
|
||||
BOOST_CHECK_EQUAL(result[T_EFFECTIVEAMOUNT].get_int(), 2);
|
||||
BOOST_CHECK_EQUAL(result[T_BID].get_int(), claim3bid);
|
||||
BOOST_CHECK_EQUAL(result[T_SEQUENCE].get_int(), claim3seq);
|
||||
BOOST_CHECK_EQUAL(result[T_CLAIMID].get_str(), claimId3.GetHex());
|
||||
|
||||
auto getclaimbyseq = tableRPC["getclaimbyseq"]->actor;
|
||||
req.params = UniValue(UniValue::VARR);
|
||||
req.params.push_back(UniValue(name));
|
||||
req.params.push_back(UniValue(claim2seq));
|
||||
|
||||
result = getclaimbyseq(req);
|
||||
BOOST_CHECK_EQUAL(result[T_LASTTAKEOVERHEIGHT].get_int(), height);
|
||||
BOOST_CHECK_EQUAL(result[T_EFFECTIVEAMOUNT].get_int(), 3);
|
||||
BOOST_CHECK_EQUAL(result[T_BID].get_int(), claim2bid);
|
||||
BOOST_CHECK_EQUAL(result[T_SEQUENCE].get_int(), claim2seq);
|
||||
BOOST_CHECK_EQUAL(result[T_CLAIMID].get_str(), claimId2.GetHex());
|
||||
|
||||
auto getclaimbyid = tableRPC["getclaimbyid"]->actor;
|
||||
req.params = UniValue(UniValue::VARR);
|
||||
req.params.push_back(UniValue(claimId1.GetHex()));
|
||||
|
||||
result = getclaimbyid(req);
|
||||
BOOST_CHECK_EQUAL(result[T_LASTTAKEOVERHEIGHT].get_int(), height);
|
||||
BOOST_CHECK_EQUAL(result[T_EFFECTIVEAMOUNT].get_int(), 1);
|
||||
BOOST_CHECK_EQUAL(result[T_BID].get_int(), claim1bid);
|
||||
BOOST_CHECK_EQUAL(result[T_SEQUENCE].get_int(), claim1seq);
|
||||
BOOST_CHECK_EQUAL(result[T_CLAIMID].get_str(), claimId1.GetHex());
|
||||
|
||||
// check by partial id (at least 3 chars)
|
||||
req.params = UniValue(UniValue::VARR);
|
||||
req.params.push_back(UniValue(claimId3.GetHex().substr(0, 3)));
|
||||
|
||||
result = getclaimbyid(req);
|
||||
BOOST_CHECK_EQUAL(result[T_LASTTAKEOVERHEIGHT].get_int(), height);
|
||||
BOOST_CHECK_EQUAL(result[T_EFFECTIVEAMOUNT].get_int(), 2);
|
||||
BOOST_CHECK_EQUAL(result[T_BID].get_int(), claim3bid);
|
||||
BOOST_CHECK_EQUAL(result[T_SEQUENCE].get_int(), claim3seq);
|
||||
BOOST_CHECK_EQUAL(result[T_CLAIMID].get_str(), claimId3.GetHex());
|
||||
|
||||
auto blockhash = chainActive.Tip()->GetBlockHash();
|
||||
|
||||
auto getnameproof = tableRPC["getnameproof"]->actor;
|
||||
req.params = UniValue(UniValue::VARR);
|
||||
req.params.push_back(UniValue(name));
|
||||
req.params.push_back(UniValue(blockhash.GetHex()));
|
||||
req.params.push_back(UniValue(claimId3.GetHex()));
|
||||
|
||||
result = getnameproof(req);
|
||||
auto claimHash = getValueHash(COutPoint(tx2.GetHash(), 1), result[T_LASTTAKEOVERHEIGHT].get_int());
|
||||
ValidatePairs(fixture, jsonToPairs(result[T_PAIRS]), claimHash);
|
||||
|
||||
// check by partial id (can be even 1 char)
|
||||
req.params = UniValue(UniValue::VARR);
|
||||
req.params.push_back(UniValue(name));
|
||||
req.params.push_back(UniValue(blockhash.GetHex()));
|
||||
req.params.push_back(UniValue(claimId2.GetHex().substr(0, 2)));
|
||||
|
||||
result = getnameproof(req);
|
||||
claimHash = getValueHash(COutPoint(tx2.GetHash(), 0), result[T_LASTTAKEOVERHEIGHT].get_int());
|
||||
ValidatePairs(fixture, jsonToPairs(result[T_PAIRS]), claimHash);
|
||||
|
||||
auto getclaimproofbybid = tableRPC["getclaimproofbybid"]->actor;
|
||||
req.params = UniValue(UniValue::VARR);
|
||||
req.params.push_back(UniValue(name));
|
||||
req.params.push_back(UniValue(claim1bid));
|
||||
|
||||
result = getclaimproofbybid(req);
|
||||
claimHash = getValueHash(COutPoint(tx1.GetHash(), 0), result[T_LASTTAKEOVERHEIGHT].get_int());
|
||||
ValidatePairs(fixture, jsonToPairs(result[T_PAIRS]), claimHash);
|
||||
|
||||
auto getclaimproofbyseq = tableRPC["getclaimproofbyseq"]->actor;
|
||||
req.params = UniValue(UniValue::VARR);
|
||||
req.params.push_back(UniValue(name));
|
||||
req.params.push_back(UniValue(claim4seq));
|
||||
|
||||
result = getclaimproofbyseq(req);
|
||||
claimHash = getValueHash(COutPoint(tx3.GetHash(), 0), result[T_LASTTAKEOVERHEIGHT].get_int());
|
||||
ValidatePairs(fixture, jsonToPairs(result[T_PAIRS]), claimHash);
|
||||
|
||||
auto getchangesinblock = tableRPC["getchangesinblock"]->actor;
|
||||
req.params = UniValue(UniValue::VARR);
|
||||
req.params.push_back(UniValue(blockhash.GetHex()));
|
||||
|
||||
result = getchangesinblock(req);
|
||||
BOOST_CHECK_EQUAL(result[T_CLAIMSADDEDORUPDATED].size(), 3);
|
||||
BOOST_CHECK_EQUAL(result[T_CLAIMSADDEDORUPDATED][0].get_str(), claimId2.GetHex());
|
||||
BOOST_CHECK_EQUAL(result[T_CLAIMSADDEDORUPDATED][1].get_str(), claimId3.GetHex());
|
||||
BOOST_CHECK_EQUAL(result[T_CLAIMSADDEDORUPDATED][2].get_str(), claimId4.GetHex());
|
||||
BOOST_CHECK_EQUAL(result[T_CLAIMSREMOVED].size(), 0);
|
||||
BOOST_CHECK_EQUAL(result[T_SUPPORTSADDEDORUPDATED].size(), 0);
|
||||
BOOST_CHECK_EQUAL(result[T_SUPPORTSREMOVED].size(), 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(claim_rpc_pending_amount_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
std::string sName1("test");
|
||||
std::string sValue1("test1");
|
||||
std::string sValue2("test2");
|
||||
|
||||
rpcfn_type getclaimsforname = tableRPC["getclaimsforname"]->actor;
|
||||
|
||||
JSONRPCRequest req;
|
||||
req.params = UniValue(UniValue::VARR);
|
||||
req.params.push_back(UniValue(sName1));
|
||||
|
||||
fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 1);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue2, 2);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
auto claims = getclaimsforname(req)[T_CLAIMS];
|
||||
BOOST_CHECK_EQUAL(claims.size(), 2U);
|
||||
BOOST_CHECK_EQUAL(claims[0][T_EFFECTIVEAMOUNT].get_int(), 1);
|
||||
BOOST_CHECK(!claims[0].exists(T_PENDINGAMOUNT));
|
||||
BOOST_CHECK_EQUAL(claims[1][T_EFFECTIVEAMOUNT].get_int(), 0);
|
||||
BOOST_CHECK(claims[1].exists(T_PENDINGAMOUNT));
|
||||
BOOST_CHECK_EQUAL(claims[1][T_PENDINGAMOUNT].get_int(), 2);
|
||||
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
claims = getclaimsforname(req)[T_CLAIMS];
|
||||
BOOST_CHECK_EQUAL(claims.size(), 2U);
|
||||
BOOST_CHECK_EQUAL(claims[0][T_EFFECTIVEAMOUNT].get_int(), 2);
|
||||
BOOST_CHECK(!claims[0].exists(T_PENDINGAMOUNT));
|
||||
BOOST_CHECK_EQUAL(claims[1][T_EFFECTIVEAMOUNT].get_int(), 1);
|
||||
BOOST_CHECK(!claims[1].exists(T_PENDINGAMOUNT));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
|
@ -28,7 +28,7 @@
|
|||
"76a91453c0307d6851aa0ce7825ba883c6bd9ad242b48688ac",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "lbrycrdreg"
|
||||
"chain": "regtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -72,7 +72,7 @@
|
|||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"chain": "lbrycrdreg"
|
||||
"chain": "regtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -90,7 +90,7 @@
|
|||
{
|
||||
"isCompressed": true,
|
||||
"isPrivkey": true,
|
||||
"chain": "lbrycrdreg"
|
||||
"chain": "regtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -294,7 +294,7 @@
|
|||
{
|
||||
"isCompressed": false,
|
||||
"isPrivkey": true,
|
||||
"chain": "lbrycrdreg"
|
||||
"chain": "regtest"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -481,7 +481,7 @@
|
|||
"001428e40f9a66993a8d50b2604af71b17e1606842d8",
|
||||
{
|
||||
"isPrivkey": false,
|
||||
"chain": "lbrycrdreg",
|
||||
"chain": "regtest",
|
||||
"tryCaseFlip": true
|
||||
}
|
||||
]
|
||||
|
|
|
@ -458,6 +458,9 @@
|
|||
["NOP", "CHECKSEQUENCEVERIFY 1", "P2SH,STRICTENC", "OK"],
|
||||
["NOP", "NOP4 1", "P2SH,STRICTENC", "OK"],
|
||||
["NOP", "NOP5 1", "P2SH,STRICTENC", "OK"],
|
||||
["NOP", "NOP6 1", "P2SH,STRICTENC", "OK"],
|
||||
["NOP", "NOP7 1", "P2SH,STRICTENC", "OK"],
|
||||
["NOP", "NOP8 1", "P2SH,STRICTENC", "OK"],
|
||||
["NOP", "NOP9 1", "P2SH,STRICTENC", "OK"],
|
||||
["NOP", "NOP10 1", "P2SH,STRICTENC", "OK"],
|
||||
|
||||
|
@ -866,8 +869,8 @@
|
|||
["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
|
||||
["2 1 RSHIFT", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
|
||||
|
||||
["1", "NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
|
||||
["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
|
||||
["1", "NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
|
||||
["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
|
||||
|
||||
["Ensure 100% coverage of discouraged NOPS"],
|
||||
["1", "NOP1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
|
||||
|
@ -1790,7 +1793,7 @@
|
|||
"2-of-2 with two identical keys and sigs pushed using OP_DUP"
|
||||
],
|
||||
[
|
||||
"0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP9 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
|
||||
"0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
|
||||
"HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL",
|
||||
"",
|
||||
"OK",
|
||||
|
@ -1804,14 +1807,14 @@
|
|||
"P2PK with non-push scriptSig but with P2SH validation"
|
||||
],
|
||||
[
|
||||
"0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP9 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
|
||||
"0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
|
||||
"HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL",
|
||||
"P2SH",
|
||||
"SIG_PUSHONLY",
|
||||
"P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY"
|
||||
],
|
||||
[
|
||||
"0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP9 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
|
||||
"0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
|
||||
"HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL",
|
||||
"SIGPUSHONLY",
|
||||
"SIG_PUSHONLY",
|
||||
|
|
|
@ -8,6 +8,7 @@ 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");
|
||||
|
@ -30,18 +31,7 @@ BOOST_AUTO_TEST_CASE(calc_min_claimtrie_fee)
|
|||
CMutableTransaction tx4;
|
||||
tx4.vout.resize(1);
|
||||
BOOST_CHECK_EQUAL(CalcMinClaimTrieFee(tx4,MIN_FEE_PER_NAMECLAIM_CHAR), 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(support_handles_value)
|
||||
{
|
||||
auto script = SupportClaimScript("s1", uint160(), "me value");
|
||||
int op = 0;
|
||||
std::vector<std::vector<unsigned char>> params;
|
||||
BOOST_CHECK(!DecodeClaimScript(script, op, params, false));
|
||||
params.clear();
|
||||
BOOST_CHECK(DecodeClaimScript(script, op, params));
|
||||
BOOST_CHECK(params[0][0] == 's');
|
||||
BOOST_CHECK(std::string(params[2].begin(), params[2].end()) == "me value");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(scriptToAsmStr_output)
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include <random.h>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <test/claimtriefixture.h>
|
||||
#include <test/test_bitcoin.h>
|
||||
|
||||
#include <chrono>
|
||||
|
@ -38,79 +37,7 @@ std::vector<std::string> random_strings(std::size_t count)
|
|||
|
||||
using namespace std;
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(prefixtrie_tests, RegTestingSetup)
|
||||
|
||||
#ifndef MAC_OSX // can't find a random number generator that produces the same sequence on OSX
|
||||
BOOST_AUTO_TEST_CASE(triehash_fuzzer_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
|
||||
auto envClaims = std::getenv("TRIEHASH_FUZZER_CLAIMS");
|
||||
auto envBlocks = std::getenv("TRIEHASH_FUZZER_BLOCKS");
|
||||
|
||||
const int claimsPerBlock = envClaims ? std::atoi(envClaims) : 100;
|
||||
const int blocks = envBlocks ? std::atoi(envBlocks) : 13;
|
||||
|
||||
auto names = random_strings(blocks * claimsPerBlock);
|
||||
|
||||
FastRandomContext frc(true);
|
||||
std::unordered_map<std::string, std::vector<CMutableTransaction>> existingClaims;
|
||||
std::vector<CMutableTransaction> existingSupports;
|
||||
std::string value(1024, 'c');
|
||||
|
||||
std::vector<CTransaction> cb {fixture.GetCoinbase()};
|
||||
for (int i = 0; i < blocks; ++i) {
|
||||
for (int j = 0; j < claimsPerBlock; ++j) {
|
||||
auto name = names[i * claimsPerBlock + j];
|
||||
auto supportFront = frc.randrange(4) == 0;
|
||||
auto supportBack = frc.randrange(4) == 0;
|
||||
auto removeClaim = frc.randrange(4) == 0;
|
||||
auto removeSupport = frc.randrange(4) == 0;
|
||||
auto hit = existingClaims.find(name);
|
||||
if (supportFront && hit != existingClaims.end() && hit->second.size()) {
|
||||
auto tx = fixture.MakeSupport(cb.back(), hit->second[frc.rand64() % hit->second.size()], name, 2);
|
||||
existingSupports.push_back(tx);
|
||||
cb.emplace_back(std::move(tx));
|
||||
}
|
||||
if (removeClaim && hit != existingClaims.end() && hit->second.size()) {
|
||||
auto idx = frc.rand64() % hit->second.size();
|
||||
fixture.Spend(hit->second[idx]);
|
||||
hit->second.erase(hit->second.begin() + idx);
|
||||
} else {
|
||||
auto tx = fixture.MakeClaim(cb.back(), name, value, 2);
|
||||
existingClaims[name].push_back(tx);
|
||||
hit = existingClaims.find(name);
|
||||
cb.emplace_back(std::move(tx));
|
||||
}
|
||||
if (supportBack && hit != existingClaims.end() && hit->second.size()) {
|
||||
auto tx = fixture.MakeSupport(cb.back(), hit->second[frc.rand64() % hit->second.size()], name, 2);
|
||||
existingSupports.push_back(tx);
|
||||
cb.emplace_back(std::move(tx));
|
||||
}
|
||||
if (removeSupport && (i & 7) == 7 && !existingSupports.empty()) {
|
||||
const auto tidx = frc.rand64() % existingSupports.size();
|
||||
const auto tx = existingSupports[tidx];
|
||||
fixture.Spend(tx);
|
||||
existingSupports.erase(existingSupports.begin() + tidx);
|
||||
}
|
||||
if (cb.back().GetValueOut() < 10 || cb.size() > 40000) {
|
||||
cb.clear();
|
||||
cb.push_back(fixture.GetCoinbase());
|
||||
}
|
||||
}
|
||||
fixture.IncrementBlocks(1);
|
||||
if (blocks > 13 && i % 50 == 0) // travisCI needs some periodic output
|
||||
std::cerr << "In triehash_fuzzer_test with " << fixture.getTotalNamesInTrie() << " names at block " << i << std::endl;
|
||||
}
|
||||
|
||||
if (blocks == 1000 && claimsPerBlock == 100)
|
||||
BOOST_CHECK_EQUAL(fixture.getMerkleHash().GetHex(), "28825257a129eef69cab87d6255c8359fc6dc083ca7f09222526e3a7971f382d");
|
||||
else if (blocks == 13 && claimsPerBlock == 100)
|
||||
BOOST_CHECK_EQUAL(fixture.getMerkleHash().GetHex(), "4e5984d6984f5f05d50e821e6228d56bcfbd16ca2093cd0308f6ff1c2bc8689a");
|
||||
else
|
||||
std::cerr << "Hash: " << fixture.getMerkleHash().GetHex() << std::endl;
|
||||
}
|
||||
#endif
|
||||
BOOST_FIXTURE_TEST_SUITE(prefixtrie_tests, BasicTestingSetup)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(insert_erase_test)
|
||||
{
|
||||
|
|
|
@ -719,16 +719,16 @@ BOOST_AUTO_TEST_CASE(script_build)
|
|||
).Num(0).PushSig(keys.key1).Add(CScript() << OP_DUP).ScriptError(SCRIPT_ERR_SIG_PUSHONLY));
|
||||
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
|
||||
"P2SH(P2PK) with non-push scriptSig but no P2SH or SIGPUSHONLY", 0, true
|
||||
).PushSig(keys.key2).Add(CScript() << OP_NOP9).PushRedeem());
|
||||
).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_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_NOP9).PushRedeem().ScriptError(SCRIPT_ERR_SIG_PUSHONLY));
|
||||
).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem().ScriptError(SCRIPT_ERR_SIG_PUSHONLY));
|
||||
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
|
||||
"P2SH(P2PK) with non-push scriptSig but not P2SH", SCRIPT_VERIFY_SIGPUSHONLY, true
|
||||
).PushSig(keys.key2).Add(CScript() << OP_NOP9).PushRedeem().ScriptError(SCRIPT_ERR_SIG_PUSHONLY));
|
||||
).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem().ScriptError(SCRIPT_ERR_SIG_PUSHONLY));
|
||||
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG,
|
||||
"2-of-2 with two identical keys and sigs pushed", SCRIPT_VERIFY_SIGPUSHONLY
|
||||
).Num(0).PushSig(keys.key1).PushSig(keys.key1));
|
||||
|
|
|
@ -81,10 +81,10 @@ std::ostream& operator<<(std::ostream& os, const CClaimValue& claim)
|
|||
std::ostream& operator<<(std::ostream& os, const CSupportValue& support)
|
||||
{
|
||||
os << "support(" << support.outPoint.ToString()
|
||||
<< ", " << support.supportedClaimId.ToString()
|
||||
<< ", " << support.nAmount
|
||||
<< ", " << support.nHeight
|
||||
<< ", " << support.nValidAtHeight << ')';
|
||||
<< ", " << support.supportedClaimId.ToString()
|
||||
<< ", " << support.nAmount
|
||||
<< ", " << support.nHeight
|
||||
<< ", " << support.nValidAtHeight << ')';
|
||||
return os;
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
|
|||
pblocktree.reset(new CBlockTreeDB(1 << 20, true));
|
||||
pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true));
|
||||
pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get()));
|
||||
pclaimTrie = new CClaimTrie(true, false, 1);
|
||||
pclaimTrie = new CClaimTrieHashFork(true, false, 1);
|
||||
if (!LoadGenesisBlock(chainparams)) {
|
||||
throw std::runtime_error("LoadGenesisBlock failed.");
|
||||
}
|
||||
|
|
|
@ -701,7 +701,7 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
|
|||
|
||||
// Check dust with default relay fee:
|
||||
CAmount nDustThreshold = 182 * dustRelayFee.GetFeePerK()/1000;
|
||||
BOOST_CHECK_EQUAL(nDustThreshold, 182);
|
||||
BOOST_CHECK_EQUAL(nDustThreshold, 546);
|
||||
// dust:
|
||||
t.vout[0].nValue = nDustThreshold - 1;
|
||||
BOOST_CHECK(!IsStandardTx(t, reason));
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
#include <util.h>
|
||||
|
||||
#include <chainparamsbase.h>
|
||||
#include <clientversion.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <sync.h>
|
||||
|
@ -559,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(), CBaseChainParams::MAIN);
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "lbrycrd");
|
||||
|
||||
test_args.ParseParameters(2, (char**)argv_testnet, error);
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), CBaseChainParams::TESTNET);
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "lbrycrdtest");
|
||||
|
||||
test_args.ParseParameters(2, (char**)argv_regtest, error);
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), CBaseChainParams::REGTEST);
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "regtest");
|
||||
|
||||
test_args.ParseParameters(3, (char**)argv_test_no_reg, error);
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), CBaseChainParams::TESTNET);
|
||||
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(), CBaseChainParams::TESTNET);
|
||||
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(), CBaseChainParams::TESTNET);
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "lbrycrdtest");
|
||||
|
||||
test_args.ParseParameters(2, (char**)argv_regtest, error);
|
||||
test_args.ReadConfigString(testnetconf);
|
||||
|
@ -587,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(), CBaseChainParams::TESTNET);
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "lbrycrdtest");
|
||||
|
||||
test_args.ParseParameters(3, (char**)argv_both, error);
|
||||
test_args.ReadConfigString(testnetconf);
|
||||
|
@ -599,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(), CBaseChainParams::TESTNET);
|
||||
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(), CBaseChainParams::TESTNET);
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "lbrycrdtest");
|
||||
|
||||
test_args.ParseParameters(2, (char**)argv_regtest, error);
|
||||
test_args.ReadConfigString(testnetconf);
|
||||
|
@ -611,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(), CBaseChainParams::TESTNET);
|
||||
BOOST_CHECK_EQUAL(test_args.GetChainName(), "lbrycrdtest");
|
||||
|
||||
test_args.ParseParameters(3, (char**)argv_both, error);
|
||||
test_args.ReadConfigString(testnetconf);
|
||||
|
|
|
@ -26,7 +26,7 @@ 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 = 560;
|
||||
static const int64_t nDefaultDbCache = 500;
|
||||
//! -dbbatchsize default (bytes)
|
||||
static const int64_t nDefaultDbBatchSize = 16 << 20;
|
||||
//! max. -dbcache (MiB)
|
||||
|
@ -34,13 +34,13 @@ static const int64_t nMaxDbCache = sizeof(void*) > 4 ? 16384 : 1024;
|
|||
//! min. -dbcache (MiB)
|
||||
static const int64_t nMinDbCache = 4;
|
||||
//! Max memory allocated to block tree DB specific cache, if no -txindex (MiB)
|
||||
static const int64_t nMaxBlockDBCache = 16;
|
||||
static const int64_t nMaxBlockDBCache = 4;
|
||||
//! Max memory allocated to block tree DB specific cache, if -txindex (MiB)
|
||||
// Unlike for the UTXO database, for the txindex scenario the leveldb cache make
|
||||
// a meaningful difference: https://github.com/bitcoin/bitcoin/pull/8273#issuecomment-229601991
|
||||
static const int64_t nMaxTxIndexCache = 1024;
|
||||
//! Max memory allocated to coin DB specific cache (MiB)
|
||||
static const int64_t nMaxCoinsDBCache = 32;
|
||||
static const int64_t nMaxCoinsDBCache = 8;
|
||||
|
||||
/** CCoinsView backed by the coin database (chainstate/) */
|
||||
class CCoinsViewDB final : public CCoinsView
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
set -e
|
||||
srcdir="$(dirname $0)"
|
||||
cd "$srcdir"
|
||||
if [ -z ${LIBTOOLIZE} ] && GLIBTOOLIZE="$(which glibtoolize 2>/dev/null)"; then
|
||||
if [ -z ${LIBTOOLIZE} ] && GLIBTOOLIZE="`which glibtoolize 2>/dev/null`"; then
|
||||
LIBTOOLIZE="${GLIBTOOLIZE}"
|
||||
export LIBTOOLIZE
|
||||
fi
|
||||
|
|
|
@ -1562,8 +1562,12 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI
|
|||
assert(trieCache.finalizeDecrement(blockUndo.takeoverHeightUndo));
|
||||
auto merkleHash = trieCache.getMerkleHash();
|
||||
if (merkleHash != pindex->pprev->hashClaimTrie) {
|
||||
if (!trieCache.empty())
|
||||
trieCache.dumpToLog(trieCache.find({}));
|
||||
for (auto cit = trieCache.begin(); cit != trieCache.end(); ++cit) {
|
||||
if (cit->claims.size() && cit->nHeightOfLastTakeover <= 0)
|
||||
LogPrintf("Invalid takeover height discovered in cache for %s\n", cit.key());
|
||||
if (cit->hash.IsNull())
|
||||
LogPrintf("Invalid hash discovered in cache for %s\n", cit.key());
|
||||
}
|
||||
LogPrintf("Hash comparison failure at block %d\n", pindex->nHeight);
|
||||
assert(merkleHash == pindex->pprev->hashClaimTrie);
|
||||
}
|
||||
|
@ -2041,7 +2045,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
|
|||
if (trieCache.getMerkleHash() != block.hashClaimTrie)
|
||||
{
|
||||
if (!trieCache.empty()) // we could run checkConsistency here, but it would take a while
|
||||
trieCache.dumpToLog(trieCache.find({}));
|
||||
trieCache.dumpToLog(trieCache.begin());
|
||||
return state.DoS(100, error("ConnectBlock() : the merkle root of the claim trie does not match "
|
||||
"(actual=%s vs block=%s on height=%d)", trieCache.getMerkleHash().GetHex(),
|
||||
block.hashClaimTrie.GetHex(), pindex->nHeight), REJECT_INVALID, "bad-claim-merkle-hash");
|
||||
|
@ -2184,7 +2188,7 @@ 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 (mode == FlushStateMode::ALWAYS && !pclaimTrie->SyncToDisk())
|
||||
if (!pclaimTrie->SyncToDisk())
|
||||
return state.Error("Failed to write to claim trie database");
|
||||
// Flush the chainstate (which may refer to block index entries).
|
||||
if (!pcoinsTip->Flush())
|
||||
|
@ -2250,8 +2254,7 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar
|
|||
}
|
||||
|
||||
std::string warningMessages;
|
||||
auto isInitialBlockDownload = IsInitialBlockDownload();
|
||||
if (!isInitialBlockDownload)
|
||||
if (!IsInitialBlockDownload())
|
||||
{
|
||||
int nUpgraded = 0;
|
||||
const CBlockIndex* pindex = pindexNew;
|
||||
|
@ -2286,7 +2289,8 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar
|
|||
}
|
||||
static int64_t lastBlockPrintTime = 0;
|
||||
auto currentTime = GetAdjustedTime();
|
||||
if (!warningMessages.empty() || !isInitialBlockDownload || lastBlockPrintTime < currentTime - 15 || LogAcceptCategory(BCLog::CLAIMS)) {
|
||||
auto oldBlock = pindexNew->nTime + MAX_FUTURE_BLOCK_TIME < currentTime;
|
||||
if (!warningMessages.empty() || !oldBlock || lastBlockPrintTime < currentTime - 15 || LogAcceptCategory(BCLog::CLAIMS)) {
|
||||
lastBlockPrintTime = currentTime;
|
||||
LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%.8g txb=%lu tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)%s",
|
||||
__func__, pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, pindexNew->nVersion,
|
||||
|
@ -2294,11 +2298,12 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar
|
|||
(unsigned long) pindexNew->nChainTx, FormatISO8601DateTime(pindexNew->GetBlockTime()),
|
||||
GuessVerificationProgress(chainParams.TxData(), pindexNew),
|
||||
pcoinsTip->DynamicMemoryUsage() * (1.0 / (1U << 20U)), pcoinsTip->GetCacheSize(),
|
||||
isInitialBlockDownload ? " IBD" : "");
|
||||
oldBlock ? " (synchronizing)" : "");
|
||||
if (!warningMessages.empty())
|
||||
LogPrintf(" warning='%s'", warningMessages); /* Continued */
|
||||
LogPrintf("\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Disconnect chainActive's tip.
|
||||
|
@ -2772,15 +2777,13 @@ bool CChainState::ActivateBestChain(CValidationState &state, const CChainParams&
|
|||
if (ShutdownRequested())
|
||||
break;
|
||||
} while (pindexNewTip != pindexMostWork);
|
||||
|
||||
auto& consensus = chainparams.GetConsensus();
|
||||
CheckBlockIndex(consensus);
|
||||
CheckBlockIndex(chainparams.GetConsensus());
|
||||
|
||||
auto flushMode = FlushStateMode::PERIODIC;
|
||||
if (pindexNewTip && chainparams.NetworkIDString() != CBaseChainParams::REGTEST
|
||||
&& pindexNewTip->nTime + consensus.nPowTargetSpacing > GetAdjustedTime()) {
|
||||
if (pindexNewTip && pindexNewTip->nTime + chainparams.GetConsensus().nPowTargetSpacing > GetAdjustedTime()) {
|
||||
// trying to ensure that we flush to disk after new blocks when we're caught up to the chain
|
||||
// they're technically allowed to be two hours late, but experience says one minute is more likely
|
||||
// LogPrintf("Added tip with time %d but it is now %ll\n", pindexNewTip->nTime, GetAdjustedTime());
|
||||
flushMode = FlushStateMode::ALWAYS;
|
||||
}
|
||||
return FlushStateToDisk(chainparams, state, flushMode);
|
||||
|
|
|
@ -57,7 +57,7 @@ static const bool DEFAULT_WHITELISTFORCERELAY = true;
|
|||
/** Default for -minrelaytxfee, minimum relay fee for transactions */
|
||||
static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = 1000;
|
||||
//! -maxtxfee default
|
||||
static const CAmount DEFAULT_TRANSACTION_MAXFEE = 0.5 * COIN;
|
||||
static const CAmount DEFAULT_TRANSACTION_MAXFEE = 0.1 * COIN;
|
||||
//! Discourage users to set fees higher than this amount (in satoshis) per kB
|
||||
static const CAmount HIGH_TX_FEE_PER_KB = 0.01 * COIN;
|
||||
//! -maxtxfee will warn if called with a higher fee than this amount (in satoshis)
|
||||
|
|
|
@ -204,10 +204,9 @@ public:
|
|||
ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache)
|
||||
{
|
||||
// Check if we've past a hardfork state for segwit.
|
||||
if (pos == Consensus::DEPLOYMENT_SEGWIT) {
|
||||
return pindexPrev != nullptr && pindexPrev->nHeight + 1 >= params.nWitnessForkHeight ?
|
||||
ThresholdState::ACTIVE : ThresholdState::FAILED;
|
||||
}
|
||||
if ((pos == Consensus::DEPLOYMENT_SEGWIT) && (pindexPrev != nullptr) &&
|
||||
(pindexPrev->nHeight + 1 >= params.nWitnessForkHeight))
|
||||
return ThresholdState::ACTIVE;
|
||||
|
||||
return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, cache.caches[pos]);
|
||||
}
|
||||
|
|
|
@ -469,10 +469,10 @@ bool BerkeleyEnvironment::Salvage(const std::string& strFile, bool fAggressive,
|
|||
}
|
||||
|
||||
|
||||
void BerkeleyEnvironment::CheckpointLSN(const std::string& strFile, bool lsnReset)
|
||||
void BerkeleyEnvironment::CheckpointLSN(const std::string& strFile)
|
||||
{
|
||||
dbenv->txn_checkpoint(0, 0, 0);
|
||||
if (fMockDb || !lsnReset)
|
||||
if (fMockDb)
|
||||
return;
|
||||
dbenv->lsn_reset(strFile.c_str(), 0);
|
||||
}
|
||||
|
@ -799,7 +799,7 @@ bool BerkeleyBatch::PeriodicFlush(BerkeleyDatabase& database)
|
|||
|
||||
// Flush wallet file so it's self contained
|
||||
env->CloseDb(strFile);
|
||||
env->CheckpointLSN(strFile, false); // too expensive to reset LSN periodically (and it's triggered on flush or backup
|
||||
env->CheckpointLSN(strFile);
|
||||
|
||||
env->mapFileUseCount.erase(mi++);
|
||||
LogPrint(BCLog::DB, "Flushed %s %dms\n", strFile, GetTimeMillis() - nStart);
|
||||
|
|
|
@ -83,7 +83,7 @@ public:
|
|||
bool Open(bool retry);
|
||||
void Close();
|
||||
void Flush(bool fShutdown);
|
||||
void CheckpointLSN(const std::string& strFile, bool lsnReset = true);
|
||||
void CheckpointLSN(const std::string& strFile);
|
||||
|
||||
void CloseDb(const std::string& strFile);
|
||||
void ReloadDbEnv();
|
||||
|
|
|
@ -808,7 +808,7 @@ UniValue listnameclaims(const JSONRPCRequest& request)
|
|||
|
||||
if (request.fHelp || request.params.size() > 3)
|
||||
throw std::runtime_error(
|
||||
"listnameclaims ( includesuppports activeonly minconf )\n"
|
||||
"listnameclaims includesuppports activeonly minconf\n"
|
||||
"Return a list of all transactions claiming names.\n"
|
||||
"\nArguments\n"
|
||||
"1. includesupports (bool, optional) Whether to also include claim supports. Default is true.\n"
|
||||
|
@ -882,7 +882,7 @@ UniValue supportclaim(const JSONRPCRequest& request)
|
|||
|
||||
if (request.fHelp || request.params.size() < 1 || request.params.size() > 5)
|
||||
throw std::runtime_error(
|
||||
"supportclaim \"name\" ( \"claimid\" amount \"value\" isTip ) \n"
|
||||
"supportclaim \"name\" \"claimid\" \"amount\" \"value\"\n"
|
||||
"Increase the value of a claim. Whichever claim has the greatest value, including all support values, will be the authoritative claim, according to the rest of the rules. The name is the name which is claimed by the claim that will be supported, the txid is the txid\
|
||||
of the claim that will be supported, nout is the transaction output which contains the claim to be supported, and amount is the amount which will be added to the value of the claim. If the claim is currently the authoritative claim, this support will go into effect immediately \
|
||||
. Otherwise, it will go into effect after 100 blocks. The support will be in effect until it is spent, and will lose its effect when the claim is spent or expires. The amount is a real and is rounded to the nearest .00000001\n"
|
||||
|
@ -918,7 +918,7 @@ UniValue supportclaim(const JSONRPCRequest& request)
|
|||
CClaimTrieCache trieCache(pclaimTrie);
|
||||
auto csToName = trieCache.getClaimsForName(sName);
|
||||
if (csToName.claimsNsupports.empty())
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Unable to find a claim named %s", sName));
|
||||
return NullUniValue;
|
||||
auto& claimNsupports = !sClaimId.empty() ? csToName.find(sClaimId) : csToName.claimsNsupports[0];
|
||||
if (claimNsupports.IsNull())
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Unable to find a claimid that starts with %s", sClaimId));
|
||||
|
@ -935,7 +935,7 @@ UniValue supportclaim(const JSONRPCRequest& request)
|
|||
if (!hex.empty()) {
|
||||
if (!IsHex(hex))
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "value/metadata must be of hexadecimal data");
|
||||
if (!trieCache.allowSupportMetadata())
|
||||
if (!IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus()))
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "value/metadata on supports is not enabled yet");
|
||||
supportScript = supportScript << ParseHex(hex);
|
||||
lastOp = OP_2DROP;
|
||||
|
@ -1914,68 +1914,6 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request)
|
|||
return result;
|
||||
}
|
||||
|
||||
static UniValue addtimelockedaddress(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) {
|
||||
std::string msg = "addtimelockedaddress timelock address ( \"label\" \"address_type\" )\n"
|
||||
"\nAdd an address that can't be redeemed until timelock. Requires a new wallet backup.\n"
|
||||
"See `importaddress` for watchonly p2sh address support.\n"
|
||||
"If 'label' is specified, assign address to that label.\n"
|
||||
|
||||
"\nArguments:\n"
|
||||
"1. timelock (numeric, required) Block height if < 500 million or unix timestamp if greater.\n"
|
||||
"1. \"address\" (string, required) The destination wallet address.\n"
|
||||
"2. \"label\" (string, optional) A label to assign the addresses to.\n"
|
||||
"3. \"address_type\" (string, optional) The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\". Default is set by -addresstype.\n"
|
||||
|
||||
"\nResult:\n"
|
||||
"{\n"
|
||||
" \"address\":\"address\", (string) The value of the new P2SH address.\n"
|
||||
" \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
|
||||
"}\n"
|
||||
;
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
|
||||
auto timelock = request.params[0].get_int();
|
||||
std::string label;
|
||||
if (!request.params[2].isNull())
|
||||
label = LabelFromValue(request.params[2]);
|
||||
|
||||
LOCK2(cs_main, pwallet->cs_wallet);
|
||||
|
||||
auto address = request.params[1].get_str();
|
||||
CTxDestination destination = DecodeDestination(address);
|
||||
if (!IsValidDestination(destination)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid LBRY address: ") + address);
|
||||
}
|
||||
auto destinationScript = GetScriptForDestination(destination);
|
||||
|
||||
OutputType output_type = pwallet->m_default_address_type;
|
||||
if (!request.params[3].isNull()) {
|
||||
if (!ParseOutputType(request.params[3].get_str(), output_type)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[3].get_str()));
|
||||
}
|
||||
}
|
||||
|
||||
// Construct using pay-to-script-hash:
|
||||
CScript inner = (CScript() << CScriptNum(timelock) << OP_CHECKLOCKTIMEVERIFY << OP_DROP) + destinationScript;
|
||||
CTxDestination dest = AddAndGetDestinationForScript(*pwallet, inner, output_type);
|
||||
pwallet->SetAddressBook(dest, label, "timelock");
|
||||
|
||||
UniValue result(UniValue::VOBJ);
|
||||
result.pushKV("address", EncodeDestination(dest));
|
||||
result.pushKV("redeemScript", HexStr(inner.begin(), inner.end()));
|
||||
return result;
|
||||
}
|
||||
|
||||
class Witnessifier : public boost::static_visitor<bool>
|
||||
{
|
||||
public:
|
||||
|
@ -3600,9 +3538,6 @@ static UniValue getwalletinfo(const JSONRPCRequest& request)
|
|||
" \"walletname\": xxxxx, (string) the wallet name\n"
|
||||
" \"walletversion\": xxxxx, (numeric) the wallet version\n"
|
||||
" \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
|
||||
" \"available_balance\": xxxxxxx, (numeric) balance minus stakes in " + CURRENCY_UNIT + "\n"
|
||||
" \"staked_claim_balance\": xxxxxxx, (numeric) total in claim reservations in " + CURRENCY_UNIT + "\n"
|
||||
" \"staked_support_balance\": xxxxxxx, (numeric) total in support reservations in " + CURRENCY_UNIT + "\n"
|
||||
" \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
|
||||
" \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + CURRENCY_UNIT + "\n"
|
||||
" \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n"
|
||||
|
@ -3631,13 +3566,7 @@ static UniValue getwalletinfo(const JSONRPCRequest& request)
|
|||
size_t kpExternalSize = pwallet->KeypoolCountExternalKeys();
|
||||
obj.pushKV("walletname", pwallet->GetName());
|
||||
obj.pushKV("walletversion", pwallet->GetVersion());
|
||||
auto balance = pwallet->GetBalance();
|
||||
auto claims = pwallet->GetBalance(ISMINE_CLAIM);
|
||||
auto supports = pwallet->GetBalance(ISMINE_SUPPORT);
|
||||
obj.pushKV("balance", ValueFromAmount(balance));
|
||||
obj.pushKV("available_balance", ValueFromAmount(balance - claims - supports));
|
||||
obj.pushKV("staked_claim_balance", ValueFromAmount(claims));
|
||||
obj.pushKV("staked_support_balance", ValueFromAmount(supports));
|
||||
obj.pushKV("balance", ValueFromAmount(pwallet->GetBalance()));
|
||||
obj.pushKV("unconfirmed_balance", ValueFromAmount(pwallet->GetUnconfirmedBalance()));
|
||||
obj.pushKV("immature_balance", ValueFromAmount(pwallet->GetImmatureBalance()));
|
||||
obj.pushKV("txcount", (int)pwallet->mapWallet.size());
|
||||
|
@ -5367,7 +5296,6 @@ static const CRPCCommand commands[] =
|
|||
{ "wallet", "abandontransaction", &abandontransaction, {"txid"} },
|
||||
{ "wallet", "abortrescan", &abortrescan, {} },
|
||||
{ "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","label|account","address_type"} },
|
||||
{ "wallet", "addtimelockedaddress", &addtimelockedaddress, {"timelock", "address", "label|account","address_type"} },
|
||||
{ "hidden", "addwitnessaddress", &addwitnessaddress, {"address","p2sh"} },
|
||||
{ "wallet", "backupwallet", &backupwallet, {"destination"} },
|
||||
{ "wallet", "bumpfee", &bumpfee, {"txid", "options"} },
|
||||
|
@ -5432,11 +5360,11 @@ static const CRPCCommand commands[] =
|
|||
|
||||
{ "generating", "generate", &generate, {"nblocks","maxtries"} },
|
||||
|
||||
{ "Claimtrie", "claimname", &claimname, {"name","value","amount"} },
|
||||
{ "Claimtrie", "updateclaim", &updateclaim, {"txid","value","amount"} },
|
||||
{ "Claimtrie", "claimname", &claimname, {"name","value","amount","address_type"} },
|
||||
{ "Claimtrie", "updateclaim", &updateclaim, {"txid","value","amount","address_type"} },
|
||||
{ "Claimtrie", "abandonclaim", &abandonclaim, {"txid","address"} },
|
||||
{ "Claimtrie", "listnameclaims", &listnameclaims, {"includesuppports","activeonly","minconf"} },
|
||||
{ "Claimtrie", "supportclaim", &supportclaim, {"name","claimid","amount","value"} },
|
||||
{ "Claimtrie", "supportclaim", &supportclaim, {"name","claimid","amount","value","address_type"} },
|
||||
{ "Claimtrie", "abandonsupport", &abandonsupport, {"txid","address"} },
|
||||
};
|
||||
|
||||
|
|
|
@ -63,10 +63,6 @@ uint256 ClaimAName(const std::string& name, const std::string& data, const std::
|
|||
UniValue results = rpc_method(req);
|
||||
auto txid = results.get_str();
|
||||
uint256 ret;
|
||||
if (txid.find(' ') != std::string::npos) {
|
||||
fprintf(stderr, "Error creating claim: %s\n", txid.c_str());
|
||||
return ret;
|
||||
}
|
||||
ret.SetHex(txid);
|
||||
return ret;
|
||||
}
|
||||
|
@ -155,17 +151,6 @@ uint256 AbandonAClaim(const uint256& txid, bool isSupport = false) {
|
|||
}
|
||||
}
|
||||
|
||||
void ValidateBalance(double claims, double supports) {
|
||||
rpcfn_type rpc_method = tableRPC["getwalletinfo"]->actor;
|
||||
JSONRPCRequest req;
|
||||
req.URI = "/wallet/tester_wallet";
|
||||
req.params = UniValue(UniValue::VARR);
|
||||
UniValue results = rpc_method(req);
|
||||
BOOST_CHECK_EQUAL(claims, results["staked_claim_balance"].get_real());
|
||||
BOOST_CHECK_EQUAL(supports, results["staked_support_balance"].get_real());
|
||||
BOOST_CHECK_EQUAL(claims + supports, results["balance"].get_real() - results["available_balance"].get_real());
|
||||
}
|
||||
|
||||
void AddClaimSupportThenRemove() {
|
||||
generateBlock(155);
|
||||
BOOST_CHECK_EQUAL(AvailableBalance(), 55.0);
|
||||
|
@ -205,8 +190,6 @@ void AddClaimSupportThenRemove() {
|
|||
BOOST_CHECK_EQUAL(looked[1]["txid"].get_str(), spid.GetHex());
|
||||
BOOST_CHECK_EQUAL(looked[1]["supported_claimid"].get_str(), clid);
|
||||
|
||||
ValidateBalance(1.0, 0.5);
|
||||
|
||||
// abandon support
|
||||
auto aid1 = AbandonAClaim(spid, true);
|
||||
BOOST_CHECK(!aid1.IsNull());
|
||||
|
@ -472,24 +455,5 @@ BOOST_AUTO_TEST_CASE(can_sign_all_pbst)
|
|||
BOOST_CHECK_EQUAL(looked.size(), 0U);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(can_claim_after_each_fork)
|
||||
{
|
||||
generateBlock(140);
|
||||
auto txid = ClaimAName("tester", "deadbeef", "1.0");
|
||||
BOOST_CHECK(!txid.IsNull());
|
||||
generateBlock(100);
|
||||
txid = ClaimAName("tester2", "deadbeef", "1.0");
|
||||
BOOST_CHECK(!txid.IsNull());
|
||||
generateBlock(100);
|
||||
txid = ClaimAName("tester3", "deadbeef", "10.0");
|
||||
BOOST_CHECK(!txid.IsNull());
|
||||
generateBlock(15);
|
||||
txid = ClaimAName("tester4", "deadbeef", "10.0");
|
||||
BOOST_CHECK(!txid.IsNull());
|
||||
generateBlock(1);
|
||||
auto looked = LookupAllNames().get_array();
|
||||
BOOST_CHECK_EQUAL(looked.size(), 4U);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
|
|
|
@ -166,7 +166,7 @@ public:
|
|||
txnouttype type;
|
||||
std::vector<CTxDestination> vDest;
|
||||
int nRequired;
|
||||
if (ExtractDestinations(StripClaimScriptPrefix(script), type, vDest, nRequired)) {
|
||||
if (ExtractDestinations(script, type, vDest, nRequired)) {
|
||||
for (const CTxDestination &dest : vDest)
|
||||
boost::apply_visitor(*this, dest);
|
||||
}
|
||||
|
@ -2985,7 +2985,6 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
|
|||
if (nChangePosInOut == -1 && nSubtractFeeFromAmount == 0 && pick_new_inputs) {
|
||||
unsigned int tx_size_with_change = nBytes + coin_selection_params.change_output_size + 2; // Add 2 as a buffer in case increasing # of outputs changes compact size
|
||||
CAmount fee_needed_with_change = GetMinimumFee(*this, tx_size_with_change, coin_control, ::mempool, ::feeEstimator, nullptr);
|
||||
fee_needed_with_change = std::max(minClaimTrieFee, fee_needed_with_change);
|
||||
CAmount minimum_value_for_change = GetDustThreshold(change_prototype_txout, discard_rate);
|
||||
if (nFeeRet >= fee_needed_with_change + minimum_value_for_change) {
|
||||
pick_new_inputs = false;
|
||||
|
|
|
@ -18,12 +18,12 @@ if test "x$1" = "x"; then
|
|||
fi
|
||||
|
||||
RET=0
|
||||
PREV_BRANCH=$(git name-rev --name-only HEAD)
|
||||
PREV_HEAD=$(git rev-parse HEAD)
|
||||
for i in $(git rev-list --reverse $1); do
|
||||
PREV_BRANCH=`git name-rev --name-only HEAD`
|
||||
PREV_HEAD=`git rev-parse HEAD`
|
||||
for i in `git rev-list --reverse $1`; do
|
||||
if git rev-list -n 1 --pretty="%s" $i | grep -q "^scripted-diff:"; then
|
||||
git checkout --quiet $i^ || exit
|
||||
SCRIPT="$(git rev-list --format=%b -n1 $i | sed '/^-BEGIN VERIFY SCRIPT-$/,/^-END VERIFY SCRIPT-$/{//!b};d')"
|
||||
SCRIPT="`git rev-list --format=%b -n1 $i | sed '/^-BEGIN VERIFY SCRIPT-$/,/^-END VERIFY SCRIPT-$/{//!b};d'`"
|
||||
if test "x$SCRIPT" = "x"; then
|
||||
echo "Error: missing script for: $i"
|
||||
echo "Failed"
|
||||
|
|
Loading…
Reference in a new issue