Compare commits
6 commits
master
...
add_signat
Author | SHA1 | Date | |
---|---|---|---|
|
afe3eec551 | ||
|
eb810178e5 | ||
|
30f8402629 | ||
|
50f32d0e66 | ||
|
6697207ac1 | ||
|
92a3df1571 |
132 changed files with 1477 additions and 5144 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! -->
|
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? -->
|
<!--- 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)? -->
|
<!-- 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:
|
stages:
|
||||||
- build
|
- build
|
||||||
- test
|
- test
|
||||||
|
- quality
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
include:
|
include:
|
||||||
|
@ -14,7 +15,7 @@ jobs:
|
||||||
- &build-template
|
- &build-template
|
||||||
stage: build
|
stage: build
|
||||||
name: linux
|
name: linux
|
||||||
env: NAME=linux DOCKER_IMAGE=lbry/build_lbrycrd_gcc EXT=
|
env: NAME=linux EXT=
|
||||||
os: linux
|
os: linux
|
||||||
dist: xenial
|
dist: xenial
|
||||||
language: minimal
|
language: minimal
|
||||||
|
@ -22,9 +23,8 @@ jobs:
|
||||||
- docker
|
- docker
|
||||||
install:
|
install:
|
||||||
- mkdir -p ${HOME}/ccache
|
- mkdir -p ${HOME}/ccache
|
||||||
- docker pull $DOCKER_IMAGE
|
- docker pull $DOCKER_BUILD_IMAGE
|
||||||
script:
|
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
|
- docker run -v "$(pwd):/lbrycrd" -v "${HOME}/ccache:/ccache" -w /lbrycrd -e CCACHE_DIR=/ccache ${DOCKER_IMAGE} packaging/build_${NAME}_64bit.sh
|
||||||
before_deploy:
|
before_deploy:
|
||||||
- mkdir -p dist
|
- mkdir -p dist
|
||||||
|
@ -48,11 +48,11 @@ jobs:
|
||||||
|
|
||||||
- <<: *build-template
|
- <<: *build-template
|
||||||
name: windows
|
name: windows
|
||||||
env: NAME=windows DOCKER_IMAGE=lbry/build_lbrycrd EXT=.exe
|
env: NAME=windows EXT=.exe
|
||||||
|
|
||||||
- <<: *build-template
|
- <<: *build-template
|
||||||
name: osx
|
name: osx
|
||||||
env: NAME=darwin DOCKER_IMAGE=lbry/build_lbrycrd EXT=
|
env: NAME=darwin EXT=
|
||||||
before_install:
|
before_install:
|
||||||
- mkdir -p ./depends/SDKs && pushd depends/SDKs && curl -C - ${MAC_OS_SDK} | tar --skip-old-files -xJ && popd
|
- 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
|
dist: xenial
|
||||||
language: minimal
|
language: minimal
|
||||||
git:
|
git:
|
||||||
clone: false
|
depth: 3
|
||||||
install:
|
install:
|
||||||
- mkdir -p testrun && cd testrun
|
- mkdir -p testrun && cd testrun
|
||||||
- curl http://build.lbry.io/lbrycrd/${TRAVIS_BRANCH}/lbrycrd-${NAME}-test.zip -o temp.zip
|
- curl http://build.lbry.io/lbrycrd/${TRAVIS_BRANCH}/lbrycrd-${NAME}-test.zip -o temp.zip
|
||||||
|
@ -78,11 +78,20 @@ jobs:
|
||||||
services:
|
services:
|
||||||
- docker
|
- docker
|
||||||
script:
|
script:
|
||||||
- docker pull lbry/wine
|
- docker pull $DOCKER_WINE_IMAGE
|
||||||
- docker run -v "$(pwd):/test" -e "WINEDEBUG=-all" -e "TRIEHASH_FUZZER_BLOCKS=1000" -it lbry/wine wine "/test/test_lbrycrd.exe"
|
- docker run -v "$(pwd):/test" -e "WINEDEBUG=-all" -e "TRIEHASH_FUZZER_BLOCKS=1000" -it $DOCKER_WINE_IMAGE wine "/test/test_lbrycrd.exe"
|
||||||
|
|
||||||
- <<: *test-template
|
- <<: *test-template
|
||||||
os: osx
|
os: osx
|
||||||
osx_image: xcode8.3
|
osx_image: xcode8.3
|
||||||
env: NAME=darwin
|
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
|
||||||
|
|
99
README.md
99
README.md
|
@ -1,32 +1,11 @@
|
||||||
# LBRYcrd - The LBRY blockchain
|
# LBRYcrd - The LBRY blockchain
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/lbryio/lbrycrd.svg?branch=master)](https://travis-ci.org/lbryio/lbrycrd)
|
[![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.
|
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)
|
|
||||||
|
|
||||||
## Installation
|
## 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.
|
||||||
|
@ -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
|
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:
|
the "--help" flag (e.g. `lbrycrdd --help`). Examples:
|
||||||
|
|
||||||
#### Examples
|
#### Examples:
|
||||||
|
|
||||||
Run `./lbrycrdd -server -daemon` to start lbrycrdd in the background.
|
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`
|
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:
|
Test locally:
|
||||||
|
```
|
||||||
```sh
|
|
||||||
./lbrycrdd -server -regtest -txindex # run this in its own window
|
./lbrycrdd -server -regtest -txindex # run this in its own window
|
||||||
./lbrycrd-cli -regtest generate 120 # mine 20 spendable coins
|
./lbrycrd-cli -regtest generate 120 # mine 20 spendable coins
|
||||||
./lbrycrd-cli -regtest claimname my_name deadbeef 1 # hold a name claim with 1 coin
|
./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
|
./lbrycrd-cli -regtest stop # kill lbrycrdd
|
||||||
rm -fr ~/.lbrycrd/regtest/ # destroy regtest data
|
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
|
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
|
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):
|
Lbrycrdd will use the below default data directories (changeable with -datadir):
|
||||||
|
|
||||||
```sh
|
```
|
||||||
Windows: %APPDATA%\lbrycrd
|
Windows: %APPDATA%\lbrycrd
|
||||||
Mac: ~/Library/Application Support/lbrycrd
|
Mac: ~/Library/Application Support/lbrycrd
|
||||||
Unix: ~/.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.
|
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.
|
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
|
rpcuser=lbry
|
||||||
rpcpassword=xyz123456790
|
rpcpassword=xyz123456790
|
||||||
daemon=1
|
daemon=1
|
||||||
|
@ -85,19 +61,15 @@ txindex=1
|
||||||
```
|
```
|
||||||
|
|
||||||
## Running from Source
|
## 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. I this sample we map a local lbrycrd folder and a local ccache folder inside the image:
|
||||||
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
|
|
||||||
git clone https://github.com/lbryio/lbrycrd.git
|
git clone https://github.com/lbryio/lbrycrd.git
|
||||||
cd lbrycrd
|
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
|
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:
|
Some examples of compiling directly:
|
||||||
|
#### Ubuntu with pulled static dependencies:
|
||||||
#### Ubuntu with pulled static dependencies
|
```
|
||||||
|
|
||||||
```sh
|
|
||||||
sudo apt install build-essential git libtool autotools-dev automake pkg-config bsdmainutils curl ca-certificates
|
sudo apt install build-essential git libtool autotools-dev automake pkg-config bsdmainutils curl ca-certificates
|
||||||
git clone https://github.com/lbryio/lbrycrd.git
|
git clone https://github.com/lbryio/lbrycrd.git
|
||||||
cd lbrycrd
|
cd lbrycrd
|
||||||
|
@ -105,14 +77,10 @@ cd lbrycrd
|
||||||
./src/test/test_lbrycrd
|
./src/test/test_lbrycrd
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Other Linux distros would be similar. The build shell script is fairly trivial; take a peek at its contents.
|
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.
|
Note: using untested dependencies may lead to conflicting results.
|
||||||
|
```
|
||||||
```sh
|
|
||||||
sudo add-apt-repository ppa:bitcoin/bitcoin
|
sudo add-apt-repository ppa:bitcoin/bitcoin
|
||||||
sudo apt-get update
|
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 \
|
||||||
|
@ -129,10 +97,8 @@ make -j$(nproc)
|
||||||
./src/lbrycrdd -server ...
|
./src/lbrycrdd -server ...
|
||||||
|
|
||||||
```
|
```
|
||||||
|
#### MacOS (cross-compiled):
|
||||||
#### MacOS (cross-compiled)
|
```
|
||||||
|
|
||||||
```sh
|
|
||||||
sudo apt-get install clang llvm git libtool autotools-dev automake pkg-config bsdmainutils curl ca-certificates \
|
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
|
libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev
|
||||||
|
|
||||||
|
@ -144,12 +110,9 @@ tar ... extract SDK to depends/SDKs/MacOSX10.11.sdk
|
||||||
./packaging/build_darwin_64bit.sh
|
./packaging/build_darwin_64bit.sh
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Look in packaging/build_darwin_64bit.sh for further understanding.
|
Look in packaging/build_darwin_64bit.sh for further understanding.
|
||||||
|
#### MacOS with local shared dependencies:
|
||||||
#### MacOS with local shared dependencies
|
```
|
||||||
|
|
||||||
```sh
|
|
||||||
brew install boost berkeley-db@4 icu4c libevent
|
brew install boost berkeley-db@4 icu4c libevent
|
||||||
# fix conflict with gawk pulled first:
|
# fix conflict with gawk pulled first:
|
||||||
brew reinstall readline
|
brew reinstall readline
|
||||||
|
@ -164,12 +127,9 @@ CONFIG_SITE=$(pwd)/depends/x86_64-apple-darwin15.6.0/share/config.site ./configu
|
||||||
make -j$(sysctl -n hw.ncpu)
|
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:
|
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 \
|
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
|
g++-mingw-w64-x86-64 mingw-w64-x86-64-dev
|
||||||
|
|
||||||
|
@ -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.
|
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:
|
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
|
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
|
./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
|
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.
|
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
|
## 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
|
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
|
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
|
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
|
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`
|
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
|
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 .
|
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)
|
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
|
||||||
|
|
||||||
## 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).
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
@ -231,9 +184,11 @@ This project is MIT licensed. For the full license, see [LICENSE](LICENSE).
|
||||||
|
|
||||||
## Security
|
## Security
|
||||||
|
|
||||||
We take security seriously. Please contact [security@lbry.com](mailto:security@lbry.com) regarding any security issues.
|
We take security seriously. Please contact security@lbry.com regarding any security issues.
|
||||||
Our PGP key is [here](https://lbry.com/faq/pgp-key) if you need it.
|
Our PGP key is [here](https://keybase.io/lbry/key.asc) if you need it.
|
||||||
|
|
||||||
## Contact
|
## Contact
|
||||||
|
|
||||||
The primary contact for this project is [@BrannonKing](https://github.com/BrannonKing) (brannon@lbry.com)
|
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
|
set -e
|
||||||
srcdir="$(dirname $0)"
|
srcdir="$(dirname $0)"
|
||||||
cd "$srcdir"
|
cd "$srcdir"
|
||||||
if [ -z ${LIBTOOLIZE} ] && GLIBTOOLIZE="$(which glibtoolize 2>/dev/null)"; then
|
if [ -z ${LIBTOOLIZE} ] && GLIBTOOLIZE="`which glibtoolize 2>/dev/null`"; then
|
||||||
LIBTOOLIZE="${GLIBTOOLIZE}"
|
LIBTOOLIZE="${GLIBTOOLIZE}"
|
||||||
export LIBTOOLIZE
|
export LIBTOOLIZE
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -3,9 +3,9 @@ AC_PREREQ([2.60])
|
||||||
define(_CLIENT_VERSION_MAJOR, 0)
|
define(_CLIENT_VERSION_MAJOR, 0)
|
||||||
define(_CLIENT_VERSION_MINOR, 17)
|
define(_CLIENT_VERSION_MINOR, 17)
|
||||||
define(_CLIENT_VERSION_REVISION, 3)
|
define(_CLIENT_VERSION_REVISION, 3)
|
||||||
define(_CLIENT_VERSION_BUILD, 3)
|
define(_CLIENT_VERSION_BUILD, 0)
|
||||||
define(_CLIENT_VERSION_IS_RELEASE, true)
|
define(_CLIENT_VERSION_IS_RELEASE, true)
|
||||||
define(_COPYRIGHT_YEAR, 2021)
|
define(_COPYRIGHT_YEAR, 2019)
|
||||||
define(_COPYRIGHT_HOLDERS,[The %s developers])
|
define(_COPYRIGHT_HOLDERS,[The %s developers])
|
||||||
define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[LBRYcrd Core]])
|
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/])
|
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
|
fi
|
||||||
|
|
||||||
find ${TEMPDIR} -name "*.sign" | while read i; do
|
find ${TEMPDIR} -name "*.sign" | while read i; do
|
||||||
SIZE=$(stat -c %s "${i}")
|
SIZE=`stat -c %s "${i}"`
|
||||||
TARGET_FILE="$(echo "${i}" | sed 's/\.sign$//')"
|
TARGET_FILE="`echo "${i}" | sed 's/\.sign$//'`"
|
||||||
|
|
||||||
echo "Allocating space for the signature of size ${SIZE} in ${TARGET_FILE}"
|
echo "Allocating space for the signature of size ${SIZE} in ${TARGET_FILE}"
|
||||||
${CODESIGN_ALLOCATE} -i "${TARGET_FILE}" -a ${ARCH} ${SIZE} -o "${i}.tmp"
|
${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
|
if [ -z ${QUIET} ]; then
|
||||||
echo "Attaching signature at offset ${OFFSET}"
|
echo "Attaching signature at offset ${OFFSET}"
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -27,19 +27,19 @@ ${CODESIGN} -f --file-list ${TEMPLIST} "$@" "${BUNDLE}"
|
||||||
|
|
||||||
grep -v CodeResources < "${TEMPLIST}" | while read i; do
|
grep -v CodeResources < "${TEMPLIST}" | while read i; do
|
||||||
TARGETFILE="${BUNDLE}/`echo "${i}" | sed "s|.*${BUNDLE}/||"`"
|
TARGETFILE="${BUNDLE}/`echo "${i}" | sed "s|.*${BUNDLE}/||"`"
|
||||||
SIZE=$(pagestuff "$i" -p | tail -2 | grep size | 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')
|
OFFSET=`pagestuff "$i" -p | tail -2 | grep offset | sed 's/[^0-9]*//g'`
|
||||||
SIGNFILE="${TEMPDIR}/${OUTROOT}/${TARGETFILE}.sign"
|
SIGNFILE="${TEMPDIR}/${OUTROOT}/${TARGETFILE}.sign"
|
||||||
DIRNAME="$(dirname "${SIGNFILE}")"
|
DIRNAME="`dirname "${SIGNFILE}"`"
|
||||||
mkdir -p "${DIRNAME}"
|
mkdir -p "${DIRNAME}"
|
||||||
echo "Adding detached signature for: ${TARGETFILE}. Size: ${SIZE}. Offset: ${OFFSET}"
|
echo "Adding detached signature for: ${TARGETFILE}. Size: ${SIZE}. Offset: ${OFFSET}"
|
||||||
dd if="$i" of="${SIGNFILE}" bs=1 skip=${OFFSET} count=${SIZE} 2>/dev/null
|
dd if="$i" of="${SIGNFILE}" bs=1 skip=${OFFSET} count=${SIZE} 2>/dev/null
|
||||||
done
|
done
|
||||||
|
|
||||||
grep CodeResources < "${TEMPLIST}" | while read i; do
|
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}"
|
RESOURCE="${TEMPDIR}/${OUTROOT}/${TARGETFILE}"
|
||||||
DIRNAME="$(dirname "${RESOURCE}")"
|
DIRNAME="`dirname "${RESOURCE}"`"
|
||||||
mkdir -p "${DIRNAME}"
|
mkdir -p "${DIRNAME}"
|
||||||
echo "Adding resource for: \"${TARGETFILE}\""
|
echo "Adding resource for: \"${TARGETFILE}\""
|
||||||
cp "${i}" "${RESOURCE}"
|
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);
|
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
|
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:
|
#### 3. Run the stratum server:
|
||||||
```
|
```
|
||||||
docker run --network host -d lbry/yiimp_stratum
|
docker run --network host -d lbry/yiimp_stratum
|
||||||
|
@ -47,7 +47,6 @@ docker run --network host -it lbry/yiimp_stratum bash
|
||||||
cat config/lbry.conf
|
cat config/lbry.conf
|
||||||
./stratum config/lbry
|
./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:
|
#### 4. Connect sgminer to it:
|
||||||
```
|
```
|
||||||
|
|
|
@ -23,7 +23,7 @@ TIMESERVER=http://timestamp.comodoca.com
|
||||||
CERTFILE="win-codesign.cert"
|
CERTFILE="win-codesign.cert"
|
||||||
|
|
||||||
mkdir -p "${OUTSUBDIR}"
|
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}"
|
echo Signing "${UNSIGNED}"
|
||||||
"${OSSLSIGNCODE}" sign -certs "${CERTFILE}" -t "${TIMESERVER}" -in "${SRCDIR}/${UNSIGNED}" -out "${WORKDIR}/${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}"
|
"${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|@build_os@|$(build_os)|' \
|
||||||
-e 's|@host_os@|$(host_os)|' \
|
-e 's|@host_os@|$(host_os)|' \
|
||||||
-e 's|@CFLAGS@|$(strip $(host_CFLAGS) $(host_$(release_type)_CFLAGS))|' \
|
-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|@CPPFLAGS@|$(strip $(host_CPPFLAGS) $(host_$(release_type)_CPPFLAGS))|' \
|
||||||
-e 's|@LDFLAGS@|$(strip $(host_LDFLAGS) $(host_$(release_type)_LDFLAGS))|' \
|
-e 's|@LDFLAGS@|$(strip $(host_LDFLAGS) $(host_$(release_type)_LDFLAGS))|' \
|
||||||
-e 's|@allow_host_packages@|$(ALLOW_HOST_PACKAGES)|' \
|
-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_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_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_release_CXXFLAGS=$(darwin_release_CFLAGS)
|
||||||
|
|
||||||
darwin_debug_CFLAGS=-Og -g
|
darwin_debug_CFLAGS=-Og
|
||||||
darwin_debug_CXXFLAGS=-O0 -g
|
darwin_debug_CXXFLAGS=$(darwin_debug_CFLAGS)
|
||||||
|
|
||||||
darwin_native_toolchain=native_cctools
|
darwin_native_toolchain=native_cctools
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
linux_CFLAGS=-pipe
|
linux_CFLAGS=-pipe
|
||||||
linux_CXXFLAGS=$(linux_CFLAGS) -std=c++11
|
linux_CXXFLAGS=$(linux_CFLAGS)
|
||||||
|
|
||||||
linux_release_CFLAGS=-O3 -g
|
linux_release_CFLAGS=-O2
|
||||||
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_CXXFLAGS=$(linux_release_CFLAGS)
|
linux_release_CXXFLAGS=$(linux_release_CFLAGS)
|
||||||
|
|
||||||
linux_debug_CFLAGS=-O1 -g
|
linux_debug_CFLAGS=-Og
|
||||||
linux_debug_CXXFLAGS=-O0 -g
|
linux_debug_CXXFLAGS=$(linux_debug_CFLAGS)
|
||||||
|
|
||||||
linux_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC
|
linux_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
mingw32_CFLAGS=-pipe
|
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_release_CXXFLAGS=$(mingw32_release_CFLAGS)
|
||||||
|
|
||||||
mingw32_debug_CFLAGS=-O1 -g
|
mingw32_debug_CFLAGS=-O1
|
||||||
mingw32_debug_CXXFLAGS=-O0 -g
|
mingw32_debug_CXXFLAGS=$(mingw32_debug_CFLAGS)
|
||||||
|
|
||||||
mingw32_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC
|
mingw32_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package=bdb
|
package=bdb
|
||||||
$(package)_version=4.8.30
|
$(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)_file_name=db-$($(package)_version).NC.tar.gz
|
||||||
$(package)_sha256_hash=12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef
|
$(package)_sha256_hash=12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef
|
||||||
$(package)_build_subdir=build_unix
|
$(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=--disable-shared --enable-cxx --disable-replication
|
||||||
$(package)_config_opts_mingw32=--enable-mingw
|
$(package)_config_opts_mingw32=--enable-mingw
|
||||||
$(package)_config_opts_linux=--with-pic
|
$(package)_config_opts_linux=--with-pic
|
||||||
$(package)_cppflags_mingw32=-DUNICODE -D_UNICODE
|
$(package)_cxxflags=-std=c++11
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_preprocess_cmds
|
define $(package)_preprocess_cmds
|
||||||
|
@ -29,4 +29,3 @@ endef
|
||||||
define $(package)_stage_cmds
|
define $(package)_stage_cmds
|
||||||
$(MAKE) DESTDIR=$($(package)_staging_dir) install_lib install_include
|
$(MAKE) DESTDIR=$($(package)_staging_dir) install_lib install_include
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package=boost
|
package=boost
|
||||||
$(package)_version=1_69_0
|
$(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)_file_name=$(package)_$($(package)_version).tar.bz2
|
||||||
$(package)_sha256_hash=8f32d4617390d1c2d16f26a27ab60d97807b35440d45891fa340fc2648b04406
|
$(package)_sha256_hash=8f32d4617390d1c2d16f26a27ab60d97807b35440d45891fa340fc2648b04406
|
||||||
$(package)_dependencies=icu
|
$(package)_dependencies=icu
|
||||||
|
|
|
@ -22,6 +22,7 @@ define $(package)_preprocess_cmds
|
||||||
PKG_CONFIG_SYSROOT_DIR=/ \
|
PKG_CONFIG_SYSROOT_DIR=/ \
|
||||||
PKG_CONFIG_LIBDIR=$(host_prefix)/lib/pkgconfig \
|
PKG_CONFIG_LIBDIR=$(host_prefix)/lib/pkgconfig \
|
||||||
PKG_CONFIG_PATH=$(host_prefix)/share/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 && \
|
mkdir -p build && cd build && \
|
||||||
../source/runConfigureICU Linux $($(package)_standard_opts) CXXFLAGS=-std=c++11 && \
|
../source/runConfigureICU Linux $($(package)_standard_opts) CXXFLAGS=-std=c++11 && \
|
||||||
$(MAKE) && cd ..
|
$(MAKE) && cd ..
|
||||||
|
@ -31,8 +32,6 @@ define $(package)_config_cmds
|
||||||
PKG_CONFIG_SYSROOT_DIR=/ \
|
PKG_CONFIG_SYSROOT_DIR=/ \
|
||||||
PKG_CONFIG_LIBDIR=$(host_prefix)/lib/pkgconfig \
|
PKG_CONFIG_LIBDIR=$(host_prefix)/lib/pkgconfig \
|
||||||
PKG_CONFIG_PATH=$(host_prefix)/share/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)
|
$($(package)_autoconf)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
|
|
@ -27,5 +27,4 @@ define $(package)_stage_cmds
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_postprocess_cmds
|
define $(package)_postprocess_cmds
|
||||||
rm lib/*.la
|
|
||||||
endef
|
endef
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package=miniupnpc
|
package=miniupnpc
|
||||||
$(package)_version=2.0.20180203
|
$(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)_file_name=$(package)-$($(package)_version).tar.gz
|
||||||
$(package)_sha256_hash=90dda8c7563ca6cd4a83e23b3c66dbbea89603a1675bfdb852897c2c9cc220b7
|
$(package)_sha256_hash=90dda8c7563ca6cd4a83e23b3c66dbbea89603a1675bfdb852897c2c9cc220b7
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ $(package)_file_name=$(package)-$($(package)_version).tar.gz
|
||||||
$(package)_sha256_hash=8f9faeaebad088e772f4ef5e38252d472be4d878c6b3a2718c10a4fcebe7a41c
|
$(package)_sha256_hash=8f9faeaebad088e772f4ef5e38252d472be4d878c6b3a2718c10a4fcebe7a41c
|
||||||
|
|
||||||
define $(package)_set_vars
|
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=--prefix=$(host_prefix) --openssldir=$(host_prefix)/etc/openssl
|
||||||
$(package)_config_opts+=no-camellia
|
$(package)_config_opts+=no-camellia
|
||||||
$(package)_config_opts+=no-capieng
|
$(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-whirlpool
|
||||||
$(package)_config_opts+=no-zlib
|
$(package)_config_opts+=no-zlib
|
||||||
$(package)_config_opts+=no-zlib-dynamic
|
$(package)_config_opts+=no-zlib-dynamic
|
||||||
|
$(package)_config_opts+=$($(package)_cflags) $($(package)_cppflags)
|
||||||
$(package)_config_opts_linux=-fPIC -Wa,--noexecstack
|
$(package)_config_opts_linux=-fPIC -Wa,--noexecstack
|
||||||
$(package)_config_opts_x86_64_linux=linux-x86_64
|
$(package)_config_opts_x86_64_linux=linux-x86_64
|
||||||
$(package)_config_opts_i686_linux=linux-generic32
|
$(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)_file_name=$(native_$(package)_file_name)
|
||||||
$(package)_sha256_hash=$(native_$(package)_sha256_hash)
|
$(package)_sha256_hash=$(native_$(package)_sha256_hash)
|
||||||
$(package)_dependencies=native_$(package)
|
$(package)_dependencies=native_$(package)
|
||||||
|
$(package)_cxxflags=-std=c++11
|
||||||
|
|
||||||
define $(package)_set_vars
|
define $(package)_set_vars
|
||||||
$(package)_config_opts=--disable-shared --with-protoc=$(build_prefix)/bin/protoc
|
$(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
|
$(package)_patches=0001-fix-build-with-older-mingw64.patch 0002-disable-pthread_set_name_np.patch
|
||||||
|
|
||||||
define $(package)_set_vars
|
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-docs --disable-shared --without-libsodium --disable-curve --disable-curve-keygen --disable-perf --disable-Werror
|
||||||
$(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_linux=--with-pic
|
$(package)_config_opts_linux=--with-pic
|
||||||
|
$(package)_cxxflags=-std=c++11
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_preprocess_cmds
|
define $(package)_preprocess_cmds
|
||||||
|
@ -32,5 +31,5 @@ endef
|
||||||
|
|
||||||
define $(package)_postprocess_cmds
|
define $(package)_postprocess_cmds
|
||||||
sed -i.old "s/ -lstdc++//" lib/pkgconfig/libzmq.pc && \
|
sed -i.old "s/ -lstdc++//" lib/pkgconfig/libzmq.pc && \
|
||||||
rm -rf bin share lib/*.la
|
rm -rf bin share
|
||||||
endef
|
endef
|
||||||
|
|
|
@ -30,13 +30,13 @@ if which ccache >/dev/null; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
pushd depends
|
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
|
popd
|
||||||
|
|
||||||
./autogen.sh
|
./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
|
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
|
${DEPS_DIR}/native/bin/x86_64-apple-darwin14-strip src/lbrycrdd src/lbrycrd-cli src/lbrycrd-tx
|
||||||
|
|
||||||
if which ccache >/dev/null; then
|
if which ccache >/dev/null; then
|
||||||
|
|
|
@ -20,13 +20,13 @@ export CXXFLAGS="${CXXFLAGS:--frecord-gcc-switches}"
|
||||||
echo "CXXFLAGS set to $CXXFLAGS"
|
echo "CXXFLAGS set to $CXXFLAGS"
|
||||||
|
|
||||||
cd depends
|
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 ..
|
cd ..
|
||||||
|
|
||||||
./autogen.sh
|
./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
|
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
|
strip src/lbrycrdd src/lbrycrd-cli src/lbrycrd-tx
|
||||||
|
|
||||||
if which ccache >/dev/null; then
|
if which ccache >/dev/null; then
|
||||||
|
|
|
@ -20,14 +20,17 @@ if which ccache >/dev/null; then
|
||||||
ccache -ps
|
ccache -ps
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
export CXXFLAGS="${CXXFLAGS:--frecord-gcc-switches}"
|
||||||
|
echo "CXXFLAGS set to $CXXFLAGS"
|
||||||
|
|
||||||
pushd depends
|
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
|
popd
|
||||||
|
|
||||||
./autogen.sh
|
./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
|
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
|
i686-w64-mingw32-strip src/lbrycrdd.exe src/lbrycrd-cli.exe src/lbrycrd-tx.exe
|
||||||
|
|
||||||
if which ccache >/dev/null; then
|
if which ccache >/dev/null; then
|
||||||
|
|
|
@ -19,14 +19,17 @@ if which ccache >/dev/null; then
|
||||||
ccache -ps
|
ccache -ps
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
export CXXFLAGS="${CXXFLAGS:--frecord-gcc-switches}"
|
||||||
|
echo "CXXFLAGS set to $CXXFLAGS"
|
||||||
|
|
||||||
pushd depends
|
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
|
popd
|
||||||
|
|
||||||
./autogen.sh
|
./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
|
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
|
x86_64-w64-mingw32-strip src/lbrycrdd.exe src/lbrycrd-cli.exe src/lbrycrd-tx.exe
|
||||||
|
|
||||||
if which ccache >/dev/null; then
|
if which ccache >/dev/null; then
|
||||||
|
|
|
@ -41,7 +41,6 @@ BITCOIN_TESTS =\
|
||||||
test/blockchain_tests.cpp \
|
test/blockchain_tests.cpp \
|
||||||
test/blockencodings_tests.cpp \
|
test/blockencodings_tests.cpp \
|
||||||
test/bloom_tests.cpp \
|
test/bloom_tests.cpp \
|
||||||
test/Checkpoints_tests.cpp \
|
|
||||||
test/bswap_tests.cpp \
|
test/bswap_tests.cpp \
|
||||||
test/checkqueue_tests.cpp \
|
test/checkqueue_tests.cpp \
|
||||||
test/coins_tests.cpp \
|
test/coins_tests.cpp \
|
||||||
|
|
|
@ -166,10 +166,10 @@ public:
|
||||||
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1548288000; // Jan 24, 2019
|
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1548288000; // Jan 24, 2019
|
||||||
|
|
||||||
// The best chain should have at least this much work.
|
// 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.
|
// 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.
|
* The message start string is designed to be unlikely to occur in normal data.
|
||||||
|
@ -195,11 +195,9 @@ public:
|
||||||
vSeeds.clear();
|
vSeeds.clear();
|
||||||
vFixedSeeds.clear();
|
vFixedSeeds.clear();
|
||||||
|
|
||||||
vSeeds.emplace_back("dnsseed1.lbry.io"); // LBRY Inc
|
vSeeds.emplace_back("dnsseed1.lbry.io"); // lbry.io
|
||||||
vSeeds.emplace_back("dnsseed2.lbry.io"); // LBRY Inc
|
vSeeds.emplace_back("dnsseed2.lbry.io"); // lbry.io
|
||||||
vSeeds.emplace_back("dnsseed3.lbry.io"); // LBRY Inc
|
vSeeds.emplace_back("dnsseed3.lbry.io"); // lbry.io
|
||||||
vSeeds.emplace_back("seed.lbry.grin.io"); // Grin
|
|
||||||
vSeeds.emplace_back("seed.allaboutlbc.com"); // Madiator2011
|
|
||||||
|
|
||||||
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1, 0x55);
|
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1, 0x55);
|
||||||
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1, 0x7a);
|
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1, 0x7a);
|
||||||
|
@ -207,6 +205,8 @@ public:
|
||||||
base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x88, 0xB2, 0x1E};
|
base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x88, 0xB2, 0x1E};
|
||||||
base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x88, 0xAD, 0xE4};
|
base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x88, 0xAD, 0xE4};
|
||||||
|
|
||||||
|
vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main));
|
||||||
|
|
||||||
bech32_hrp = "lbc";
|
bech32_hrp = "lbc";
|
||||||
|
|
||||||
vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main));
|
vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main));
|
||||||
|
|
|
@ -62,8 +62,7 @@ bool CClaimScriptUndoAddOp::supportClaim(CClaimTrieCache& trieCache, const std::
|
||||||
if (LogAcceptCategory(BCLog::CLAIMS)) {
|
if (LogAcceptCategory(BCLog::CLAIMS)) {
|
||||||
LogPrintf("--- [%lu]: OP_SUPPORT_CLAIM \"%s\" with claimId %s and tx prevout %s at index %d\n", nHeight, name,
|
LogPrintf("--- [%lu]: OP_SUPPORT_CLAIM \"%s\" with claimId %s and tx prevout %s at index %d\n", nHeight, name,
|
||||||
claimId.GetHex(), point.hash.ToString(), point.n);
|
claimId.GetHex(), point.hash.ToString(), point.n);
|
||||||
LogPrintf(
|
LogPrintf("%s: (txid: %s, nOut: %d) Removing support for %s, claimId: %s, from the claim trie due to block disconnect\n",
|
||||||
"%s: (txid: %s, nOut: %d) Removing support for %s, claimId: %s, from the claim trie due to block disconnect\n",
|
|
||||||
__func__, point.hash.ToString(), point.n, name, claimId.ToString());
|
__func__, point.hash.ToString(), point.n, name, claimId.ToString());
|
||||||
}
|
}
|
||||||
bool res = trieCache.undoAddSupport(name, point, nHeight);
|
bool res = trieCache.undoAddSupport(name, point, nHeight);
|
||||||
|
|
|
@ -2,16 +2,16 @@
|
||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#ifndef CLAIMSCRIPTOP_H
|
#ifndef BITCOIN_CLAIMSCRIPTOP_H
|
||||||
#define CLAIMSCRIPTOP_H
|
#define BITCOIN_CLAIMSCRIPTOP_H
|
||||||
|
|
||||||
#include "amount.h"
|
#include <amount.h>
|
||||||
#include "claimtrie.h"
|
#include <claimtrie.h>
|
||||||
#include "hash.h"
|
#include <hash.h>
|
||||||
#include "primitives/transaction.h"
|
#include <primitives/transaction.h>
|
||||||
#include "script/script.h"
|
#include <script/script.h>
|
||||||
#include "uint256.h"
|
#include <uint256.h>
|
||||||
#include "util.h"
|
#include <util.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -242,4 +242,4 @@ struct CUpdateCacheCallbacks
|
||||||
*/
|
*/
|
||||||
void UpdateCache(const CTransaction& tx, CClaimTrieCache& trieCache, const CCoinsViewCache& view, int nHeight, const CUpdateCacheCallbacks& callbacks = {});
|
void UpdateCache(const CTransaction& tx, CClaimTrieCache& trieCache, const CCoinsViewCache& view, int nHeight, const CUpdateCacheCallbacks& callbacks = {});
|
||||||
|
|
||||||
#endif // CLAIMSCRIPTOP_H
|
#endif // BITCOIN_CLAIMSCRIPTOP_H
|
||||||
|
|
|
@ -208,15 +208,15 @@ COptional<const std::vector<queueEntryType<T>>> CClaimTrieCacheBase::getQueueCac
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
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 <>
|
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>
|
template <typename T>
|
||||||
|
@ -246,15 +246,15 @@ COptional<const queueNameRowType> CClaimTrieCacheBase::getQueueCacheNameRow(cons
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
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 <>
|
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>
|
template <typename T>
|
||||||
|
@ -266,8 +266,13 @@ expirationQueueRowType* CClaimTrieCacheBase::getExpirationQueueCacheRow(int, boo
|
||||||
|
|
||||||
bool CClaimTrieCacheBase::haveClaim(const std::string& name, const COutPoint& outPoint) const
|
bool CClaimTrieCacheBase::haveClaim(const std::string& name, const COutPoint& outPoint) const
|
||||||
{
|
{
|
||||||
auto it = find(name);
|
auto it = nodesToAddOrUpdate.find(name);
|
||||||
return it && it->haveClaim(outPoint);
|
if (it && it->haveClaim(outPoint))
|
||||||
|
return true;
|
||||||
|
if (it || 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
|
bool CClaimTrieCacheBase::haveSupport(const std::string& name, const COutPoint& outPoint) const
|
||||||
|
@ -320,39 +325,70 @@ bool CClaimTrieCacheBase::haveSupportInQueue(const std::string& name, const COut
|
||||||
return haveInQueue<CSupportValue>(name, outPoint, nValidAtHeight);
|
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);
|
||||||
|
|
||||||
|
data.hash = current.hash;
|
||||||
|
data.flags |= current.children.empty() ? 0 : CClaimTrieDataFlags::POTENTIAL_CHILDREN;
|
||||||
|
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 CClaimTrie::getTotalNamesInTrie() const
|
||||||
{
|
{
|
||||||
std::size_t count = 0;
|
std::size_t count = 0;
|
||||||
for (auto it = begin(); it != end(); ++it)
|
CClaimTrieDataNode node;
|
||||||
if (!it->empty()) ++count;
|
if (find({}, node))
|
||||||
|
recurseNodes({}, node, [&count](const std::string &name, const CClaimTrieData &data, const std::vector<std::string>& children) {
|
||||||
|
count += !data.empty();
|
||||||
|
});
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t CClaimTrie::getTotalClaimsInTrie() const
|
std::size_t CClaimTrie::getTotalClaimsInTrie() const
|
||||||
{
|
{
|
||||||
std::size_t count = 0;
|
std::size_t count = 0;
|
||||||
for (auto it = begin(); it != end(); ++it)
|
CClaimTrieDataNode node;
|
||||||
count += it->claims.size();
|
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;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
CAmount CClaimTrie::getTotalValueOfClaimsInTrie(bool fControllingOnly) const
|
CAmount CClaimTrie::getTotalValueOfClaimsInTrie(bool fControllingOnly) const
|
||||||
{
|
{
|
||||||
CAmount value_in_subtrie = 0;
|
CAmount value_in_subtrie = 0;
|
||||||
for (auto it = begin(); it != end(); ++it) {
|
CClaimTrieDataNode node;
|
||||||
for (auto& claim : it->claims) {
|
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;
|
value_in_subtrie += claim.nAmount;
|
||||||
if (fControllingOnly)
|
if (fControllingOnly)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
return value_in_subtrie;
|
return value_in_subtrie;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrieCacheBase::getInfoForName(const std::string& name, CClaimValue& claim) const
|
bool CClaimTrieCacheBase::getInfoForName(const std::string& name, CClaimValue& claim) const
|
||||||
{
|
{
|
||||||
auto it = find(name);
|
auto it = nodesToAddOrUpdate.find(name);
|
||||||
return it && it->getBestClaim(claim);
|
if (it && it->getBestClaim(claim))
|
||||||
|
return true;
|
||||||
|
if (it || nodesToDelete.count(name))
|
||||||
|
return false;
|
||||||
|
CClaimTrieData claims;
|
||||||
|
return base->find(name, claims) && claims.getBestClaim(claim);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -374,9 +410,15 @@ CClaimSupportToName CClaimTrieCacheBase::getClaimsForName(const std::string& nam
|
||||||
auto supports = getSupportsForName(name);
|
auto supports = getSupportsForName(name);
|
||||||
insertRowsFromQueue(supports, name);
|
insertRowsFromQueue(supports, name);
|
||||||
|
|
||||||
if (auto it = find(name)) {
|
if (auto it = nodesToAddOrUpdate.find(name)) {
|
||||||
claims = it->claims;
|
claims = it->claims;
|
||||||
nLastTakeoverHeight = it->nHeightOfLastTakeover;
|
nLastTakeoverHeight = it->nHeightOfLastTakeover;
|
||||||
|
} else if (!nodesToDelete.count(name)) {
|
||||||
|
CClaimTrieData data;
|
||||||
|
if (base->find(name, data)) {
|
||||||
|
claims = data.claims;
|
||||||
|
nLastTakeoverHeight = data.nHeightOfLastTakeover;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
insertRowsFromQueue(claims, name);
|
insertRowsFromQueue(claims, name);
|
||||||
|
|
||||||
|
@ -411,79 +453,94 @@ void completeHash(uint256& partialHash, const std::string& key, std::size_t to)
|
||||||
.Finalize(partialHash.begin());
|
.Finalize(partialHash.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
bool CClaimTrie::checkConsistency(const uint256& rootHash) const
|
||||||
using iCbType = std::function<void(T&)>;
|
|
||||||
|
|
||||||
template <typename TIterator>
|
|
||||||
uint256 recursiveMerkleHash(TIterator& it, const iCbType<TIterator>& process)
|
|
||||||
{
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
std::vector<uint8_t> vchToHash;
|
std::vector<uint8_t> vchToHash;
|
||||||
const auto pos = it.key().size();
|
const auto pos = name.size();
|
||||||
for (auto& child : it.children()) {
|
for (auto &child : children) {
|
||||||
process(child);
|
auto key = name + child;
|
||||||
auto& key = child.key();
|
CClaimTrieDataNode node;
|
||||||
auto hash = child->hash;
|
success &= find(key, node);
|
||||||
|
auto hash = node.hash;
|
||||||
completeHash(hash, key, pos);
|
completeHash(hash, key, pos);
|
||||||
vchToHash.push_back(key[pos]);
|
vchToHash.push_back(key[pos]);
|
||||||
vchToHash.insert(vchToHash.end(), hash.begin(), hash.end());
|
vchToHash.insert(vchToHash.end(), hash.begin(), hash.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
CClaimValue claim;
|
CClaimValue claim;
|
||||||
if (it->getBestClaim(claim)) {
|
if (data.getBestClaim(claim)) {
|
||||||
uint256 valueHash = getValueHash(claim.outPoint, it->nHeightOfLastTakeover);
|
uint256 valueHash = getValueHash(claim.outPoint, data.nHeightOfLastTakeover);
|
||||||
vchToHash.insert(vchToHash.end(), valueHash.begin(), valueHash.end());
|
vchToHash.insert(vchToHash.end(), valueHash.begin(), valueHash.end());
|
||||||
} else if (!it.hasChildren()) {
|
} else {
|
||||||
return {};
|
success &= !children.empty(); // we disallow leaf nodes without claims
|
||||||
|
}
|
||||||
|
success &= data.hash == Hash(vchToHash.begin(), vchToHash.end());
|
||||||
|
});
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Hash(vchToHash.begin(), vchToHash.end());
|
std::vector<std::pair<std::string, CClaimTrieDataNode>> CClaimTrie::nodes(const std::string &key) const {
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrieCacheBase::recursiveCheckConsistency(CClaimTrie::const_iterator& it, std::string& failed) const
|
return ret;
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
process(it);
|
|
||||||
} catch (const CRecursiveBreak&) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrieCacheBase::checkConsistency() const
|
bool CClaimTrie::contains(const std::string &key) const {
|
||||||
{
|
return db->Exists(std::make_pair(TRIE_NODE_CHILDREN, key));
|
||||||
if (base->empty())
|
}
|
||||||
return true;
|
|
||||||
|
|
||||||
auto it = base->cbegin();
|
bool CClaimTrie::empty() const {
|
||||||
std::string failed;
|
return !contains({});
|
||||||
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;
|
bool CClaimTrie::find(const std::string& key, CClaimTrieDataNode &node) const {
|
||||||
for (const auto &piece : nodesToDelete) joined += ", " + piece;
|
return db->Read(std::make_pair(TRIE_NODE_CHILDREN, key), node);
|
||||||
LogPrintf("Nodes to be deleted: %s\n", joined.substr(2));
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return consistent;
|
bool CClaimTrie::find(const std::string& key, CClaimTrieData &data) const {
|
||||||
|
return db->Read(std::make_pair(TRIE_NODE_CLAIMS, key), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename K, typename T>
|
template <typename K, typename T>
|
||||||
|
@ -522,22 +579,24 @@ bool CClaimTrieCacheBase::flush()
|
||||||
|
|
||||||
getMerkleHash();
|
getMerkleHash();
|
||||||
|
|
||||||
for (const auto& nodeName : nodesToDelete) {
|
for (auto it = nodesToAddOrUpdate.begin(); it != nodesToAddOrUpdate.end(); ++it) {
|
||||||
if (nodesToAddOrUpdate.contains(nodeName))
|
bool removed = forDeleteFromBase.erase(it.key());
|
||||||
continue;
|
if (it->flags & CClaimTrieDataFlags::HASH_DIRTY) {
|
||||||
auto nodes = base->nodes(nodeName);
|
CClaimTrieDataNode node;
|
||||||
base->erase(nodeName);
|
node.hash = it->hash;
|
||||||
for (auto& node : nodes)
|
for (auto &child: it.children()) // ordering here is important
|
||||||
if (!node)
|
node.children.push_back(child.key().substr(it.key().size()));
|
||||||
batch.Erase(std::make_pair(TRIE_NODE, node.key()));
|
|
||||||
|
batch.Write(std::make_pair(TRIE_NODE_CHILDREN, it.key()), node);
|
||||||
|
|
||||||
|
if (removed || (it->flags & CClaimTrieDataFlags::CLAIMS_DIRTY))
|
||||||
|
batch.Write(std::make_pair(TRIE_NODE_CLAIMS, it.key()), it.data());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto it = nodesToAddOrUpdate.begin(); it != nodesToAddOrUpdate.end(); ++it) {
|
for (auto& name: forDeleteFromBase) {
|
||||||
auto old = base->find(it.key());
|
batch.Erase(std::make_pair(TRIE_NODE_CHILDREN, name));
|
||||||
if (!old || old.data() != it.data()) {
|
batch.Erase(std::make_pair(TRIE_NODE_CLAIMS, name));
|
||||||
base->copy(it);
|
|
||||||
batch.Write(std::make_pair(TRIE_NODE, it.key()), it.data());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BatchWriteQueue(batch, SUPPORT, supportCache);
|
BatchWriteQueue(batch, SUPPORT, supportCache);
|
||||||
|
@ -561,70 +620,32 @@ bool CClaimTrieCacheBase::flush()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrieCacheBase::ReadFromDisk(const CBlockIndex* tip)
|
bool CClaimTrieCacheBase::validateTrieConsistency(const CBlockIndex* tip)
|
||||||
{
|
{
|
||||||
LogPrintf("Loading the claim trie from disk...\n");
|
if (!tip || tip->nHeight < 1)
|
||||||
|
return true;
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LogPrintf("Checking claim trie consistency... ");
|
LogPrintf("Checking claim trie consistency... ");
|
||||||
if (checkConsistency()) {
|
if (base->checkConsistency(tip->hashClaimTrie)) {
|
||||||
LogPrintf("consistent\n");
|
LogPrintf("consistent\n");
|
||||||
if (tip && tip->hashClaimTrie != getMerkleHash())
|
|
||||||
return error("%s(): hashes don't match when reading claimtrie from disk", __func__);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
LogPrintf("inconsistent!\n");
|
LogPrintf("inconsistent!\n");
|
||||||
return false;
|
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\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return validateTrieConsistency(tip);
|
||||||
|
}
|
||||||
|
|
||||||
CClaimTrieCacheBase::CClaimTrieCacheBase(CClaimTrie* base) : base(base)
|
CClaimTrieCacheBase::CClaimTrieCacheBase(CClaimTrie* base) : base(base)
|
||||||
{
|
{
|
||||||
assert(base);
|
assert(base);
|
||||||
|
@ -636,65 +657,92 @@ int CClaimTrieCacheBase::expirationTime() const
|
||||||
return Params().GetConsensus().nOriginalClaimExpirationTime;
|
return Params().GetConsensus().nOriginalClaimExpirationTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 CClaimTrieCacheBase::recursiveComputeMerkleHash(CClaimTrie::iterator& it)
|
uint256 CClaimTrieCacheBase::recursiveComputeMerkleHash(CClaimPrefixTrie::iterator& it)
|
||||||
{
|
{
|
||||||
using iterator = CClaimTrie::iterator;
|
if (!it->hash.IsNull())
|
||||||
iCbType<iterator> process = [&process](iterator& it) {
|
|
||||||
if (it->hash.IsNull())
|
|
||||||
it->hash = recursiveMerkleHash(it, process);
|
|
||||||
assert(!it->hash.IsNull());
|
|
||||||
};
|
|
||||||
process(it);
|
|
||||||
return it->hash;
|
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()
|
uint256 CClaimTrieCacheBase::getMerkleHash()
|
||||||
{
|
{
|
||||||
auto it = nodesToAddOrUpdate.begin();
|
if (auto it = nodesToAddOrUpdate.begin())
|
||||||
if (!it && nodesToDelete.empty())
|
return recursiveComputeMerkleHash(it);
|
||||||
it = base->begin();
|
if (nodesToDelete.empty() && nodesAlreadyCached.empty()) {
|
||||||
return !it ? one : recursiveComputeMerkleHash(it);
|
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);
|
return nodesToAddOrUpdate.begin();
|
||||||
if (it || nodesToDelete.count(name))
|
}
|
||||||
return it;
|
|
||||||
return base->find(name);
|
CClaimPrefixTrie::const_iterator CClaimTrieCacheBase::end() const
|
||||||
|
{
|
||||||
|
return nodesToAddOrUpdate.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrieCacheBase::empty() const
|
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
|
// we need all parent nodes and their one level deep children
|
||||||
// to calculate merkle hash
|
// to calculate merkle hash
|
||||||
auto nodes = base->nodes(name);
|
auto nodes = base->nodes(name);
|
||||||
for (auto& node: nodes) {
|
for (auto& node: nodes) {
|
||||||
for (auto& child : node.children())
|
if (nodesAlreadyCached.insert(node.first).second) {
|
||||||
if (!nodesAlreadyCached.count(child.key()))
|
// do not insert nodes that are already present
|
||||||
nodesToAddOrUpdate.copy(child);
|
CClaimTrieData data;
|
||||||
insert(node);
|
base->find(node.first, data);
|
||||||
|
data.hash = node.second.hash;
|
||||||
|
data.flags = node.second.children.empty() ? 0 : CClaimTrieDataFlags::POTENTIAL_CHILDREN;
|
||||||
|
nodesToAddOrUpdate.insert(node.first, data);
|
||||||
|
}
|
||||||
|
for (auto& child : node.second.children) {
|
||||||
|
auto childKey = node.first + child;
|
||||||
|
if (nodesAlreadyCached.insert(childKey).second) {
|
||||||
|
CClaimTrieData childData;
|
||||||
|
if (!base->find(childKey, childData))
|
||||||
|
childData = {};
|
||||||
|
CClaimTrieDataNode childNode;
|
||||||
|
if (base->find(childKey, childNode)) {
|
||||||
|
childData.hash = childNode.hash;
|
||||||
|
childData.flags = childNode.children.empty() ? 0 : CClaimTrieDataFlags::POTENTIAL_CHILDREN;
|
||||||
|
}
|
||||||
|
nodesToAddOrUpdate.insert(childKey, childData);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = nodesToAddOrUpdate.find(name);
|
auto it = nodesToAddOrUpdate.find(name);
|
||||||
if (!it && create) {
|
if (!it && create) {
|
||||||
it = nodesToAddOrUpdate.insert(name, CClaimTrieData{});
|
it = nodesToAddOrUpdate.insert(name, CClaimTrieData{});
|
||||||
|
// if (it.hasChildren()) any children should be in the trie (not base alone)
|
||||||
|
// it->flags |= CClaimTrieDataFlags::POTENTIAL_CHILDREN;
|
||||||
confirmTakeoverWorkaroundNeeded(name);
|
confirmTakeoverWorkaroundNeeded(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -715,10 +763,11 @@ bool CClaimTrieCacheBase::getLastTakeoverForName(const std::string& name, uint16
|
||||||
std::tie(claimId, takeoverHeight) = cit->second;
|
std::tie(claimId, takeoverHeight) = cit->second;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (auto it = base->find(name)) {
|
CClaimTrieData data;
|
||||||
takeoverHeight = it->nHeightOfLastTakeover;
|
if (base->find(name, data)) {
|
||||||
|
takeoverHeight = data.nHeightOfLastTakeover;
|
||||||
CClaimValue claim;
|
CClaimValue claim;
|
||||||
if (it->getBestClaim(claim)) {
|
if (data.getBestClaim(claim)) {
|
||||||
claimId = claim.claimId;
|
claimId = claim.claimId;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -728,8 +777,12 @@ bool CClaimTrieCacheBase::getLastTakeoverForName(const std::string& name, uint16
|
||||||
|
|
||||||
void CClaimTrieCacheBase::markAsDirty(const std::string& name, bool fCheckTakeover)
|
void CClaimTrieCacheBase::markAsDirty(const std::string& name, bool fCheckTakeover)
|
||||||
{
|
{
|
||||||
for (auto& node : nodesToAddOrUpdate.nodes(name))
|
for (auto& node : nodesToAddOrUpdate.nodes(name)) {
|
||||||
|
node->flags |= CClaimTrieDataFlags::HASH_DIRTY;
|
||||||
node->hash.SetNull();
|
node->hash.SetNull();
|
||||||
|
if (node.key() == name)
|
||||||
|
node->flags |= CClaimTrieDataFlags::CLAIMS_DIRTY;
|
||||||
|
}
|
||||||
|
|
||||||
if (fCheckTakeover)
|
if (fCheckTakeover)
|
||||||
namesToCheckForTakeover.insert(name);
|
namesToCheckForTakeover.insert(name);
|
||||||
|
@ -763,6 +816,9 @@ bool CClaimTrieCacheBase::removeClaimFromTrie(const std::string& name, const COu
|
||||||
for (auto& child: it.children())
|
for (auto& child: it.children())
|
||||||
cacheData(child.key(), false);
|
cacheData(child.key(), false);
|
||||||
|
|
||||||
|
for (auto& node : nodesToAddOrUpdate.nodes(name))
|
||||||
|
forDeleteFromBase.emplace(node.key());
|
||||||
|
|
||||||
nodesToAddOrUpdate.erase(name);
|
nodesToAddOrUpdate.erase(name);
|
||||||
nodesToDelete.insert(name);
|
nodesToDelete.insert(name);
|
||||||
|
|
||||||
|
@ -935,14 +991,10 @@ bool CClaimTrieCacheBase::remove(T& value, const std::string& name, const COutPo
|
||||||
nValidAtHeight = nHeight + getDelayForName(name);
|
nValidAtHeight = nHeight + getDelayForName(name);
|
||||||
std::string adjusted = adjustNameForValidHeight(name, nValidAtHeight);
|
std::string adjusted = adjustNameForValidHeight(name, nValidAtHeight);
|
||||||
|
|
||||||
auto rfq = removeFromQueue(adjusted, outPoint, value);
|
if (removeFromQueue(adjusted, outPoint, value) || removeFromCache(name, outPoint, value, fCheckTakeover)) {
|
||||||
if (rfq || removeFromCache(name, outPoint, value, fCheckTakeover)) {
|
|
||||||
int expirationHeight = value.nHeight + expirationTime();
|
int expirationHeight = value.nHeight + expirationTime();
|
||||||
if (auto itQueueRow = getExpirationQueueCacheRow<T>(expirationHeight, false)) {
|
if (auto itQueueRow = getExpirationQueueCacheRow<T>(expirationHeight, false))
|
||||||
eraseOutPoint(*itQueueRow, CNameOutPointType{adjusted, outPoint});
|
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;
|
nValidAtHeight = value.nValidAtHeight;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1003,11 +1055,13 @@ bool CClaimTrieCacheBase::removeSupportFromMap(const std::string& name, const CO
|
||||||
return false;
|
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) {
|
if (diffFromBase) {
|
||||||
auto hit = base->find(it.key());
|
CClaimTrieDataNode node;
|
||||||
if (hit && hit->hash == it->hash)
|
if (base->find(it.key(), node) && node.hash == it->hash)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1101,13 +1155,10 @@ void CClaimTrieCacheBase::undoIncrement(insertUndoType& insertUndo, std::vector<
|
||||||
if (auto itExpirationRow = getExpirationQueueCacheRow<T>(nNextHeight, false)) {
|
if (auto itExpirationRow = getExpirationQueueCacheRow<T>(nNextHeight, false)) {
|
||||||
for (const auto& itEntry : *itExpirationRow) {
|
for (const auto& itEntry : *itExpirationRow) {
|
||||||
T value;
|
T value;
|
||||||
if (removeFromCache(itEntry.name, itEntry.outPoint, value, true)) {
|
assert(removeFromCache(itEntry.name, itEntry.outPoint, value, true));
|
||||||
expireUndo.emplace_back(itEntry.name, value);
|
expireUndo.emplace_back(itEntry.name, value);
|
||||||
addTo(deleted, 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);
|
|
||||||
}
|
|
||||||
itExpirationRow->clear();
|
itExpirationRow->clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1324,8 +1375,12 @@ int CClaimTrieCacheBase::getNumBlocksOfContinuousOwnership(const std::string& na
|
||||||
that->removalWorkaround.erase(hit);
|
that->removalWorkaround.erase(hit);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
auto it = nodesToAddOrUpdate.find(name);
|
if (auto it = nodesToAddOrUpdate.find(name))
|
||||||
return (it || (it = base->find(name))) && !it->empty() ? nNextHeight - it->nHeightOfLastTakeover : 0;
|
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
|
int CClaimTrieCacheBase::getDelayForName(const std::string& name) const
|
||||||
|
@ -1352,22 +1407,23 @@ std::string CClaimTrieCacheBase::adjustNameForValidHeight(const std::string& nam
|
||||||
|
|
||||||
bool CClaimTrieCacheBase::clear()
|
bool CClaimTrieCacheBase::clear()
|
||||||
{
|
{
|
||||||
|
forDeleteFromBase.clear();
|
||||||
|
nodesToAddOrUpdate.clear();
|
||||||
|
claimsToAddToByIdIndex.clear();
|
||||||
supportCache.clear();
|
supportCache.clear();
|
||||||
nodesToDelete.clear();
|
nodesToDelete.clear();
|
||||||
|
claimsToDeleteFromByIdIndex.clear();
|
||||||
takeoverCache.clear();
|
takeoverCache.clear();
|
||||||
claimQueueCache.clear();
|
claimQueueCache.clear();
|
||||||
supportQueueCache.clear();
|
supportQueueCache.clear();
|
||||||
removalWorkaround.clear();
|
|
||||||
nodesToAddOrUpdate.clear();
|
|
||||||
nodesAlreadyCached.clear();
|
nodesAlreadyCached.clear();
|
||||||
takeoverWorkaround.clear();
|
takeoverWorkaround.clear();
|
||||||
|
removalWorkaround.clear();
|
||||||
claimQueueNameCache.clear();
|
claimQueueNameCache.clear();
|
||||||
expirationQueueCache.clear();
|
expirationQueueCache.clear();
|
||||||
supportQueueNameCache.clear();
|
supportQueueNameCache.clear();
|
||||||
claimsToAddToByIdIndex.clear();
|
|
||||||
namesToCheckForTakeover.clear();
|
namesToCheckForTakeover.clear();
|
||||||
supportExpirationQueueCache.clear();
|
supportExpirationQueueCache.clear();
|
||||||
claimsToDeleteFromByIdIndex.clear();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1377,7 +1433,7 @@ bool CClaimTrieCacheBase::getProofForName(const std::string& name, CClaimTriePro
|
||||||
cacheData(name, false);
|
cacheData(name, false);
|
||||||
getMerkleHash();
|
getMerkleHash();
|
||||||
proof = CClaimTrieProof();
|
proof = CClaimTrieProof();
|
||||||
for (auto& it : static_cast<const CClaimTrie&>(nodesToAddOrUpdate).nodes(name)) {
|
for (auto& it : static_cast<const CClaimPrefixTrie&>(nodesToAddOrUpdate).nodes(name)) {
|
||||||
CClaimValue claim;
|
CClaimValue claim;
|
||||||
const auto& key = it.key();
|
const auto& key = it.key();
|
||||||
bool fNodeHasValue = it->getBestClaim(claim);
|
bool fNodeHasValue = it->getBestClaim(claim);
|
||||||
|
@ -1393,7 +1449,7 @@ bool CClaimTrieCacheBase::getProofForName(const std::string& name, CClaimTriePro
|
||||||
for (auto i = pos; i + 1 < childKey.size(); ++i) {
|
for (auto i = pos; i + 1 < childKey.size(); ++i) {
|
||||||
children.emplace_back(childKey[i], uint256{});
|
children.emplace_back(childKey[i], uint256{});
|
||||||
proof.nodes.emplace_back(children, fNodeHasValue, valueHash);
|
proof.nodes.emplace_back(children, fNodeHasValue, valueHash);
|
||||||
children.clear();
|
children.clear(); // move promises to leave it in a valid state only
|
||||||
valueHash.SetNull();
|
valueHash.SetNull();
|
||||||
fNodeHasValue = false;
|
fNodeHasValue = false;
|
||||||
}
|
}
|
||||||
|
@ -1417,22 +1473,33 @@ bool CClaimTrieCacheBase::getProofForName(const std::string& name, CClaimTriePro
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClaimTrieCacheBase::iterate(std::function<void(const std::string&, const CClaimTrieData&)> callback) const
|
void CClaimTrieCacheBase::recurseNodes(const std::string &name,
|
||||||
{
|
std::function<void(const std::string &, const CClaimTrieData &)> function) const {
|
||||||
if (nodesToAddOrUpdate.empty()) {
|
|
||||||
for (auto it = base->cbegin(); it != base->cend(); ++it)
|
std::function<CClaimTrie::recurseNodesCB> baseFunction = [this, &function]
|
||||||
if (!nodesToDelete.count(it.key()))
|
(const std::string& name, const CClaimTrieData& data, const std::vector<std::string>&) {
|
||||||
callback(it.key(), it.data());
|
if (nodesToDelete.find(name) == nodesToDelete.end())
|
||||||
return;
|
function(name, data);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (empty()) {
|
||||||
|
CClaimTrieDataNode node;
|
||||||
|
if (base->find(name, node))
|
||||||
|
base->recurseNodes(name, node, baseFunction);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (auto it = begin(); it != end(); ++it) {
|
||||||
|
function(it.key(), it.data());
|
||||||
|
if ((it->flags & CClaimTrieDataFlags::POTENTIAL_CHILDREN) && !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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,9 @@
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
// leveldb keys
|
// leveldb keys
|
||||||
#define TRIE_NODE 'n'
|
#define TRIE_NODE 'n' // deprecated
|
||||||
#define TRIE_NODE_CHILDREN 'b'
|
#define TRIE_NODE_CHILDREN 'b'
|
||||||
|
#define TRIE_NODE_CLAIMS 'c'
|
||||||
#define CLAIM_BY_ID 'i'
|
#define CLAIM_BY_ID 'i'
|
||||||
#define CLAIM_QUEUE_ROW 'r'
|
#define CLAIM_QUEUE_ROW 'r'
|
||||||
#define CLAIM_QUEUE_NAME_ROW 'm'
|
#define CLAIM_QUEUE_NAME_ROW 'm'
|
||||||
|
@ -62,6 +63,7 @@ struct CClaimValue
|
||||||
READWRITE(nAmount);
|
READWRITE(nAmount);
|
||||||
READWRITE(nHeight);
|
READWRITE(nHeight);
|
||||||
READWRITE(nValidAtHeight);
|
READWRITE(nValidAtHeight);
|
||||||
|
READWRITE(nEffectiveAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator<(const CClaimValue& other) const
|
bool operator<(const CClaimValue& other) const
|
||||||
|
@ -134,12 +136,21 @@ struct CSupportValue
|
||||||
typedef std::vector<CClaimValue> claimEntryType;
|
typedef std::vector<CClaimValue> claimEntryType;
|
||||||
typedef std::vector<CSupportValue> supportEntryType;
|
typedef std::vector<CSupportValue> supportEntryType;
|
||||||
|
|
||||||
|
enum CClaimTrieDataFlags: uint32_t {
|
||||||
|
HASH_DIRTY = 1U,
|
||||||
|
CLAIMS_DIRTY = 2U,
|
||||||
|
POTENTIAL_CHILDREN = 4U, // existing on disk
|
||||||
|
};
|
||||||
|
|
||||||
struct CClaimTrieData
|
struct CClaimTrieData
|
||||||
{
|
{
|
||||||
uint256 hash;
|
|
||||||
claimEntryType claims;
|
claimEntryType claims;
|
||||||
int nHeightOfLastTakeover = 0;
|
int nHeightOfLastTakeover = 0;
|
||||||
|
|
||||||
|
// non-serialized data:
|
||||||
|
uint32_t flags = 0;
|
||||||
|
uint256 hash;
|
||||||
|
|
||||||
CClaimTrieData() = default;
|
CClaimTrieData() = default;
|
||||||
CClaimTrieData(CClaimTrieData&&) = default;
|
CClaimTrieData(CClaimTrieData&&) = default;
|
||||||
CClaimTrieData(const CClaimTrieData&) = default;
|
CClaimTrieData(const CClaimTrieData&) = default;
|
||||||
|
@ -157,25 +168,13 @@ struct CClaimTrieData
|
||||||
template <typename Stream, typename Operation>
|
template <typename Stream, typename Operation>
|
||||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
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(claims);
|
||||||
READWRITE(nHeightOfLastTakeover);
|
READWRITE(nHeightOfLastTakeover);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const CClaimTrieData& other) const
|
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
|
bool operator!=(const CClaimTrieData& other) const
|
||||||
|
@ -189,6 +188,28 @@ 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
|
struct COutPointHeightType
|
||||||
{
|
{
|
||||||
COutPoint outPoint;
|
COutPoint outPoint;
|
||||||
|
@ -343,7 +364,7 @@ struct CClaimSupportToName
|
||||||
const std::vector<CSupportValue> unmatchedSupports;
|
const std::vector<CSupportValue> unmatchedSupports;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CClaimTrie : public CPrefixTrie<std::string, CClaimTrieData>
|
class CClaimTrie
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CClaimTrie() = default;
|
CClaimTrie() = default;
|
||||||
|
@ -366,12 +387,23 @@ public:
|
||||||
|
|
||||||
std::size_t getTotalNamesInTrie() const;
|
std::size_t getTotalNamesInTrie() const;
|
||||||
std::size_t getTotalClaimsInTrie() const;
|
std::size_t getTotalClaimsInTrie() const;
|
||||||
|
virtual bool checkConsistency(const uint256& rootHash) const;
|
||||||
CAmount getTotalValueOfClaimsInTrie(bool fControllingOnly) 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:
|
protected:
|
||||||
int nNextHeight = 0;
|
int nNextHeight = 0;
|
||||||
int nProportionalDelayFactor = 0;
|
int nProportionalDelayFactor = 0;
|
||||||
std::unique_ptr<CDBWrapper> db;
|
std::unique_ptr<CDBWrapper> db;
|
||||||
|
|
||||||
|
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
|
struct CClaimTrieProofNode
|
||||||
|
@ -476,6 +508,8 @@ typedef std::map<int, expirationQueueRowType> expirationQueueType;
|
||||||
typedef std::set<CClaimValue> claimIndexClaimListType;
|
typedef std::set<CClaimValue> claimIndexClaimListType;
|
||||||
typedef std::vector<CClaimIndexElement> claimIndexElementListType;
|
typedef std::vector<CClaimIndexElement> claimIndexElementListType;
|
||||||
|
|
||||||
|
typedef CPrefixTrie<std::string, CClaimTrieData> CClaimPrefixTrie;
|
||||||
|
|
||||||
class CClaimTrieCacheBase
|
class CClaimTrieCacheBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -486,7 +520,6 @@ public:
|
||||||
|
|
||||||
bool flush();
|
bool flush();
|
||||||
bool empty() const;
|
bool empty() const;
|
||||||
bool checkConsistency() const;
|
|
||||||
bool ReadFromDisk(const CBlockIndex* tip);
|
bool ReadFromDisk(const CBlockIndex* tip);
|
||||||
|
|
||||||
bool haveClaim(const std::string& name, const COutPoint& outPoint) const;
|
bool haveClaim(const std::string& name, const COutPoint& outPoint) const;
|
||||||
|
@ -527,20 +560,21 @@ public:
|
||||||
|
|
||||||
virtual CClaimSupportToName getClaimsForName(const std::string& name) const;
|
virtual CClaimSupportToName getClaimsForName(const std::string& name) const;
|
||||||
|
|
||||||
CClaimTrie::const_iterator find(const std::string& name) const;
|
CClaimPrefixTrie::const_iterator begin() const;
|
||||||
void iterate(std::function<void(const std::string&, const CClaimTrieData&)> callback) 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;
|
virtual std::string adjustNameForValidHeight(const std::string& name, int validHeight) const;
|
||||||
|
|
||||||
|
void recurseNodes(const std::string& name, std::function<void(const std::string&, const CClaimTrieData&)> function) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CClaimTrie* base;
|
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> nodesAlreadyCached; // set of nodes already pulled into cache from base
|
||||||
std::unordered_set<std::string> namesToCheckForTakeover; // takeover numbers are updated on increment
|
std::unordered_set<std::string> namesToCheckForTakeover; // takeover numbers are updated on increment
|
||||||
|
|
||||||
virtual uint256 recursiveComputeMerkleHash(CClaimTrie::iterator& it);
|
virtual uint256 recursiveComputeMerkleHash(CClaimPrefixTrie::iterator& it);
|
||||||
virtual bool recursiveCheckConsistency(CClaimTrie::const_iterator& it, std::string& failed) const;
|
|
||||||
|
|
||||||
virtual bool insertClaimIntoTrie(const std::string& name, const CClaimValue& claim, bool fCheckTakeover);
|
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);
|
virtual bool removeClaimFromTrie(const std::string& name, const COutPoint& outPoint, CClaimValue& claim, bool fCheckTakeover);
|
||||||
|
@ -553,7 +587,7 @@ protected:
|
||||||
int getDelayForName(const std::string& name) const;
|
int getDelayForName(const std::string& name) const;
|
||||||
virtual int getDelayForName(const std::string& name, const uint160& claimId) 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;
|
bool getLastTakeoverForName(const std::string& name, uint160& claimId, int& takeoverHeight) const;
|
||||||
|
|
||||||
|
@ -584,6 +618,7 @@ private:
|
||||||
std::unordered_set<std::string> nodesToDelete; // to be removed from base (and disk) on flush
|
std::unordered_set<std::string> nodesToDelete; // to be removed from base (and disk) on flush
|
||||||
std::unordered_map<std::string, bool> takeoverWorkaround;
|
std::unordered_map<std::string, bool> takeoverWorkaround;
|
||||||
std::unordered_set<std::string> removalWorkaround;
|
std::unordered_set<std::string> removalWorkaround;
|
||||||
|
std::unordered_set<std::string> forDeleteFromBase;
|
||||||
|
|
||||||
bool shouldUseTakeoverWorkaround(const std::string& key) const;
|
bool shouldUseTakeoverWorkaround(const std::string& key) const;
|
||||||
void addTakeoverWorkaroundPotential(const std::string& key);
|
void addTakeoverWorkaroundPotential(const std::string& key);
|
||||||
|
@ -595,6 +630,8 @@ private:
|
||||||
bool removeSupport(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight, bool fCheckTakeover);
|
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 removeClaim(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight, bool fCheckTakeover);
|
||||||
|
|
||||||
|
bool validateTrieConsistency(const CBlockIndex* tip);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void insertRowsFromQueue(std::vector<T>& result, const std::string& name) const;
|
void insertRowsFromQueue(std::vector<T>& result, const std::string& name) const;
|
||||||
|
|
||||||
|
@ -744,13 +781,20 @@ public:
|
||||||
bool allowSupportMetadata() const;
|
bool allowSupportMetadata() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint256 recursiveComputeMerkleHash(CClaimTrie::iterator& it) override;
|
uint256 recursiveComputeMerkleHash(CClaimPrefixTrie::iterator& it) override;
|
||||||
bool recursiveCheckConsistency(CClaimTrie::const_iterator& it, std::string& failed) const override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void copyAllBaseToCache();
|
void copyAllBaseToCache();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CClaimTrieHashFork : public CClaimTrie
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using CClaimTrie::CClaimTrie;
|
||||||
|
protected:
|
||||||
|
bool checkConsistency(const uint256& rootHash) const override;
|
||||||
|
};
|
||||||
|
|
||||||
typedef CClaimTrieCacheHashFork CClaimTrieCache;
|
typedef CClaimTrieCacheHashFork CClaimTrieCache;
|
||||||
|
|
||||||
#endif // BITCOIN_CLAIMTRIE_H
|
#endif // BITCOIN_CLAIMTRIE_H
|
||||||
|
|
|
@ -5,8 +5,6 @@
|
||||||
#include <hash.h>
|
#include <hash.h>
|
||||||
|
|
||||||
#include <boost/locale.hpp>
|
#include <boost/locale.hpp>
|
||||||
#include <boost/locale/conversion.hpp>
|
|
||||||
#include <boost/locale/localization_backend.hpp>
|
|
||||||
#include <boost/scope_exit.hpp>
|
#include <boost/scope_exit.hpp>
|
||||||
#include <boost/scoped_ptr.hpp>
|
#include <boost/scoped_ptr.hpp>
|
||||||
|
|
||||||
|
@ -172,12 +170,17 @@ bool CClaimTrieCacheNormalizationFork::normalizeAllNamesInTrieIfNecessary(insert
|
||||||
// run the one-time upgrade of all names that need to change
|
// 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
|
// 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) {
|
boost::scoped_ptr<CDBIterator> pcursor(base->db->NewIterator());
|
||||||
const std::string normalized = normalizeClaimName(it.key(), true);
|
for (pcursor->SeekToFirst(); pcursor->Valid(); pcursor->Next()) {
|
||||||
if (normalized == it.key())
|
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;
|
continue;
|
||||||
|
|
||||||
auto& name = it.key();
|
|
||||||
auto supports = getSupportsForName(name);
|
auto supports = getSupportsForName(name);
|
||||||
for (auto support : supports) {
|
for (auto support : supports) {
|
||||||
// if it's already going to expire just skip it
|
// if it's already going to expire just skip it
|
||||||
|
@ -272,17 +275,23 @@ std::vector<uint256> getClaimHashes(const CClaimTrieData& data)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using iCbType = std::function<uint256(T&)>;
|
using iCbType = std::function<uint256(T&)>;
|
||||||
|
|
||||||
template <typename TIterator>
|
template <typename T>
|
||||||
uint256 recursiveBinaryTreeHash(TIterator& it, const iCbType<TIterator>& process)
|
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;
|
std::vector<uint256> childHashes;
|
||||||
for (auto& child : it.children())
|
for (auto& child : children)
|
||||||
childHashes.emplace_back(process(child));
|
childHashes.emplace_back(childHash(child));
|
||||||
|
|
||||||
std::vector<uint256> claimHashes;
|
std::vector<uint256> claimHashes;
|
||||||
if (!it->empty())
|
if (!data.empty())
|
||||||
claimHashes = getClaimHashes(it.data());
|
claimHashes = getClaimHashes(data);
|
||||||
else if (!it.hasChildren())
|
else if (children.empty())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
auto left = childHashes.empty() ? leafHash : ComputeMerkleRoot(childHashes);
|
auto left = childHashes.empty() ? leafHash : ComputeMerkleRoot(childHashes);
|
||||||
|
@ -291,44 +300,53 @@ uint256 recursiveBinaryTreeHash(TIterator& it, const iCbType<TIterator>& process
|
||||||
return Hash(left.begin(), left.end(), right.begin(), right.end());
|
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)
|
if (nNextHeight < Params().GetConsensus().nAllClaimsInMerkleForkHeight)
|
||||||
return CClaimTrieCacheNormalizationFork::recursiveComputeMerkleHash(it);
|
return CClaimTrieCacheNormalizationFork::recursiveComputeMerkleHash(it);
|
||||||
|
|
||||||
using iterator = CClaimTrie::iterator;
|
using iterator = CClaimPrefixTrie::iterator;
|
||||||
iCbType<iterator> process = [&process](iterator& it) -> uint256 {
|
iCbType<iterator> process = [&process](iterator& it) -> uint256 {
|
||||||
if (it->hash.IsNull())
|
if (it->hash.IsNull())
|
||||||
it->hash = recursiveBinaryTreeHash(it, process);
|
it->hash = recursiveMerkleHash(it.data(), it.children(), process);
|
||||||
assert(!it->hash.IsNull());
|
|
||||||
return it->hash;
|
return it->hash;
|
||||||
};
|
};
|
||||||
return process(it);
|
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)
|
std::vector<uint256> ComputeMerklePath(const std::vector<uint256>& hashes, uint32_t idx)
|
||||||
{
|
{
|
||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
|
@ -404,7 +422,7 @@ bool CClaimTrieCacheHashFork::getProofForName(const std::string& name, CClaimTri
|
||||||
cacheData(name, false);
|
cacheData(name, false);
|
||||||
getMerkleHash();
|
getMerkleHash();
|
||||||
proof = CClaimTrieProof();
|
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;
|
std::vector<uint256> childHashes;
|
||||||
uint32_t nextCurrentIdx = 0;
|
uint32_t nextCurrentIdx = 0;
|
||||||
for (auto& child : it.children()) {
|
for (auto& child : it.children()) {
|
||||||
|
@ -447,12 +465,15 @@ bool CClaimTrieCacheHashFork::getProofForName(const std::string& name, CClaimTri
|
||||||
|
|
||||||
void CClaimTrieCacheHashFork::copyAllBaseToCache()
|
void CClaimTrieCacheHashFork::copyAllBaseToCache()
|
||||||
{
|
{
|
||||||
for (auto it = base->cbegin(); it != base->cend(); ++it)
|
recurseNodes({}, [this](const std::string& name, const CClaimTrieData& data) {
|
||||||
if (nodesAlreadyCached.insert(it.key()).second)
|
if (nodesAlreadyCached.insert(name).second)
|
||||||
nodesToAddOrUpdate.insert(it.key(), it.data());
|
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->hash.SetNull();
|
||||||
|
it->flags |= CClaimTrieDataFlags::HASH_DIRTY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClaimTrieCacheHashFork::initializeIncrement()
|
void CClaimTrieCacheHashFork::initializeIncrement()
|
||||||
|
@ -475,7 +496,6 @@ bool CClaimTrieCacheHashFork::finalizeDecrement(std::vector<std::pair<std::strin
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrieCacheHashFork::allowSupportMetadata() const
|
bool CClaimTrieCacheHashFork::allowSupportMetadata() const {
|
||||||
{
|
|
||||||
return nNextHeight >= Params().GetConsensus().nAllClaimsInMerkleForkHeight;
|
return nNextHeight >= Params().GetConsensus().nAllClaimsInMerkleForkHeight;
|
||||||
}
|
}
|
||||||
|
|
12
src/init.cpp
12
src/init.cpp
|
@ -22,7 +22,6 @@
|
||||||
#include <httprpc.h>
|
#include <httprpc.h>
|
||||||
#include <index/txindex.h>
|
#include <index/txindex.h>
|
||||||
#include <key.h>
|
#include <key.h>
|
||||||
#include <lbry.h>
|
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <miner.h>
|
#include <miner.h>
|
||||||
#include <netbase.h>
|
#include <netbase.h>
|
||||||
|
@ -399,7 +398,6 @@ void SetupServerArgs()
|
||||||
hidden_args.emplace_back("-sysperms");
|
hidden_args.emplace_back("-sysperms");
|
||||||
#endif
|
#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("-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("-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);
|
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);
|
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("-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("-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);
|
gArgs.AddArg("-uacomment=<cmt>", "Append comment to the user agent string", false, OptionsCategory::DEBUG_TEST);
|
||||||
|
|
||||||
SetupChainParamsBaseOptions();
|
SetupChainParamsBaseOptions();
|
||||||
|
@ -1235,6 +1234,11 @@ bool AppInitMain()
|
||||||
CreatePidFile(GetPidFile(), getpid());
|
CreatePidFile(GetPidFile(), getpid());
|
||||||
#endif
|
#endif
|
||||||
if (g_logger->m_print_to_file) {
|
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()) {
|
if (!g_logger->OpenDebugLog()) {
|
||||||
return InitError(strprintf("Could not open debug log file %s",
|
return InitError(strprintf("Could not open debug log file %s",
|
||||||
g_logger->m_file_path.string()));
|
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 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));
|
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;
|
bool fLoaded = false;
|
||||||
while (!fLoaded && !ShutdownRequested()) {
|
while (!fLoaded && !ShutdownRequested()) {
|
||||||
bool fReset = fReindex;
|
bool fReset = fReindex;
|
||||||
|
@ -1463,7 +1465,7 @@ bool AppInitMain()
|
||||||
int64_t trieCacheMB = gArgs.GetArg("-claimtriecache", nDefaultDbCache);
|
int64_t trieCacheMB = gArgs.GetArg("-claimtriecache", nDefaultDbCache);
|
||||||
trieCacheMB = std::min(trieCacheMB, nMaxDbCache);
|
trieCacheMB = std::min(trieCacheMB, nMaxDbCache);
|
||||||
trieCacheMB = std::max(trieCacheMB, nMinDbCache);
|
trieCacheMB = std::max(trieCacheMB, nMinDbCache);
|
||||||
pclaimTrie = new CClaimTrie(false, fReindex || fReindexChainState, 32, trieCacheMB);
|
pclaimTrie = new CClaimTrieHashFork(false, fReindex || fReindexChainState, 32, trieCacheMB);
|
||||||
|
|
||||||
if (fReset) {
|
if (fReset) {
|
||||||
pblocktree->WriteReindexing(true);
|
pblocktree->WriteReindexing(true);
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
uint32_t g_memfileSize = 0;
|
|
||||||
|
|
||||||
unsigned int CalculateLbryNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
|
unsigned int CalculateLbryNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
|
||||||
{
|
{
|
||||||
if (params.fPowNoRetargeting)
|
if (params.fPowNoRetargeting)
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#ifndef LBRY_H
|
#ifndef BITCOIN_LBRY_H
|
||||||
#define LBRY_H
|
#define BITCOIN_LBRY_H
|
||||||
|
|
||||||
#include <chain.h>
|
#include <chain.h>
|
||||||
#include <chainparams.h>
|
#include <chainparams.h>
|
||||||
|
|
||||||
extern uint32_t g_memfileSize;
|
|
||||||
unsigned int CalculateLbryNextWorkRequired(const CBlockIndex* pindexLast, int64_t nLastRetargetTime, const Consensus::Params& params);
|
unsigned int CalculateLbryNextWorkRequired(const CBlockIndex* pindexLast, int64_t nLastRetargetTime, const Consensus::Params& params);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -37,12 +37,6 @@ bool BCLog::Logger::OpenDebugLog()
|
||||||
assert(m_fileout == nullptr);
|
assert(m_fileout == nullptr);
|
||||||
assert(!m_file_path.empty());
|
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");
|
m_fileout = fsbridge::fopen(m_file_path, "a");
|
||||||
if (!m_fileout) {
|
if (!m_fileout) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -89,6 +83,11 @@ bool BCLog::Logger::WillLogCategory(BCLog::LogFlags category) const
|
||||||
return (m_categories.load(std::memory_order_relaxed) & category) != 0;
|
return (m_categories.load(std::memory_order_relaxed) & category) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BCLog::Logger::DefaultShrinkDebugFile() const
|
||||||
|
{
|
||||||
|
return m_categories == BCLog::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
struct CLogCategoryDesc
|
struct CLogCategoryDesc
|
||||||
{
|
{
|
||||||
BCLog::LogFlags flag;
|
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 Enabled() const { return m_print_to_console || m_print_to_file; }
|
||||||
|
|
||||||
bool OpenDebugLog();
|
bool OpenDebugLog();
|
||||||
|
void ShrinkDebugFile();
|
||||||
|
|
||||||
uint32_t GetCategoryMask() const { return m_categories.load(); }
|
uint32_t GetCategoryMask() const { return m_categories.load(); }
|
||||||
|
|
||||||
|
@ -102,6 +103,8 @@ namespace BCLog {
|
||||||
bool DisableCategory(const std::string& str);
|
bool DisableCategory(const std::string& str);
|
||||||
|
|
||||||
bool WillLogCategory(LogFlags category) const;
|
bool WillLogCategory(LogFlags category) const;
|
||||||
|
|
||||||
|
bool DefaultShrinkDebugFile() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace BCLog
|
} // namespace BCLog
|
||||||
|
|
|
@ -208,7 +208,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
|
||||||
CValidationState state;
|
CValidationState state;
|
||||||
if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) {
|
if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) {
|
||||||
if (!trieCache.empty())
|
if (!trieCache.empty())
|
||||||
trieCache.dumpToLog(trieCache.find({}));
|
trieCache.dumpToLog(trieCache.begin());
|
||||||
throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state)));
|
throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state)));
|
||||||
}
|
}
|
||||||
int64_t nTime2 = GetTimeMicros();
|
int64_t nTime2 = GetTimeMicros();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "nameclaim.h"
|
#include <nameclaim.h>
|
||||||
#include "hash.h"
|
#include <hash.h>
|
||||||
#include "util.h"
|
#include <util.h>
|
||||||
|
|
||||||
std::vector<unsigned char> uint32_t_to_vch(uint32_t n)
|
std::vector<unsigned char> uint32_t_to_vch(uint32_t n)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#ifndef BITCOIN_NAMECLAIM_H
|
#ifndef BITCOIN_NAMECLAIM_H
|
||||||
#define BITCOIN_NAMECLAIM_H
|
#define BITCOIN_NAMECLAIM_H
|
||||||
|
|
||||||
#include "amount.h"
|
#include <amount.h>
|
||||||
#include "script/script.h"
|
#include <script/script.h>
|
||||||
#include "primitives/transaction.h"
|
#include <primitives/transaction.h>
|
||||||
#include "uint256.h"
|
#include <uint256.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
|
@ -3666,7 +3666,8 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
|
||||||
if (state.vBlocksInFlight.size() > 0) {
|
if (state.vBlocksInFlight.size() > 0) {
|
||||||
QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
|
QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
|
||||||
int nOtherPeersWithValidatedDownloads = nPeersWithValidatedDownloads - (state.nBlocksInFlightValidHeaders > 0);
|
int nOtherPeersWithValidatedDownloads = nPeersWithValidatedDownloads - (state.nBlocksInFlightValidHeaders > 0);
|
||||||
if (nNow > state.nDownloadingSince + consensusParams.nPowTargetSpacing * (BLOCK_DOWNLOAD_TIMEOUT_BASE + BLOCK_DOWNLOAD_TIMEOUT_PER_PEER * nOtherPeersWithValidatedDownloads)) {
|
auto powTargetSpacing = std::max(int64_t(2) * 60, consensusParams.nPowTargetSpacing);
|
||||||
|
if (nNow > state.nDownloadingSince + powTargetSpacing * (BLOCK_DOWNLOAD_TIMEOUT_BASE + BLOCK_DOWNLOAD_TIMEOUT_PER_PEER * nOtherPeersWithValidatedDownloads)) {
|
||||||
LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.hash.ToString(), pto->GetId());
|
LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.hash.ToString(), pto->GetId());
|
||||||
pto->fDisconnect = true;
|
pto->fDisconnect = true;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,79 +1,5 @@
|
||||||
|
|
||||||
#include <claimtrie.h>
|
|
||||||
#include <fs.h>
|
|
||||||
#include <lbry.h>
|
|
||||||
#include <limits>
|
|
||||||
#include <memory>
|
|
||||||
#include <prefixtrie.h>
|
#include <prefixtrie.h>
|
||||||
|
#include <claimtrie.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)...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TKey, typename TData>
|
template <typename TKey, typename TData>
|
||||||
template <bool IsConst>
|
template <bool IsConst>
|
||||||
|
@ -91,7 +17,7 @@ typename CPrefixTrie<TKey, TData>::template Iterator<IsConst>& CPrefixTrie<TKey,
|
||||||
stack.clear();
|
stack.clear();
|
||||||
stack.reserve(o.stack.size());
|
stack.reserve(o.stack.size());
|
||||||
for (auto& i : o.stack)
|
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;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +47,7 @@ typename CPrefixTrie<TKey, TData>::template Iterator<IsConst>& CPrefixTrie<TKey,
|
||||||
if (!shared->children.empty()) {
|
if (!shared->children.empty()) {
|
||||||
auto& children = shared->children;
|
auto& children = shared->children;
|
||||||
auto it = children.begin();
|
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;
|
auto& postfix = it->first;
|
||||||
name.insert(name.end(), postfix.begin(), postfix.end());
|
name.insert(name.end(), postfix.begin(), postfix.end());
|
||||||
node = it->second;
|
node = it->second;
|
||||||
|
@ -179,30 +105,18 @@ bool CPrefixTrie<TKey, TData>::Iterator<IsConst>::operator!=(const Iterator& o)
|
||||||
|
|
||||||
template <typename TKey, typename TData>
|
template <typename TKey, typename TData>
|
||||||
template <bool IsConst>
|
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()};
|
assert(!node.expired());
|
||||||
|
return TPair(name, node.lock()->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TKey, typename TData>
|
template <typename TKey, typename TData>
|
||||||
template <bool IsConst>
|
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()};
|
assert(!node.expired());
|
||||||
}
|
return &(node.lock()->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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TKey, typename TData>
|
template <typename TKey, typename TData>
|
||||||
|
@ -214,20 +128,18 @@ const TKey& CPrefixTrie<TKey, TData>::Iterator<IsConst>::key() const
|
||||||
|
|
||||||
template <typename TKey, typename TData>
|
template <typename TKey, typename TData>
|
||||||
template <bool IsConst>
|
template <bool IsConst>
|
||||||
typename CPrefixTrie<TKey, TData>::template Iterator<IsConst>::data_reference CPrefixTrie<TKey, TData>::Iterator<IsConst>::data()
|
TData& CPrefixTrie<TKey, TData>::Iterator<IsConst>::data()
|
||||||
{
|
{
|
||||||
auto shared = node.lock();
|
assert(!node.expired());
|
||||||
assert(shared);
|
return node.lock()->data;
|
||||||
return *(shared->data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TKey, typename TData>
|
template <typename TKey, typename TData>
|
||||||
template <bool IsConst>
|
template <bool IsConst>
|
||||||
const TData& CPrefixTrie<TKey, TData>::Iterator<IsConst>::data() const
|
const TData& CPrefixTrie<TKey, TData>::Iterator<IsConst>::data() const
|
||||||
{
|
{
|
||||||
auto shared = node.lock();
|
assert(!node.expired());
|
||||||
assert(shared);
|
return node.lock()->data;
|
||||||
return *(shared->data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TKey, typename TData>
|
template <typename TKey, typename TData>
|
||||||
|
@ -327,20 +239,19 @@ std::shared_ptr<typename CPrefixTrie<TKey, TData>::Node>& CPrefixTrie<TKey, TDat
|
||||||
}
|
}
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
++size;
|
++size;
|
||||||
it = children.emplace(key, allocateShared<Node>()).first;
|
it = children.emplace(key, std::make_shared<Node>()).first;
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
if (count < it->first.size()) {
|
if (count < it->first.size()) {
|
||||||
TKey prefix(key.begin(), key.begin() + count);
|
const TKey prefix(key.begin(), key.begin() + count);
|
||||||
TKey postfix(it->first.begin() + count, it->first.end());
|
const TKey postfix(it->first.begin() + count, it->first.end());
|
||||||
auto nodes = std::move(it->second);
|
auto nodes = std::move(it->second);
|
||||||
children.erase(it);
|
children.erase(it);
|
||||||
++size;
|
++size;
|
||||||
it = children.emplace(std::move(prefix), allocateShared<Node>()).first;
|
it = children.emplace(prefix, std::make_shared<Node>()).first;
|
||||||
it->second->children.emplace(std::move(postfix), std::move(nodes));
|
it->second->children.emplace(postfix, std::move(nodes));
|
||||||
if (key.size() == count)
|
if (key.size() == count)
|
||||||
return it->second;
|
return it->second;
|
||||||
it->second->data = allocateShared<TData>();
|
|
||||||
}
|
}
|
||||||
return insert(TKey(key.begin() + count, key.end()), it->second);
|
return insert(TKey(key.begin() + count, key.end()), it->second);
|
||||||
}
|
}
|
||||||
|
@ -357,12 +268,12 @@ void CPrefixTrie<TKey, TData>::erase(const TKey& key, std::shared_ptr<Node>& nod
|
||||||
if (!find(key, node, cb))
|
if (!find(key, node, cb))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
nodes.back().second->data = allocateShared<TData>();
|
nodes.back().second->data = {};
|
||||||
for (; nodes.size() > 1; nodes.pop_back()) {
|
for (; nodes.size() > 1; nodes.pop_back()) {
|
||||||
// if we have only one child and no data ourselves, bring them up to our level
|
// if we have only one child and no data ourselves, bring them up to our level
|
||||||
auto& cNode = nodes.back().second;
|
auto& cNode = nodes.back().second;
|
||||||
auto onlyOneChild = cNode->children.size() == 1;
|
auto onlyOneChild = cNode->children.size() == 1;
|
||||||
auto noData = cNode->data->empty();
|
auto noData = cNode->data.empty();
|
||||||
if (onlyOneChild && noData) {
|
if (onlyOneChild && noData) {
|
||||||
auto child = cNode->children.begin();
|
auto child = cNode->children.begin();
|
||||||
auto& prefix = nodes.back().first;
|
auto& prefix = nodes.back().first;
|
||||||
|
@ -370,7 +281,7 @@ void CPrefixTrie<TKey, TData>::erase(const TKey& key, std::shared_ptr<Node>& nod
|
||||||
auto& postfix = child->first;
|
auto& postfix = child->first;
|
||||||
newKey.insert(newKey.end(), postfix.begin(), postfix.end());
|
newKey.insert(newKey.end(), postfix.begin(), postfix.end());
|
||||||
auto& pNode = nodes[nodes.size() - 2].second;
|
auto& pNode = nodes[nodes.size() - 2].second;
|
||||||
pNode->children.emplace(std::move(newKey), std::move(child->second));
|
pNode->children.emplace(newKey, std::move(child->second));
|
||||||
pNode->children.erase(prefix);
|
pNode->children.erase(prefix);
|
||||||
--size;
|
--size;
|
||||||
continue;
|
continue;
|
||||||
|
@ -388,9 +299,8 @@ void CPrefixTrie<TKey, TData>::erase(const TKey& key, std::shared_ptr<Node>& nod
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TKey, typename TData>
|
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>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TKey, typename TData>
|
template <typename TKey, typename TData>
|
||||||
|
@ -398,7 +308,7 @@ template <typename TDataUni>
|
||||||
typename CPrefixTrie<TKey, TData>::iterator CPrefixTrie<TKey, TData>::insert(const TKey& key, TDataUni&& data)
|
typename CPrefixTrie<TKey, TData>::iterator CPrefixTrie<TKey, TData>::insert(const TKey& key, TDataUni&& data)
|
||||||
{
|
{
|
||||||
auto& node = key.empty() ? root : insert(key, root);
|
auto& node = key.empty() ? root : insert(key, root);
|
||||||
node->data = allocateShared<TData>(std::forward<TDataUni>(data));
|
node->data = std::forward<TDataUni>(data);
|
||||||
return key.empty() ? begin() : iterator{key, node};
|
return key.empty() ? begin() : iterator{key, node};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,9 +332,9 @@ typename CPrefixTrie<TKey, TData>::iterator CPrefixTrie<TKey, TData>::insert(CPr
|
||||||
auto name = it.key();
|
auto name = it.key();
|
||||||
name.insert(name.end(), key.begin(), key.end());
|
name.insert(name.end(), key.begin(), key.end());
|
||||||
auto& node = insert(key, shared);
|
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::forward<TDataUni>(data);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,7 +403,7 @@ bool CPrefixTrie<TKey, TData>::erase(const TKey& key)
|
||||||
{
|
{
|
||||||
auto size_was = height();
|
auto size_was = height();
|
||||||
if (key.empty()) {
|
if (key.empty()) {
|
||||||
root->data = allocateShared<TData>();
|
root->data = {};
|
||||||
} else {
|
} else {
|
||||||
erase(key, root);
|
erase(key, root);
|
||||||
}
|
}
|
||||||
|
@ -504,7 +414,7 @@ template <typename TKey, typename TData>
|
||||||
void CPrefixTrie<TKey, TData>::clear()
|
void CPrefixTrie<TKey, TData>::clear()
|
||||||
{
|
{
|
||||||
size = 0;
|
size = 0;
|
||||||
root->data = allocateShared<TData>();
|
root->data = {};
|
||||||
root->children.clear();
|
root->children.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -517,7 +427,7 @@ bool CPrefixTrie<TKey, TData>::empty() const
|
||||||
template <typename TKey, typename TData>
|
template <typename TKey, typename TData>
|
||||||
std::size_t CPrefixTrie<TKey, TData>::height() const
|
std::size_t CPrefixTrie<TKey, TData>::height() const
|
||||||
{
|
{
|
||||||
return size + (root->data->empty() ? 0 : 1);
|
return size + (root->data.empty() ? 0 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TKey, typename TData>
|
template <typename TKey, typename TData>
|
||||||
|
|
|
@ -27,9 +27,9 @@ class CPrefixTrie
|
||||||
Node() = default;
|
Node() = default;
|
||||||
Node(const Node&) = delete;
|
Node(const Node&) = delete;
|
||||||
Node(Node&& o) noexcept = default;
|
Node(Node&& o) noexcept = default;
|
||||||
Node& operator=(Node&&) noexcept = default;
|
Node& operator=(Node&& o) noexcept = default;
|
||||||
Node& operator=(const Node&) = delete;
|
Node& operator=(const Node&) = delete;
|
||||||
std::shared_ptr<TData> data;
|
TData data;
|
||||||
};
|
};
|
||||||
|
|
||||||
using TChildren = decltype(Node::children);
|
using TChildren = decltype(Node::children);
|
||||||
|
@ -42,15 +42,15 @@ class CPrefixTrie
|
||||||
friend class CPrefixTrie<TKey, TData>;
|
friend class CPrefixTrie<TKey, TData>;
|
||||||
|
|
||||||
using TKeyRef = std::reference_wrapper<const TKey>;
|
using TKeyRef = std::reference_wrapper<const TKey>;
|
||||||
using TDataRef = std::reference_wrapper<typename std::conditional<IsConst, const TData, TData>::type>;
|
using TDataRef = std::reference_wrapper<TData>;
|
||||||
using TPair = std::pair<TKeyRef, TDataRef>;
|
using TPair = std::pair<TKeyRef, TDataRef>;
|
||||||
using ConstTPair = std::pair<TKeyRef, const TData>;
|
|
||||||
|
|
||||||
TKey name;
|
TKey name;
|
||||||
std::weak_ptr<Node> node;
|
std::weak_ptr<Node> node;
|
||||||
|
|
||||||
struct Bookmark {
|
struct Bookmark {
|
||||||
TKey name;
|
TKey name;
|
||||||
|
std::weak_ptr<Node> parent;
|
||||||
typename TChildren::iterator it;
|
typename TChildren::iterator it;
|
||||||
typename TChildren::iterator end;
|
typename TChildren::iterator end;
|
||||||
};
|
};
|
||||||
|
@ -60,11 +60,8 @@ class CPrefixTrie
|
||||||
public:
|
public:
|
||||||
// Iterator traits
|
// Iterator traits
|
||||||
using value_type = TPair;
|
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 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 difference_type = std::ptrdiff_t;
|
||||||
using iterator_category = std::forward_iterator_tag;
|
using iterator_category = std::forward_iterator_tag;
|
||||||
|
|
||||||
|
@ -92,15 +89,12 @@ class CPrefixTrie
|
||||||
bool operator==(const Iterator& o) const;
|
bool operator==(const Iterator& o) const;
|
||||||
bool operator!=(const Iterator& o) const;
|
bool operator!=(const Iterator& o) const;
|
||||||
|
|
||||||
reference operator*();
|
reference operator*() const;
|
||||||
const_reference operator*() const;
|
pointer operator->() const;
|
||||||
|
|
||||||
pointer operator->();
|
|
||||||
const_pointer operator->() const;
|
|
||||||
|
|
||||||
const TKey& key() const;
|
const TKey& key() const;
|
||||||
|
|
||||||
data_reference data();
|
TData& data();
|
||||||
const TData& data() const;
|
const TData& data() const;
|
||||||
|
|
||||||
std::size_t depth() const;
|
std::size_t depth() const;
|
||||||
|
|
|
@ -1319,8 +1319,6 @@ static UniValue getchaintips(const JSONRPCRequest& request)
|
||||||
" \"height\": xxxx,\n"
|
" \"height\": xxxx,\n"
|
||||||
" \"hash\": \"xxxx\",\n"
|
" \"hash\": \"xxxx\",\n"
|
||||||
" \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\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"
|
" \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"]\n"
|
"]\n"
|
||||||
|
@ -1374,19 +1372,8 @@ static UniValue getchaintips(const JSONRPCRequest& request)
|
||||||
obj.pushKV("height", block->nHeight);
|
obj.pushKV("height", block->nHeight);
|
||||||
obj.pushKV("hash", block->phashBlock->GetHex());
|
obj.pushKV("hash", block->phashBlock->GetHex());
|
||||||
|
|
||||||
// not use ForkAt method because we need the previous one as well
|
const int branchLen = block->nHeight - chainActive.FindFork(block)->nHeight;
|
||||||
const CBlockIndex *forkAt = block, *forkPrev = block;
|
|
||||||
while (forkAt && !chainActive.Contains(forkAt)) {
|
|
||||||
forkPrev = forkAt;
|
|
||||||
forkAt = forkAt->pprev;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int branchLen = block->nHeight - forkAt->nHeight;
|
|
||||||
obj.pushKV("branchlen", branchLen);
|
obj.pushKV("branchlen", branchLen);
|
||||||
if (forkAt != forkPrev) {
|
|
||||||
obj.pushKV("branchhash", forkAt->phashBlock->GetHex());
|
|
||||||
obj.pushKV("branchhashNext", forkPrev->phashBlock->GetHex());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string status;
|
std::string status;
|
||||||
if (chainActive.Contains(block)) {
|
if (chainActive.Contains(block)) {
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
|
|
||||||
#include <boost/locale.hpp>
|
#include <boost/locale.hpp>
|
||||||
#include <boost/locale/conversion.hpp>
|
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
@ -307,7 +306,7 @@ static UniValue getclaimsintrie(const JSONRPCRequest& request)
|
||||||
}
|
}
|
||||||
|
|
||||||
UniValue ret(UniValue::VARR);
|
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())
|
if (ShutdownRequested())
|
||||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Shutdown requested");
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Shutdown requested");
|
||||||
|
|
||||||
|
@ -348,7 +347,7 @@ static UniValue getnamesintrie(const JSONRPCRequest& request)
|
||||||
}
|
}
|
||||||
|
|
||||||
UniValue ret(UniValue::VARR);
|
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())
|
if (!data.empty())
|
||||||
ret.push_back(escapeNonUtf8(name));
|
ret.push_back(escapeNonUtf8(name));
|
||||||
if (ShutdownRequested())
|
if (ShutdownRequested())
|
||||||
|
|
|
@ -451,7 +451,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
|
||||||
if (strMode != "template")
|
if (strMode != "template")
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
|
||||||
|
|
||||||
if (Params().NetworkIDString() == CBaseChainParams::MAIN)
|
if (Params().NetworkIDString() != CBaseChainParams::REGTEST) // who should own this constant?
|
||||||
{
|
{
|
||||||
if (!g_connman)
|
if (!g_connman)
|
||||||
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
|
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
|
// 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));
|
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 aCaps(UniValue::VARR); aCaps.push_back("proposal");
|
||||||
UniValue result(UniValue::VOBJ);
|
UniValue result(UniValue::VOBJ);
|
||||||
|
@ -623,6 +621,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
|
||||||
aMutable.push_back("time");
|
aMutable.push_back("time");
|
||||||
aMutable.push_back("transactions");
|
aMutable.push_back("transactions");
|
||||||
aMutable.push_back("prevblock");
|
aMutable.push_back("prevblock");
|
||||||
|
aMutable.push_back("submit/coinbase");
|
||||||
|
|
||||||
result.pushKV("capabilities", aCaps);
|
result.pushKV("capabilities", aCaps);
|
||||||
|
|
||||||
|
|
|
@ -436,9 +436,17 @@ CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniVal
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
|
throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
|
||||||
}
|
}
|
||||||
|
|
||||||
CScript scriptPubKey = GetScriptForDestination(destination);
|
auto rawAmount = outputs[name_];
|
||||||
CAmount nAmount = AmountFromValue(outputs[name_]);
|
CAmount nAmount;
|
||||||
|
CScript prefix;
|
||||||
|
if (rawAmount.isArray() && rawAmount.size() > 2) {
|
||||||
|
nAmount = AmountFromValue(rawAmount[0]);
|
||||||
|
prefix = ClaimNameScript(rawAmount[1].get_str(), rawAmount[2].get_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
nAmount = AmountFromValue(outputs[name_]);
|
||||||
|
|
||||||
|
CScript scriptPubKey = prefix + GetScriptForDestination(destination);
|
||||||
CTxOut out(nAmount, scriptPubKey);
|
CTxOut out(nAmount, scriptPubKey);
|
||||||
rawTx.vout.push_back(out);
|
rawTx.vout.push_back(out);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,21 +64,9 @@ void CScheduler::serviceQueue()
|
||||||
// Explicitly use a template here to avoid hitting that overload.
|
// Explicitly use a template here to avoid hitting that overload.
|
||||||
while (!shouldStop() && !taskQueue.empty()) {
|
while (!shouldStop() && !taskQueue.empty()) {
|
||||||
boost::chrono::system_clock::time_point timeToWaitFor = taskQueue.begin()->first;
|
boost::chrono::system_clock::time_point timeToWaitFor = taskQueue.begin()->first;
|
||||||
try {
|
if (newTaskScheduled.wait_until<>(lock, timeToWaitFor) == boost::cv_status::timeout)
|
||||||
if (newTaskScheduled.wait_until<>(lock, timeToWaitFor) == boost::cv_status::timeout) {
|
|
||||||
break; // Exit loop after timeout, it means we reached the time of the event
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
// If there are multiple threads, the queue can empty while we're waiting (another
|
// If there are multiple threads, the queue can empty while we're waiting (another
|
||||||
// thread may service the task we were waiting on).
|
// thread may service the task we were waiting on).
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
// Copyright (c) 2011-2015 The Bitcoin Core developers
|
|
||||||
// Distributed under the MIT software license, see the accompanying
|
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
||||||
|
|
||||||
//
|
|
||||||
// Unit tests for block-chain checkpoints
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "checkpoints.h"
|
|
||||||
|
|
||||||
#include "uint256.h"
|
|
||||||
#include "test/test_bitcoin.h"
|
|
||||||
#include "chainparams.h"
|
|
||||||
|
|
||||||
#include <boost/test/unit_test.hpp>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_SUITE(Checkpoints_tests, BasicTestingSetup)
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(sanity)
|
|
||||||
{
|
|
||||||
//const CCheckpointData& checkpoints = Params(CBaseChainParams::MAIN).Checkpoints();
|
|
||||||
//BOOST_CHECK(Checkpoints::GetTotalBlocksEstimate(checkpoints) >= 134444);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
|
|
@ -18,7 +18,7 @@ BOOST_AUTO_TEST_CASE(claim_replace_test) {
|
||||||
fixture.Spend(tx1);
|
fixture.Spend(tx1);
|
||||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "bassfisher", "one", 1);
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "bassfisher", "one", 1);
|
||||||
fixture.IncrementBlocks(1);
|
fixture.IncrementBlocks(1);
|
||||||
BOOST_CHECK(fixture.checkConsistency());
|
BOOST_CHECK(pclaimTrie->checkConsistency(fixture.getMerkleHash()));
|
||||||
BOOST_CHECK(!fixture.is_best_claim("bass", tx1));
|
BOOST_CHECK(!fixture.is_best_claim("bass", tx1));
|
||||||
BOOST_CHECK(fixture.is_best_claim("bassfisher", tx2));
|
BOOST_CHECK(fixture.is_best_claim("bassfisher", tx2));
|
||||||
}
|
}
|
||||||
|
@ -1852,18 +1852,17 @@ BOOST_AUTO_TEST_CASE(update_on_support2_test)
|
||||||
CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, name, 1);
|
CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, name, 1);
|
||||||
fixture.IncrementBlocks(1);
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
auto it = pclaimTrie->find(name);
|
CClaimTrieData node;
|
||||||
BOOST_CHECK(it);
|
BOOST_CHECK(pclaimTrie->find(name, node));
|
||||||
BOOST_CHECK_EQUAL(it->nHeightOfLastTakeover, height + 1);
|
BOOST_CHECK_EQUAL(node.nHeightOfLastTakeover, height + 1);
|
||||||
|
|
||||||
fixture.Spend(s1);
|
fixture.Spend(s1);
|
||||||
fixture.Spend(s2);
|
fixture.Spend(s2);
|
||||||
CMutableTransaction u1 = fixture.MakeUpdate(tx1, name, value, ClaimIdHash(tx1.GetHash(), 0), 3);
|
CMutableTransaction u1 = fixture.MakeUpdate(tx1, name, value, ClaimIdHash(tx1.GetHash(), 0), 3);
|
||||||
fixture.IncrementBlocks(1);
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
it = pclaimTrie->find(name);
|
BOOST_CHECK(pclaimTrie->find(name, node));
|
||||||
BOOST_CHECK(it);
|
BOOST_CHECK_EQUAL(node.nHeightOfLastTakeover, height + 1);
|
||||||
BOOST_CHECK_EQUAL(it->nHeightOfLastTakeover, height + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
|
@ -37,7 +37,7 @@ public:
|
||||||
return nodesToAddOrUpdate.height();
|
return nodesToAddOrUpdate.height();
|
||||||
}
|
}
|
||||||
|
|
||||||
CClaimTrie::iterator getCache(const std::string& key)
|
CClaimPrefixTrie::iterator getCache(const std::string& key)
|
||||||
{
|
{
|
||||||
return nodesToAddOrUpdate.find(key);
|
return nodesToAddOrUpdate.find(key);
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
|
||||||
|
|
||||||
BOOST_CHECK(!pclaimTrie->empty());
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
BOOST_CHECK_EQUAL(ntState.getMerkleHash(), hash2);
|
BOOST_CHECK_EQUAL(ntState.getMerkleHash(), hash2);
|
||||||
BOOST_CHECK(ntState.checkConsistency());
|
BOOST_CHECK(pclaimTrie->checkConsistency(hash2));
|
||||||
|
|
||||||
CClaimTrieCacheTest ntState1(pclaimTrie);
|
CClaimTrieCacheTest ntState1(pclaimTrie);
|
||||||
ntState1.removeClaimFromTrie(std::string("test"), tx1OutPoint, unused, true);
|
ntState1.removeClaimFromTrie(std::string("test"), tx1OutPoint, unused, true);
|
||||||
|
@ -128,7 +128,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
|
||||||
|
|
||||||
BOOST_CHECK(!pclaimTrie->empty());
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
BOOST_CHECK_EQUAL(ntState2.getMerkleHash(), hash3);
|
BOOST_CHECK_EQUAL(ntState2.getMerkleHash(), hash3);
|
||||||
BOOST_CHECK(ntState2.checkConsistency());
|
BOOST_CHECK(pclaimTrie->checkConsistency(hash3));
|
||||||
|
|
||||||
CClaimTrieCacheTest ntState3(pclaimTrie);
|
CClaimTrieCacheTest ntState3(pclaimTrie);
|
||||||
ntState3.insertClaimIntoTrie(std::string("test"), CClaimValue(tx1OutPoint, hash160, 50, 100, 200), true);
|
ntState3.insertClaimIntoTrie(std::string("test"), CClaimValue(tx1OutPoint, hash160, 50, 100, 200), true);
|
||||||
|
@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
|
||||||
ntState3.flush();
|
ntState3.flush();
|
||||||
BOOST_CHECK(!pclaimTrie->empty());
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
BOOST_CHECK_EQUAL(ntState3.getMerkleHash(), hash4);
|
BOOST_CHECK_EQUAL(ntState3.getMerkleHash(), hash4);
|
||||||
BOOST_CHECK(ntState3.checkConsistency());
|
BOOST_CHECK(pclaimTrie->checkConsistency(hash4));
|
||||||
|
|
||||||
CClaimTrieCacheTest ntState4(pclaimTrie);
|
CClaimTrieCacheTest ntState4(pclaimTrie);
|
||||||
ntState4.removeClaimFromTrie(std::string("abab"), tx6OutPoint, unused, true);
|
ntState4.removeClaimFromTrie(std::string("abab"), tx6OutPoint, unused, true);
|
||||||
|
@ -144,7 +144,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
|
||||||
ntState4.flush();
|
ntState4.flush();
|
||||||
BOOST_CHECK(!pclaimTrie->empty());
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
BOOST_CHECK_EQUAL(ntState4.getMerkleHash(), hash2);
|
BOOST_CHECK_EQUAL(ntState4.getMerkleHash(), hash2);
|
||||||
BOOST_CHECK(ntState4.checkConsistency());
|
BOOST_CHECK(pclaimTrie->checkConsistency(hash2));
|
||||||
|
|
||||||
CClaimTrieCacheTest ntState5(pclaimTrie);
|
CClaimTrieCacheTest ntState5(pclaimTrie);
|
||||||
ntState5.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused, true);
|
ntState5.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused, true);
|
||||||
|
@ -153,7 +153,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
|
||||||
ntState5.flush();
|
ntState5.flush();
|
||||||
BOOST_CHECK(!pclaimTrie->empty());
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
BOOST_CHECK_EQUAL(ntState5.getMerkleHash(), hash2);
|
BOOST_CHECK_EQUAL(ntState5.getMerkleHash(), hash2);
|
||||||
BOOST_CHECK(ntState5.checkConsistency());
|
BOOST_CHECK(pclaimTrie->checkConsistency(hash2));
|
||||||
|
|
||||||
CClaimTrieCacheTest ntState6(pclaimTrie);
|
CClaimTrieCacheTest ntState6(pclaimTrie);
|
||||||
ntState6.insertClaimIntoTrie(std::string("test"), CClaimValue(tx3OutPoint, hash160, 50, 101, 201), true);
|
ntState6.insertClaimIntoTrie(std::string("test"), CClaimValue(tx3OutPoint, hash160, 50, 101, 201), true);
|
||||||
|
@ -162,7 +162,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
|
||||||
ntState6.flush();
|
ntState6.flush();
|
||||||
BOOST_CHECK(!pclaimTrie->empty());
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
BOOST_CHECK_EQUAL(ntState6.getMerkleHash(), hash2);
|
BOOST_CHECK_EQUAL(ntState6.getMerkleHash(), hash2);
|
||||||
BOOST_CHECK(ntState6.checkConsistency());
|
BOOST_CHECK(pclaimTrie->checkConsistency(hash2));
|
||||||
|
|
||||||
CClaimTrieCacheTest ntState7(pclaimTrie);
|
CClaimTrieCacheTest ntState7(pclaimTrie);
|
||||||
ntState7.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused, true);
|
ntState7.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused, true);
|
||||||
|
@ -174,7 +174,7 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test)
|
||||||
ntState7.flush();
|
ntState7.flush();
|
||||||
BOOST_CHECK(pclaimTrie->empty());
|
BOOST_CHECK(pclaimTrie->empty());
|
||||||
BOOST_CHECK_EQUAL(ntState7.getMerkleHash(), hash0);
|
BOOST_CHECK_EQUAL(ntState7.getMerkleHash(), hash0);
|
||||||
BOOST_CHECK(ntState7.checkConsistency());
|
BOOST_CHECK(pclaimTrie->checkConsistency(hash0));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(basic_insertion_info_test)
|
BOOST_AUTO_TEST_CASE(basic_insertion_info_test)
|
||||||
|
@ -281,12 +281,14 @@ BOOST_AUTO_TEST_CASE(iteratetrie_test)
|
||||||
ctc.insertClaimIntoTrie("test", claimVal, true);
|
ctc.insertClaimIntoTrie("test", claimVal, true);
|
||||||
BOOST_CHECK(ctc.flush());
|
BOOST_CHECK(ctc.flush());
|
||||||
|
|
||||||
auto hit = pclaimTrie->find("");
|
CClaimTrieDataNode node;
|
||||||
BOOST_CHECK(hit);
|
BOOST_CHECK(pclaimTrie->find("", node));
|
||||||
BOOST_CHECK_EQUAL(hit.children().size(), 1U);
|
BOOST_CHECK_EQUAL(node.children.size(), 1U);
|
||||||
BOOST_CHECK(hit = pclaimTrie->find("test"));
|
BOOST_CHECK(pclaimTrie->find("test", node));
|
||||||
BOOST_CHECK_EQUAL(hit.children().size(), 0U);
|
BOOST_CHECK_EQUAL(node.children.size(), 0U);
|
||||||
BOOST_CHECK_EQUAL(hit.data().claims.size(), 1);
|
CClaimTrieData data;
|
||||||
|
BOOST_CHECK(pclaimTrie->find("test", data));
|
||||||
|
BOOST_CHECK_EQUAL(data.claims.size(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(trie_stays_consistent_test)
|
BOOST_AUTO_TEST_CASE(trie_stays_consistent_test)
|
||||||
|
@ -303,13 +305,13 @@ BOOST_AUTO_TEST_CASE(trie_stays_consistent_test)
|
||||||
BOOST_CHECK(cache.insertClaimIntoTrie(name, value, false));
|
BOOST_CHECK(cache.insertClaimIntoTrie(name, value, false));
|
||||||
|
|
||||||
cache.flush();
|
cache.flush();
|
||||||
BOOST_CHECK(cache.checkConsistency());
|
BOOST_CHECK(trie.checkConsistency(cache.getMerkleHash()));
|
||||||
|
|
||||||
for (auto& name: names) {
|
for (auto& name: names) {
|
||||||
CClaimValue temp;
|
CClaimValue temp;
|
||||||
BOOST_CHECK(cache.removeClaimFromTrie(name, COutPoint(), temp, false));
|
BOOST_CHECK(cache.removeClaimFromTrie(name, COutPoint(), temp, false));
|
||||||
cache.flush();
|
cache.flush();
|
||||||
BOOST_CHECK(cache.checkConsistency());
|
BOOST_CHECK(trie.checkConsistency(cache.getMerkleHash()));
|
||||||
}
|
}
|
||||||
BOOST_CHECK(trie.empty());
|
BOOST_CHECK(trie.empty());
|
||||||
}
|
}
|
||||||
|
@ -382,6 +384,7 @@ BOOST_AUTO_TEST_CASE(verify_basic_serialization)
|
||||||
ssData >> cv2;
|
ssData >> cv2;
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(cv, cv2);
|
BOOST_CHECK_EQUAL(cv, cv2);
|
||||||
|
BOOST_CHECK_EQUAL(cv.nEffectiveAmount, cv2.nEffectiveAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(claimtrienode_serialize_unserialize)
|
BOOST_AUTO_TEST_CASE(claimtrienode_serialize_unserialize)
|
||||||
|
|
|
@ -93,7 +93,8 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_normalization)
|
||||||
BOOST_CHECK(fixture.is_best_claim("normalizetest", tx1));
|
BOOST_CHECK(fixture.is_best_claim("normalizetest", tx1));
|
||||||
BOOST_CHECK(fixture.best_claim_effective_amount_equals("normalizetest", 3));
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("normalizetest", 3));
|
||||||
|
|
||||||
BOOST_CHECK(!pclaimTrie->find("normalizeTest"));
|
CClaimTrieData data;
|
||||||
|
BOOST_CHECK(!pclaimTrie->find("normalizeTest", data));
|
||||||
|
|
||||||
// Check equivalence of normalized claim names
|
// Check equivalence of normalized claim names
|
||||||
BOOST_CHECK(fixture.is_best_claim("normalizetest", tx1)); // collapsed tx2
|
BOOST_CHECK(fixture.is_best_claim("normalizetest", tx1)); // collapsed tx2
|
||||||
|
@ -222,7 +223,8 @@ BOOST_AUTO_TEST_CASE(claimtriecache_normalization)
|
||||||
BOOST_CHECK(!trieCache.spendClaim(name_normd, COutPoint(tx2.GetHash(), 0), currentHeight, amelieValidHeight));
|
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(trieCache.spendClaim(name_upper, COutPoint(tx2.GetHash(), 0), currentHeight, amelieValidHeight));
|
||||||
|
|
||||||
BOOST_CHECK(!pclaimTrie->find(name));
|
CClaimTrieData data;
|
||||||
|
BOOST_CHECK(!pclaimTrie->find(name, data));
|
||||||
BOOST_CHECK(trieCache.getInfoForName(name, nval1));
|
BOOST_CHECK(trieCache.getInfoForName(name, nval1));
|
||||||
BOOST_CHECK(trieCache.addClaim(name, COutPoint(tx1.GetHash(), 0), ClaimIdHash(tx1.GetHash(), 0), CAmount(2), currentHeight + 1));
|
BOOST_CHECK(trieCache.addClaim(name, COutPoint(tx1.GetHash(), 0), ClaimIdHash(tx1.GetHash(), 0), CAmount(2), currentHeight + 1));
|
||||||
BOOST_CHECK(trieCache.getInfoForName(name, nval1));
|
BOOST_CHECK(trieCache.getInfoForName(name, nval1));
|
||||||
|
@ -234,9 +236,8 @@ BOOST_AUTO_TEST_CASE(claimtriecache_normalization)
|
||||||
BOOST_CHECK(trieCache.incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverHeightUndo));
|
BOOST_CHECK(trieCache.incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverHeightUndo));
|
||||||
BOOST_CHECK(trieCache.shouldNormalize());
|
BOOST_CHECK(trieCache.shouldNormalize());
|
||||||
|
|
||||||
// we cannot use getXXXForName cause they will normalized name
|
CClaimTrieDataNode node;
|
||||||
for (auto it = pclaimTrie->cbegin(); it != pclaimTrie->cend(); ++it)
|
BOOST_CHECK(!pclaimTrie->find(name, node));
|
||||||
BOOST_CHECK(it.key() != name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(undo_normalization_does_not_kill_claim_order)
|
BOOST_AUTO_TEST_CASE(undo_normalization_does_not_kill_claim_order)
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include <rpc/register.h>
|
#include <rpc/register.h>
|
||||||
#include <script/sigcache.h>
|
#include <script/sigcache.h>
|
||||||
|
|
||||||
#include "claimtrie.h"
|
#include <claimtrie.h>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
#include <boost/test/unit_test_parameters.hpp>
|
#include <boost/test/unit_test_parameters.hpp>
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
|
||||||
pblocktree.reset(new CBlockTreeDB(1 << 20, true));
|
pblocktree.reset(new CBlockTreeDB(1 << 20, true));
|
||||||
pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true));
|
pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true));
|
||||||
pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get()));
|
pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get()));
|
||||||
pclaimTrie = new CClaimTrie(true, false, 1);
|
pclaimTrie = new CClaimTrieHashFork(true, false, 1);
|
||||||
if (!LoadGenesisBlock(chainparams)) {
|
if (!LoadGenesisBlock(chainparams)) {
|
||||||
throw std::runtime_error("LoadGenesisBlock failed.");
|
throw std::runtime_error("LoadGenesisBlock failed.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ struct CDiskTxPos;
|
||||||
//! No need to periodic flush if at least this much space still available.
|
//! No need to periodic flush if at least this much space still available.
|
||||||
static constexpr int MAX_BLOCK_COINSDB_USAGE = 10;
|
static constexpr int MAX_BLOCK_COINSDB_USAGE = 10;
|
||||||
//! -dbcache default (MiB)
|
//! -dbcache default (MiB)
|
||||||
static const int64_t nDefaultDbCache = 560;
|
static const int64_t nDefaultDbCache = 500;
|
||||||
//! -dbbatchsize default (bytes)
|
//! -dbbatchsize default (bytes)
|
||||||
static const int64_t nDefaultDbBatchSize = 16 << 20;
|
static const int64_t nDefaultDbBatchSize = 16 << 20;
|
||||||
//! max. -dbcache (MiB)
|
//! max. -dbcache (MiB)
|
||||||
|
@ -34,13 +34,13 @@ static const int64_t nMaxDbCache = sizeof(void*) > 4 ? 16384 : 1024;
|
||||||
//! min. -dbcache (MiB)
|
//! min. -dbcache (MiB)
|
||||||
static const int64_t nMinDbCache = 4;
|
static const int64_t nMinDbCache = 4;
|
||||||
//! Max memory allocated to block tree DB specific cache, if no -txindex (MiB)
|
//! 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)
|
//! 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
|
// 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
|
// a meaningful difference: https://github.com/bitcoin/bitcoin/pull/8273#issuecomment-229601991
|
||||||
static const int64_t nMaxTxIndexCache = 1024;
|
static const int64_t nMaxTxIndexCache = 1024;
|
||||||
//! Max memory allocated to coin DB specific cache (MiB)
|
//! 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/) */
|
/** CCoinsView backed by the coin database (chainstate/) */
|
||||||
class CCoinsViewDB final : public CCoinsView
|
class CCoinsViewDB final : public CCoinsView
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
set -e
|
set -e
|
||||||
srcdir="$(dirname $0)"
|
srcdir="$(dirname $0)"
|
||||||
cd "$srcdir"
|
cd "$srcdir"
|
||||||
if [ -z ${LIBTOOLIZE} ] && GLIBTOOLIZE="$(which glibtoolize 2>/dev/null)"; then
|
if [ -z ${LIBTOOLIZE} ] && GLIBTOOLIZE="`which glibtoolize 2>/dev/null`"; then
|
||||||
LIBTOOLIZE="${GLIBTOOLIZE}"
|
LIBTOOLIZE="${GLIBTOOLIZE}"
|
||||||
export LIBTOOLIZE
|
export LIBTOOLIZE
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -1562,8 +1562,12 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI
|
||||||
assert(trieCache.finalizeDecrement(blockUndo.takeoverHeightUndo));
|
assert(trieCache.finalizeDecrement(blockUndo.takeoverHeightUndo));
|
||||||
auto merkleHash = trieCache.getMerkleHash();
|
auto merkleHash = trieCache.getMerkleHash();
|
||||||
if (merkleHash != pindex->pprev->hashClaimTrie) {
|
if (merkleHash != pindex->pprev->hashClaimTrie) {
|
||||||
if (!trieCache.empty())
|
for (auto cit = trieCache.begin(); cit != trieCache.end(); ++cit) {
|
||||||
trieCache.dumpToLog(trieCache.find({}));
|
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);
|
LogPrintf("Hash comparison failure at block %d\n", pindex->nHeight);
|
||||||
assert(merkleHash == pindex->pprev->hashClaimTrie);
|
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.getMerkleHash() != block.hashClaimTrie)
|
||||||
{
|
{
|
||||||
if (!trieCache.empty()) // we could run checkConsistency here, but it would take a while
|
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 "
|
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(),
|
"(actual=%s vs block=%s on height=%d)", trieCache.getMerkleHash().GetHex(),
|
||||||
block.hashClaimTrie.GetHex(), pindex->nHeight), REJECT_INVALID, "bad-claim-merkle-hash");
|
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.
|
// overwrite one. Still, use a conservative safety factor of 2.
|
||||||
if (!CheckDiskSpace(48 * 2 * 2 * pcoinsTip->GetCacheSize()))
|
if (!CheckDiskSpace(48 * 2 * 2 * pcoinsTip->GetCacheSize()))
|
||||||
return state.Error("out of disk space");
|
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");
|
return state.Error("Failed to write to claim trie database");
|
||||||
// Flush the chainstate (which may refer to block index entries).
|
// Flush the chainstate (which may refer to block index entries).
|
||||||
if (!pcoinsTip->Flush())
|
if (!pcoinsTip->Flush())
|
||||||
|
@ -2772,15 +2776,13 @@ bool CChainState::ActivateBestChain(CValidationState &state, const CChainParams&
|
||||||
if (ShutdownRequested())
|
if (ShutdownRequested())
|
||||||
break;
|
break;
|
||||||
} while (pindexNewTip != pindexMostWork);
|
} while (pindexNewTip != pindexMostWork);
|
||||||
|
CheckBlockIndex(chainparams.GetConsensus());
|
||||||
auto& consensus = chainparams.GetConsensus();
|
|
||||||
CheckBlockIndex(consensus);
|
|
||||||
|
|
||||||
auto flushMode = FlushStateMode::PERIODIC;
|
auto flushMode = FlushStateMode::PERIODIC;
|
||||||
if (pindexNewTip && chainparams.NetworkIDString() != CBaseChainParams::REGTEST
|
if (pindexNewTip && pindexNewTip->nTime + chainparams.GetConsensus().nPowTargetSpacing > GetAdjustedTime()) {
|
||||||
&& pindexNewTip->nTime + consensus.nPowTargetSpacing > GetAdjustedTime()) {
|
|
||||||
// trying to ensure that we flush to disk after new blocks when we're caught up to the chain
|
// 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
|
// 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;
|
flushMode = FlushStateMode::ALWAYS;
|
||||||
}
|
}
|
||||||
return FlushStateToDisk(chainparams, state, flushMode);
|
return FlushStateToDisk(chainparams, state, flushMode);
|
||||||
|
|
|
@ -57,7 +57,7 @@ static const bool DEFAULT_WHITELISTFORCERELAY = true;
|
||||||
/** Default for -minrelaytxfee, minimum relay fee for transactions */
|
/** Default for -minrelaytxfee, minimum relay fee for transactions */
|
||||||
static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = 1000;
|
static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = 1000;
|
||||||
//! -maxtxfee default
|
//! -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
|
//! Discourage users to set fees higher than this amount (in satoshis) per kB
|
||||||
static const CAmount HIGH_TX_FEE_PER_KB = 0.01 * COIN;
|
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)
|
//! -maxtxfee will warn if called with a higher fee than this amount (in satoshis)
|
||||||
|
|
|
@ -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);
|
dbenv->txn_checkpoint(0, 0, 0);
|
||||||
if (fMockDb || !lsnReset)
|
if (fMockDb)
|
||||||
return;
|
return;
|
||||||
dbenv->lsn_reset(strFile.c_str(), 0);
|
dbenv->lsn_reset(strFile.c_str(), 0);
|
||||||
}
|
}
|
||||||
|
@ -799,7 +799,7 @@ bool BerkeleyBatch::PeriodicFlush(BerkeleyDatabase& database)
|
||||||
|
|
||||||
// Flush wallet file so it's self contained
|
// Flush wallet file so it's self contained
|
||||||
env->CloseDb(strFile);
|
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++);
|
env->mapFileUseCount.erase(mi++);
|
||||||
LogPrint(BCLog::DB, "Flushed %s %dms\n", strFile, GetTimeMillis() - nStart);
|
LogPrint(BCLog::DB, "Flushed %s %dms\n", strFile, GetTimeMillis() - nStart);
|
||||||
|
|
|
@ -83,7 +83,7 @@ public:
|
||||||
bool Open(bool retry);
|
bool Open(bool retry);
|
||||||
void Close();
|
void Close();
|
||||||
void Flush(bool fShutdown);
|
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 CloseDb(const std::string& strFile);
|
||||||
void ReloadDbEnv();
|
void ReloadDbEnv();
|
||||||
|
|
|
@ -15,5 +15,5 @@ RPCAUTH=@abs_top_srcdir@/share/rpcauth/rpcauth.py
|
||||||
# Which components are enabled. These are commented out by `configure` if they were disabled when running config.
|
# Which components are enabled. These are commented out by `configure` if they were disabled when running config.
|
||||||
@ENABLE_WALLET_TRUE@ENABLE_WALLET=true
|
@ENABLE_WALLET_TRUE@ENABLE_WALLET=true
|
||||||
@BUILD_BITCOIN_UTILS_TRUE@ENABLE_UTILS=true
|
@BUILD_BITCOIN_UTILS_TRUE@ENABLE_UTILS=true
|
||||||
@BUILD_BITCOIND_TRUE@ENABLE_BITCOIND=true
|
@BUILD_BITCOIND_TRUE@ENABLE_LBRYCRDD=true
|
||||||
@ENABLE_ZMQ_TRUE@ENABLE_ZMQ=true
|
@ENABLE_ZMQ_TRUE@ENABLE_ZMQ=true
|
||||||
|
|
|
@ -1,117 +1,117 @@
|
||||||
{
|
{
|
||||||
"blocks": [
|
"blocks": [
|
||||||
"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff7f20020000000101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000",
|
"010000000000000000000000000000000000000000000000000000000000000000000000cc59e59ff97ac092b55e423aa5495151ed6fb80570a5bb78cd5bd1c3821c21b8010000000000000000000000000000000000000000000000000000000000000033193156ffff7f20010000000101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff1f04ffff001d010417696e736572742074696d657374616d7020737472696e67ffffffff01000004bfc91b8e001976a914345991dbf57bfb014b87006acdfafbfc5fe8292f88ac00000000",
|
||||||
"0000002006226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f1cd16b94f20a8a3dda91027c888025f2ec1a07ddcb2786bdff5916e66c00406f194ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03510101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000205675686976674f50a0a1953d172e9ecf4a4a621dc9a4c3795decd49912cf3f6e9c2646796e96a45b91dd9199a449736bd9a78880936306be5f125a7ebcbc69e4010000000000000000000000000000000000000000000000000000000000000045298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03510101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"0000002014341131c18d3b3aa30056a0f7a97c9ac852d3fd0ec9c76f7a25e83c01e7f821bf83574fb606f25c59200c844443201faf923ef5284fd4401f3104a323c601491a4ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03520101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"0000002062b18e4b01940481bc4d3dc3d49851177ae06fbb651e9027f35acb15046499556f9c965b9b8c109db568d32d7d3a0dd7ee4d132490f42b51f4ba2652fec7bd1b010000000000000000000000000000000000000000000000000000000000000046298e5dffff7f20050000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03520101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"0000002078616da95299bd42cd8f813c8043816ec5741de466be3162e16bfff471808461f671e694afaf534d37df484f1990fc19a65fc26964b38141b7f8ecf61b8a50241a4ae75affff7f200500000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03530101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020206689482dff24cf7b740fec087fded521465ab6e902d44b9edd81fcbed205189bef9d4d146ce1baddb2e321b6cd48c7ff10d1a9c24c6860f195710575a2168f010000000000000000000000000000000000000000000000000000000000000046298e5dffff7f20040000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03530101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020a08613f37d305835a3a1553e77a479eba0f34c06c52e429ece54f5973cd77a7086a1efcaf75f1cd5be2c9deb6a7850225757a2cfc3031a91cc1330b3af4acc891b4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03540101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020af6bafcae32d53ed80d5ebc76ff7f8f6ae33ee1e1d111f1581cc6999242035d4b06a8e0c34b018cf12ce80647162741e7151d6a64af60e8d93e4642510d320e8010000000000000000000000000000000000000000000000000000000000000047298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03540101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000203b304fa1ce0505c2366982939ac148d9124c5ac747cc9aea133cea9916484966305de0e8d049f2be65c68d64d2c45746def5a9b4fcb8e298692b53b83b4690241b4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03550101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020917411a2c128c8d514268810af750a485ca175000082b6925beb4217168de79d2bec9aeb4b9ecbd4205a11951a4939402524dd8e9d8f982d4f12d01b300af7de010000000000000000000000000000000000000000000000000000000000000047298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03550101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020fbdf49978ec4f0b23704b6772a614336872587e29c463f375836ffd775248837fed9f3fdfc33f076c6663ae78070fad7263c1e24161f3ee1a4857b8931815e2c1b4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03560101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020e8881b5ca1d771630f7a16590c05a269f3fde4d548b21c056105aaab827dd7bff4e300719036df10ebb927cbd6b5005003807a71427b8a8a433597a14743b3d2010000000000000000000000000000000000000000000000000000000000000047298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03560101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020c37548b9ca256b9ff17187d4d4309cf3143845b0a5811d3ca5427b2fddf000731a10985dfd473561c070c3527c3fe3941834cf51b3dfbacb501b44c69c9745ce1b4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03570101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020cd187a1c21cc697ea2a8b12767900ade0c50537666e2d9f0612cb568b2809cd205477c5c00c155eadd3f24a662b9ce3d45e94714fa6680514e84ce81dbae641b010000000000000000000000000000000000000000000000000000000000000047298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03570101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020383dd3766c0675440f26370ad62d687e335ea3a650dec9b02fe544107cc1823a13b98696d41562945457d655f4c6921f736068f7a72afd1ad6b335f2857d16631c4ae75affff7f200400000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03580101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"0000002046925fe8d280c0ed84269e7d2f6fc75e0989f5b12a8329c9d3750b204af1e231cde3845b2f0b31b6adb93e0e3a0a4546010a9f70d9edd2d3945b44ddfd1f3286010000000000000000000000000000000000000000000000000000000000000048298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03580101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000207476dd96d81f53e63934ce28c9e89022e0f24d040ec3c838443e925fc3a2f230a94d0cbcefb4a151191dd7664153944d9eee3b7b46d4ba997f397ed2b72c3afe1c4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03590101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000200fa35702ea19e64830a09274eeaa84376257865960d42ef686c7ee036aef79ab9eadc578fb13d50e5f392884a1c2b5d5558bed09dbd573af82f3a3b2203918fe010000000000000000000000000000000000000000000000000000000000000048298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03590101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000209e425c73eea16cce98c0d47d6070aca29f0524eab4b97af84c386aa5322dd43055002f097e929bc6ad88ce869968e1b049aab7f6e45a5b869cf4349afd5d43e01c4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035a0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"0000002078a772ace3aaa0ee543c1e039c0fb298f57cfaca055f53410fcabc7d593c6c87bbdeae34c9cb3617bc38e3ab0a43ffeb37c06b1d624d2e50d2f843c5f08fa507010000000000000000000000000000000000000000000000000000000000000048298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff035a0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000202090e16a514fad40386413a100bbaa4fc14086a8d3501ac64c91fdef922e834a369e409444d0ec496eb0dd9a47f1fe81a7ab974bab28c50a912b994acf13b5f91c4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035b0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"0000002021307a96ba4a365dfbe87c8c99ba8c43bd89cc4092310bcec9ea6eadca718a35731fa75a0f07302b163ad8f680b8d557dfd0acf18280b4ebbc41e5e8515923fb010000000000000000000000000000000000000000000000000000000000000048298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff035b0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020777b767e42624c52775b331f19e81ba03be2f51a0608166cd5388c1a47d5e776473570bb9bba553a7db4a9a3083533027c54af1fea3ef6ef67757ef2255d64631c4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035c0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000208520fad5219fe882f6f0e5742d64624687a2fd5f1f4dced164594e8c51e886468757b56faabb2905c5c264ec6303e5df726e7448efb30e662c5eab6e4c19f5cd010000000000000000000000000000000000000000000000000000000000000048298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff035c0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"0000002076bb2bf3251a51ec367a42f8584043171a5d53157394cd776ebd017e2982127653d953aca3e2217f56533c043c07b9a926a30672ebce2562f1d06a6dc5044e7b1c4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035d0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020b6cae7e19f4ac24957a8f932b1da05d9abceec8875dfccec7c2b4d8af9f8d510140d54e8dbd0ea528aad963ea5a4036f7b050d8cea603b706e36bd9f6e601e6f010000000000000000000000000000000000000000000000000000000000000048298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff035d0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020e6d7f02292655b73fc1f1958b09633ba07265d71d2a2784060b354cbbf1900202e9c9b02b63170002a94a0c9d8d787e2faa4c074a1ebdeb2855555347321dd101d4ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035e0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020f5e9391e41591c52889ad5e1bac5be8cb2c632592f13b039fa8f15dbe80083b9cf1a5a45904bda75bc081d78d370776f4a2d2bbe03dfe54e12cc26c6ab52b9cd010000000000000000000000000000000000000000000000000000000000000049298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff035e0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020d61f077b0ed326e17f0a3d5af3fa876b72b434a252c9c3248d20130ed744287fcb10da470222dd29c7a07e2da7eb25d6499ed3919676df89cc630bd1b23fbb411d4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035f0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020ca24db3b830fadbd52dce722453f40433b3bd373a7b146603c489b8ec8eaf76a709f5659d1242f71629dc7b46dd2328add4f12672c3e4a0a6c002f9d220ef58f010000000000000000000000000000000000000000000000000000000000000049298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff035f0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000205efa9741cf51533ed6e07a97c71768372f53ca9c6df83894d64fe94c718eee23a207441e79ecdcf99ef3326385f5f675e2dea84c85ab8973219c63f92847ed5b1d4ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03600101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"0000002037920b818e2deb397ae1b6816e95c846af08dbffb9917c026c9004dd5bbb750d037207bdebdb719af94d699ed8b7f8443e0e49ee2857fa4d01c782cd6411e18f010000000000000000000000000000000000000000000000000000000000000049298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03600101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020368386b0a0f46b2a2c4648eb9cb5dd1380c4f22e437e0bd49420670993361e5b9026632c2ddbb4b31b3c3118c51e43ea4d78e05c0aca0956278ead26a263d1521d4ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401110101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020418ba5059965888fc5b34bc4f454da675e14b87c4e5936004e2be27ab1c754b1bfde5825b014d9b49397ea4a74800a7bc070ba26aaebb0fd39cc4aea79678290010000000000000000000000000000000000000000000000000000000000000049298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401110101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020dd0a1594bbff6345a3e34f326e5ee605c855f5e0a5c363fc39615a8b1539b736200b51297dbee4aadf9b536cd2afe7617651e0a1d0f0610f436518a2a4dc54621d4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401120101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020b87c7b459c40c17e1767f2823772eedacd36dcbe923dbdb50a93d5a8c714c35bf50ca0b9ecbd902f0e51d28841871c5cee712f91dd8791c620bd223bdf0e6a33010000000000000000000000000000000000000000000000000000000000000049298e5dffff7f20040000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401120101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020f302a1092709dc27a32d7229d391b90824a75828692c4bb2ca8f0ca5c88b3613c2e18797ffe8b367336338f90b2cf8c3f66277eb1e1ddbe18c052977294f10691d4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401130101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020c41716369b5eb60c987548f45fc79a1e0d92b32731e8652366ad884fad383a809e07104556faa0d9f6e4d7611d5868f7e7d46b302de2b0e45b322a487bf6c70c010000000000000000000000000000000000000000000000000000000000000049298e5dffff7f20040000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401130101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000203dcc77aac703a8cd0e799384b74383c1d5f236426f77d516694607fc88fe85581276a20ceb98d02e6355c9dba4312e2fdc9832f4302cc307e1263f2df0aadd6a1e4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401140101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020684b238cbf19d1f77054be44701353eb7d4d8ebf56432a5e0b37cfc4b986e45b17549e75a37864a74ed7c3617e2f620da9c5c736762eb73b66bedf7bf79ddb2301000000000000000000000000000000000000000000000000000000000000004a298e5dffff7f20040000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401140101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020dfe109704a0b2801aee4232c31fb744145a7c80dd91a7727e16d4057719d5c3730f8296243521d82d96ed75c5af800a722fc9dde2e02af95c8c9822190ba07b21e4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401150101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020b6ef5783f5c123e87b11cb186ceb1d4cc7c3290e8e12165f1bfad7577b486c184eead20e1914c8090d7bab52dc4a92ae58ff97a029b6c075f1ca4abc30d6df4f01000000000000000000000000000000000000000000000000000000000000004a298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401150101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000201ef9ef2699bc36fd646bb9ba8629644bc98396122f6753710caf0315d7539f751382d3d85f17eb8b42cf17e54baa327886dcf6fa63207e097df8f9b84cc5422f1e4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401160101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"0000002096a670e039d621b147c4c68b8ece1d442502aa1b3389896e0a2c9ee24092bb2e155c431d467db173e369a59198b2bc50a16185f914306c3e032f42b24454440001000000000000000000000000000000000000000000000000000000000000004a298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401160101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020834c91f23cd91b727be08b892f1c1a2f33c1e66d66f35607925fa1be4bca2c25b4145a73b1c71b945f5bb9ede3d8d95c9a3b12a0a81b7b14f440ec5146dd4ec71e4ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401170101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020fde40a0ddb45461a36120b2300fb19ad701b93eaa2d99f8d7da85101fd80c5efc6455c8ecceb8d07485a799ea260e635528d863e36573023f9c1e2a3e8de2b7601000000000000000000000000000000000000000000000000000000000000004a298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401170101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000205743202bf1e543a9be2a59b62be6a5a494511fab96968007b8d7199ea60a524697227ba473ceaf48d4f48ee17f8ee6cd2f1f5ddff03a641642ece240e7872f8f1e4ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401180101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000207d4488c7932c51ab2f922f010ceb3df5b4dec027862e57b8c244d42f5534c6c38e2190ef4d9186ca5ab6dac103432302c481be9769b9cf9fa096868e77a3764101000000000000000000000000000000000000000000000000000000000000004a298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401180101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000207469f5c1841bf57275d82db23e5a8f0e8512af1eb10119c238519cdd6cdced34fd96dc659a874b3f5d30fbe6ea421a6b9791dfce8450f8851e4b90d80f0f794e1e4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401190101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020896b06cf7936eba3ca7d79470bcc2c290a1b15a3de06d1cd73b10a106b27f8fb49b54d8e2162871dc1c295f5163ad3df67d4a7a5cd43c800094ef1cb1e8a1b9d01000000000000000000000000000000000000000000000000000000000000004a298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401190101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020b6338f55fcc473b744d53d675b4a83dcd80ddec9d02ad3323cf1ff50ac0412239d986ec20885d772fdc67803273aaec43871426ac93d3815846a8cd13dea5af11f4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011a0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020be9003ce95f64c98bf870555b9263304c546079dd3614a599cf07fb4776af3aa2e8cd162f0ae28e7a4fb10f173e44f80f1fafe36e35dc5a4a9b33bb7629e04b101000000000000000000000000000000000000000000000000000000000000004b298e5dffff7f20050000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04011a0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020a19d9edf2d22415cf226b4e1416c8a3097e0af222efac2bfeab15fa1f07b3f24c18580c4004de6d6244a30ce431c4be3ca44731509fc6b11710c792efed5e9191f4ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011b0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000205d826c945361bd5283024395ba3f07bc3ec107bc79407d8ae6891e08848dad96e30e56c9ab0ad1e6107d3f95b88004128a732f2589e2f2ccaef41c886b07abf001000000000000000000000000000000000000000000000000000000000000004b298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04011b0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000208f9f29a27424ec01ce77485617088506ca8faeef69300f0a474ad63ca5d32972d6049609fa3588d6ffab4d9d89a90636ac94c0ca1995f7768163abeb25dbf2bc1f4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011c0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020fb80b3a74bf9f8446419e32d172725c2edfd755283cad14f16c9fd8e0db8f63a8165ffe9fb63399644d6a3465b84972eba11a560ac2bb327f350b8c859beb63901000000000000000000000000000000000000000000000000000000000000004b298e5dffff7f20020000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04011c0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020fbd87d530a9ec3835ab579337fd16e512cec6c4779ab4d84e7256b3333dece28de1065c8c3d3d166e057139ac59af6f4f2c0d241b6269bbea6f61c5eff3dba431f4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011d0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"0000002026aafd727bc33bebb8c9d4c5c231edc6ad7f1b120416f6eec899345137155287da9b8b939a2e0dae1fdc57e8f051b847a898bf372632e47aa906852a445a24bc01000000000000000000000000000000000000000000000000000000000000004b298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04011d0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020dc6ef4f436baab2d6880f242a2588313a2739ac694e30319344045ee318c9524d0ec7fbcaca30ce85392cb03b64015ece769afb50fd07db05c15ec49abf7d71c1f4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011e0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020eff266f8410f99391deffa0f2fbffcc2ef8224ba82d2f990711a28538c537e0094f83b6c8fada8283220abceb95e2180473f068ff096264a8f2bad31863152eb01000000000000000000000000000000000000000000000000000000000000004b298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04011e0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020386bf4cbb3708ae6345b9f2459bdd99d07422b05f9b005d2d4d1d3bf87d47359ebb22b3a15c8e94ddd8129527873b9bebfa10c54d11196961376efbcaad3c4681f4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011f0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020ba106ca41ee82bbb2bc6d0fe05d495dcc62a0e23c9519edd4b2d7ec12a08d8510db06e473aec2b882def52f084b4b0d9f6265d47780c15abd54827df6c62fea601000000000000000000000000000000000000000000000000000000000000004b298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04011f0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020600e892f12ad82a23ce12684d3ffa0887eab5e3e97804fa651050b23366cc55ef2468e65c3d3cf49650657eb47d0b0b7949c71dcc0922eb824523157b7eff478204ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401200101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020043eb2d4b22b694311bb7489d61bf58b66bc278ea260a48f834c2d4032e32bb311976be9aaf30c1d8d6a9723d210adce2b625c0a29947cd14953410e00642f7a01000000000000000000000000000000000000000000000000000000000000004c298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401200101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"0000002068e4aec52a3f4e44279e3a65cd476237bdfcc2328390bb31b8a903f89ddfa70e8d669f61b469acb31b1d4ecdc238e6616a83a30644a5d06fc2ca1aad6449d09b204ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401210101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000207a1bce01ae3d23f10eb96c919d69bece9764584690aa62ac5e529f5b11e39c8a77679b50d559cbaac0040176e82355231529ac2f48de1d5983bc9366d4a1fb3c01000000000000000000000000000000000000000000000000000000000000004c298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401210101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020cf2428ae9a5014b910275807f54a8bbbeec47d462f9d284ada60329b4955ff10cf83c44ddde39a709aef54fb302c7f1cb36db8fe7c3befce20dcc3729767518c204ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401220101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000209afb1c2dbdb163ae0a769e6b0f45ce0a6120ae93e8b0cd9c3c324e680c368d0ceabbb0033eedd8bfe159ba57d523ece2b9d4e86c1754b09fca80e78890744a3201000000000000000000000000000000000000000000000000000000000000004c298e5dffff7f20040000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401220101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000205801eef8cca082407ce4798648c4d3ba0fc4dd2d4459eccfe5300c7960760d16cb3dd78a2f22fb88717a175e45c53d34f970b94ef9f7cd1b6c279294d427d163204ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401230101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020139aab4d7175fcabb17a76c6660a2484d596a1a87b8794863aaa403015e794e9bda24098c56906da7fa1d0f104f3731e5d9ac14886148c7dcf728a562051dd0f01000000000000000000000000000000000000000000000000000000000000004c298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401230101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"0000002088320983a4bcb95b9f342994c6943c227f3102d3b16282f048ceb8e15748662a52d1207591a0a364bc9245a76e36530f147ec4d1b4e1917676b4071f542c3b19204ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401240101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020433a8cf135270470d6bbd5c66751d8b343a26bf2e215b77b4840c07f8c2edb80f2e3a01d0db6fa8565e780e15d7650ca3913e9dc0a362bce208b69eee8778c6e01000000000000000000000000000000000000000000000000000000000000004c298e5dffff7f20020000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401240101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020acd85b6d8087d3b6bd2a208a2e39b75da459c0e0eb14088075a23a2e043e8a4ed5a1754491f8180d293b42e6c04ec3f82e29c1f2600dc8607616f69a4a464e6e204ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401250101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"0000002058df283f1cab9904c9d31ea0c69ddcf0bbaf9059ef94303fa03e7aff67f90b656f4c2c390587d278e29453a773dda990246265d181a64b4f8de5f87e0b2d72d601000000000000000000000000000000000000000000000000000000000000004c298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401250101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000204873bcb379f78da4497ce1e22f6bfb63537b89c8c522257a7b7bef74e515ed1b6b235faab048fa73a76c68fdbdde6a4ee7ebe0a3b7b23df24ce75dbd2cf49c33214ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401260101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020474409f36e71c4ae8aa34e5cf5e30edb96444afffccdc0adaeda4a5b33ac0edcc757ff2a006fa36785373524813efc635e42a8a6ffd7b30d87d7d45aab6473f101000000000000000000000000000000000000000000000000000000000000004d298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401260101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020a87f6d13bae8e2e07996c3316e8e0da6aec7d1aee6b80aa5883018e4d136db3e9a498ff7d322ad93863e0a5318af7e7d0ed683fd2e4ecf523f2b7369106dbe4a214ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401270101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020b2a45ac6975c714b53f173477bd4d7abed2e131f6d1d0f36228a59d278a0803a362739c353a03108aabda333039e417365c29271b4fed1577ca88300a0f903e801000000000000000000000000000000000000000000000000000000000000004d298e5dffff7f20050000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401270101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020d9b0618450a51c08f43187c479e20d351f0466464409bb3071dc0af7c51d65498a198cef23dddd2c4b93d9d3288ae922584e221a9ef1ded3dba5a2ad494d9237214ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401280101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020a2eb5532ba64f5b4980217cc53abc0122133b67da0cd15e27620296175b6773110d335e63a14d0c7f87360044640b2430f36d56dfdb51faa03a78f7b0682bebe01000000000000000000000000000000000000000000000000000000000000004d298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401280101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020167dff31847b8dcad472bb6bb7d0af53b245f0f1d4c9f83d4ce14a0f05d42d7f0f2638ffc0e6896230f28df1865ef133dccb1f027545c6a1177dffd1fecf8a01214ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401290101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020703c37af817a6d6a5d4ea28eb8273dd039d3e5aad463d2079f7311e9f7ec0270d733d311164ef0c13d63fdc6ae1859a1212c77f6b99bc232502ab0f6e9c2463601000000000000000000000000000000000000000000000000000000000000004d298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401290101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000208236c04424573692504e777e179b9247e54622b118239311413812f13cefbf6e39a639143f599dc76208b2014de12a364716df2918af9186453e3676dca743d7214ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012a0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000207016a47fdb3ad2dfa1f5dfb4d325d7397b48d773aa84e89e0e4fd1c86d1963867b121f48a0be5dff0406e4e5e3b84c9b9502f43610114a6937c12e4eba142e3401000000000000000000000000000000000000000000000000000000000000004d298e5dffff7f20020000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04012a0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020fab7b55aeb59f63315dbc10784c55e55635a7600cc4f3b94a00003007e7fc90b4af016248e9908882f8a7f0bd8743c8da82da119446e8b02e4d3b8d1d938a3aa214ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012b0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020f17810d1cc695dfad2789149c9b21c90ed4f2a2663b33a9c1154763bf599601dad47e87a7bbaf33cc004e13f7a0722acc62755a69a666c24da7ba1f838e11a9701000000000000000000000000000000000000000000000000000000000000004d298e5dffff7f20020000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04012b0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020794b4160d8fd4ebe7611d0fc9d3e04f3038a485669f74075aa153852ed181121c577f4c0b7151f6d78a16e3c21ab291b53ced8a5c4f05a22caf24a25ed029d56224ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012c0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"0000002047e742da0f3d882548e333c5de9ba5c1e89c366b53de17e95f2126089b473f8d9927f26f88eec45759dc6d1f5a310b303a3dd7d113e1c7732a472a3163bb2d3601000000000000000000000000000000000000000000000000000000000000004e298e5dffff7f20020000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04012c0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000204a8acdb549d2ed922360ae0e81de6c913c3fd84b0de51abacbf97162a99f7c26c656b252d3259c33ffc7e5d403843accc6ace9b7e60e911e2347a6a0b0abd122224ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012d0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020b74842271729497e94c33429c6e21ebfc46c82f587fbfaa91bf30a7fa1df77197c65d2b6735b85a3718befcf7a789df26bfaf929b32eec42594c94862fec6d7f01000000000000000000000000000000000000000000000000000000000000004e298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04012d0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020dee6d00c7058b3422e4273c98c16181e04ea93116496a8442de546c2ee9fd86b550013f39e004b3829dc3717b17fcfedc87de9450315fcca540963119cb264c1224ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012e0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020a3291c68b92c19bf503e3a48f89b3d85923d8d23791b3b77b541224be114da6f052f7b4a4a72a178fc26adf081cb28494d2e2386f42cb8fd3db9ff2da5f8a22e01000000000000000000000000000000000000000000000000000000000000004e298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04012e0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000202ebca471f5fb2226a790233c3d0bc323f73d935872f3e15b66bd5fdcb822101d7b68788ed61d3fb8cb746f627e09db2fc09d8a07672747709d92ae400e053e78224ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012f0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020b84c9aedee6173c6926b37c5c451fc0a9ae1bcf23508ac4de8b790befc65216665f48aa0f54655f985e9f1e3a5a58683d40b523ef430aae8593734171a204e9d01000000000000000000000000000000000000000000000000000000000000004e298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04012f0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020ee500470fc1c71a82f2cbb9f8d5723bcdf57b8051fc458a8dbd8d0dbf60d0e40d1a0be0e50f3312d4830e3900186e5a6760d44006c164b4f0758218ef2b2de8e224ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401300101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020bd7b9820463851223f9543192c338fd3701c7998c823086951df721335665eb2d2d152c34514ff98c551509347d4415e8f7aff1f3639be677df20d03557ee9f101000000000000000000000000000000000000000000000000000000000000004e298e5dffff7f20020000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401300101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000205057e8d8a7451d79325851dc8e0f4dfdb1dfaaab637509d9e61f0e064af5ee5c185221c53c0cf43261b3c238c0e8117da5d6ac60085615f7a3d8027726cb2143224ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401310101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020a4f6ad65c748ab035e3d520f6c33ba047d28bdfdb6e5a0a4015a5a3a9e0f4ba0f79d7ae2f66ff289ff6b8f4ce435152f382d6d54285528b422a3d0c94ea9483701000000000000000000000000000000000000000000000000000000000000004e298e5dffff7f20030000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401310101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000200907f01d9c5c872296796ca77feb62eb414cc080e13a93e59e181528bc19c336eaabacb1ebcbd20b26f6bacdc712ffe17d4c8131e7f99b9cac309c0683737c04234ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401320101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020fa467509059c29bc043e527bd38ca2620dc441145deed28a9d7865a7417ac5b8428f2c186fa501cc53f1e91972e0fb9ba8bc6ae7daebb54784cdeb21c5076c0d01000000000000000000000000000000000000000000000000000000000000004f298e5dffff7f20020000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401320101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000209bd6a4ec962d9e6199c0a2f39481a7ecc322fedbd2320cbe7dc984c6ab958421fe7a5c7f2513a3c3de9ddf7b211f5bfe85675b31183c4bb98ae79ab28cd055ac234ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401330101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000205dc60a8d80efe426d3dfcd8a5741499f9f7a0bebf5f9da39e6887d13a84690429f2c8e7a35b50bc86245a4250b3e3ce74d1ca128bb11ddf7da9fde9ca0f0c40101000000000000000000000000000000000000000000000000000000000000004f298e5dffff7f20050000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401330101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000202b8a6381b7c9476fd77be379a929863db6b7edd9858d6eca0f68a430dc87cc3a9c6c8b34bfadfdacbe95cb1d4ae5ce4e4f4ccf0300171d7a91cdc97f620c7b37234ae75affff7f200400000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401340101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020ea09bbbdbb30103822f451568802e25341ead64a0538c529f8e3159d3f3162f57b7460f7b6ab41416b590f664473e0887b148f4482ab1842cdbcbfce807bd69201000000000000000000000000000000000000000000000000000000000000004f298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401340101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000203d3e9a0b4decf12b4402a2178b60599311c8a9c7d50ece365a61ca29530da7056754ddf7d77a11cc8ce680a74fae01d851bda024fc9c51712c55b4a190caef24234ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401350101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020d8dd90f93424b2fbbd10ef671d14edf5ea4727ab4e574126b9f7dab2a3ba17ac7a5412415fa65b28385e15f30c50202101d26aec4360f967e8449b15fc230c0e01000000000000000000000000000000000000000000000000000000000000004f298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401350101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"0000002067fa05082d4f7a29a3985f30798940cd854c76a2b20e9560b2047f7753193f71ac61b8df17a8a63f099c8f55869301fc2a0aa37355a4a2f89078135ee72a1362234ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401360101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000202e6425938fb77136939680c552a6be236e15ac4ed625998f63471227239c29d02dedb613647b0ad43c476af1b44286d66c2d09b94bcfb409bf9b078cddbd82ca01000000000000000000000000000000000000000000000000000000000000004f298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401360101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020249684272865fec3ad62ecb73dfd930500e32e475306c9e5d4b6d545e3687b0a48deaeebfafa213f0a560994b3f4000d5e2b93951d7e5be40073503877292dc7234ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401370101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020267e25450655771ab9a1a3e04a65c184c728bd3cd9d325a347e2f8e339df2502951d2d58675bdd42d0485baecef3fd996220059a6c30e5272e92c35c0588506501000000000000000000000000000000000000000000000000000000000000004f298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401370101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000204671db1df91098669bb03c3e8504d432da99853601366c7de7585bb8f23a6e1e2996a16c11a0f9ae87d937f566c8bbd919040528c1bf8dae4e22a8f0ac5f935a244ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401380101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020c3a96bd46f98c92a3311b8053980954f8d66c12581d3dc1eaff58d2cc2524377bafafac9739f3ad59b142347361e92c56a6a2433b96395b1f32ad070c940341a010000000000000000000000000000000000000000000000000000000000000050298e5dffff7f20020000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401380101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000203046500cabfee552ed114c505279cd75c28faa811adcb5010c53c14df5de3216d265321a4168c70fff1c85fd83bd976cc03c8c1fb6567398cc24053e343ad137244ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401390101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000206d0512cd762e3ac801a71b2a34440d54e879f20ec6ce46c1affaf500a6d473a2fc5485980b8c8ea92e2e021555c4c7d51a1bc1876ba159d268fd9b82bfa565da010000000000000000000000000000000000000000000000000000000000000050298e5dffff7f20020000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401390101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020591533cf8dd1fa1872c7e6d62ef714b28886f38f7921ee614e13b748eaf923282a96287277f18b1113a9c3ac384fd7b43bccd0e45114908ca5396a76cbd736fd244ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013a0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020b1fcc4dfb3c7234a37b412c53d7875f3904a8fabbc53e6371e5e4893bcf2637ae58c32587cef1ca2302eade194d66bc81f727204cf76e1d884d63f8d3939b358010000000000000000000000000000000000000000000000000000000000000050298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04013a0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000205286b5747d0244a55e1dce435fdbb9f300d7138fff3b16767bc09196eb00256c6795e3f372a2d5d137244a4fd72fd799e8de913f868f22269eaa628d7d2970a1244ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013b0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020404faf641adf310aa8fc82b9cff35f33d4259583add438e565df88a6fa67855f0ceb812d629a05ae41aa3dd2cc8393f3043f5d038c5c39e2764d804ac3e8d8ae010000000000000000000000000000000000000000000000000000000000000050298e5dffff7f20030000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04013b0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000209649b55f6a5ff0d5db73aeb7089fcce605fb9dd23971e577b73747ffab586f4edf84581240223e2d8912a6eca049e06aa46ddbf271af08e9ac9605505311418b244ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013c0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000205e026a6a245be5cca56cbdff8bfb8880455aef0ace6bd67ec1b0b0756824325668b82f456bae643458146e4242df88046b0d39f5b80f4d3bce9619cd0849d43e010000000000000000000000000000000000000000000000000000000000000050298e5dffff7f20020000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04013c0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020fe7ff82c11ad3a3db3dc11a03a67e0b86b727d232c80f37209b028bc2689296c0da76fb756e1c9833f38b198cfe843ab820fbc0c38e30f8f858f6ffdbd64e834244ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013d0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020229ebb1ae197e0626ead2b50480fa897c8aa13367999360d901a616a3d378aaeacfa4886f415f04cc0a86adcea8d5ceca8cbca31049f2986cca7e921732cb5c4010000000000000000000000000000000000000000000000000000000000000050298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04013d0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020c02e6109b6aaf6643cac109ad5b5be7f7ec47c7993335bdceea6e0e490ae9067eb1fcee49ecc40a61477f934e3b9821f2cc7ada429fcca2cd645866742854c40254ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013e0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000201ff4b0bc9ac5207724a625f7116579f93c59e976ed187b9c9188336c75887b3b14931ab5dfef97c4a9bb83cd6994ee705bad1b2c2be7dc5ec8d1d70415867092010000000000000000000000000000000000000000000000000000000000000051298e5dffff7f20020000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04013e0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020956c46fce0adfc8a30d91c7b7f328f17c2a90771083884c4fdb7f24640598f6fa69c4e5971bd3b6cdc7e3ee98e03a969b28c3220fdc685cc2eb77293763ca4ba254ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013f0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020f93263a21cd8b06dba37ae68182bebe2dc4884bd87f6bb90421662ce3517b7851bd25e4486ddb133ee285c31fd67dd0ab1fad43696ef3b9a7f258372afddd92a010000000000000000000000000000000000000000000000000000000000000051298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04013f0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000203eec7d0ea9c539f47e684eec9dba900e27c805b8200f237924c7df8065957726c83caf659fa341bf45f733a92cf76daf2cfb6bccbf969a2753f5f7d9cda4bd1e254ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401400101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000206e901e57352c9c935270bd33cf42b3aeca463290c264744b7593434a348b94286e21b29fddfee89035236430f0519fdde42edbba2cff3a69395e71ac0a8cc078010000000000000000000000000000000000000000000000000000000000000051298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401400101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000203c022b42283bf651ee4d536fe71b7e5382e9783d4a85f8bc159f00b97f16d82d312ac4f89f1b1496de576811f2ff17de44b512db0beddae59e030e2ce3eba4df254ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401410101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020547e4b25278bef0b46c4ff096179c05a9ad25b1e8d735bab9109e5f9c625228f22aaf37d0db4e12ad40d286c0c210787d7b4e55fb1cca0e0756045183ddb7304010000000000000000000000000000000000000000000000000000000000000051298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401410101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000205da9709dea4bea4f3229d0eed439a4820a0e817f9fbbcd8bb355cd8052702973403358080a2881b823a740f58b6b0c922b42189e06326478cc33390f2c704743254ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401420101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000207d8a623bcfd2ca3da4a10d9842f18489d2e1b1bba5803d236f881aba3b152c7d1f41e6374dae64966b3791bede633c69a4a7c1a362ccfc232a47041b684655c7010000000000000000000000000000000000000000000000000000000000000051298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401420101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020447c49f664916cc13a839e27f7cbe0b09dea990dec71dd479b537ecfb771c7159ae6241727c2645ce00817909ba97d43447fe2e146bce55b7dccd5bcd27d2e3d254ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401430101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020e6f81efb92a28e66b65eab2dbccaf70570eb53d6dc5057e640e7a3cd14983b79f94c3177a4cd10e1b04baadf9ef3e97fee16d5787a5c6a4b6a000aeccdef7322010000000000000000000000000000000000000000000000000000000000000051298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401430101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020ae3b214b1495953eea3b99af7ade4b8d22d615d598dd6c790c6576d6453ef35d37fbd3446f8431f00052f278c3e0359beba54a2f5064bc6be4990478fcf4e086264ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401440101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020b318408ed77cfdd0e5c4106b3d963df17474289d7a94989fd51b3a62028f905db2c4447dbaa57602ce22c585a0203819ab96c932ac91d9908e288c501366ccd9010000000000000000000000000000000000000000000000000000000000000052298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401440101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000204cc68f9f571f59145e1f7505550d56da13a797fbc7e5a178dd7f6f9241d91f007f2400f7aa1b32b30bf869e4da86f75eaf2baae182efc45c42c6245f06aba675264ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401450101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"0000002042fd200cbc0f6d5e21e753df0cf9b4bf411173188c5f629515dd9e438621873266e52da4579cf92d25016da99bd70854cfeefc787f89d291b647886a0f98cada010000000000000000000000000000000000000000000000000000000000000052298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401450101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"0000002096d55714a83c3d030cc72141eac3577b8a394b8366b2c93354fcecdafeab025022f5e26de7e4eba3f8e4a09f243b55ea6f08bfd013e2051cf1d5df20dcb3331b264ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401460101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"0000002049a79824a608770beaefd83b6bf490c5205ddeb33bb51b63472945a62c2fa3d30208ffe437833ddb3df6ab62506b5c3f2d9b05f35bf029b64681edb499b79d9b010000000000000000000000000000000000000000000000000000000000000052298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401460101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000202ccf49665bd46e4915dcc9221f5fc72124bb73fb11fed8869dc5862a47950c0d654693a1d86098212d68fa9a27f9df0faafea4aecebd8b203f2ab8f3f0b86196264ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401470101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000203a6ebcc5e5031f3a90cb145feb8614c922b01bca955e9878ecea00f6e0635f4a6e144c018c0a95e5d83473865107f0453b4d0cb2d655687bba38fa3c8664fe0c010000000000000000000000000000000000000000000000000000000000000052298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401470101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000205d0be5aea546eab7734cbee757ea5f4983ab3a3f202323c1c88590bdbc8b561974cb0de6549bfdec92322ad53d8a4192433edab0e33a10e7561d2e27c7759f8a264ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401480101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020d6990869ce59bec3a60675ac9e9997f147090869b1dd07be9e1cb2f94f28fe9c7d5e5f0cb033a158cdfa50ec6d5118d42ffb4d52284348bf0f68f0990db0627c010000000000000000000000000000000000000000000000000000000000000052298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401480101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020fc3d70d4f690d7d7da90b1c832a51c2a92940cdd9fccda6a909c7256ad567160550e1089b48fe75f0f1e6f712cc2a1d4aad384a4ceacf1c71576420fe8e7de46264ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401490101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000206515ed2b781786fd8bbd982a7e170776b0ea4320ced88972bd90649f7542231431b27ee4ea6d05f07887027356a76c5cce03375eb525fee6bde3b69656575882010000000000000000000000000000000000000000000000000000000000000052298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401490101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020995ab1f2293e3aa1e7bef418919bdce60032e89e60223b8c12b17488c50af83b3a360b4f89551aa0ced646a6210b0c3d3f7d0464faa248b9d252c89615babc9f274ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014a0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020f87d4477a677bd04749b9c52f7a4544ca0adc7150fd2f691e0d0930a09a7d1b043a9d9deb3739829c6fa8e8abc9c30573224e43f6c36ee103012f4fffbba2b9b010000000000000000000000000000000000000000000000000000000000000053298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04014a0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020e02dd5e1201ebe7ef453e77df3021cffde1b5447b9eced017963489e005ac247e1f2b80e91180cd9744c3e126eb8a0fb34ced45587da6b0fa9fd1c6946f049bf274ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014b0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"0000002027f74ac6b315fa990ff6fe9fd07966ee64c4d051e7ce92cad3dc84f1cbf2452bd1d0326fe6c571de5fb37707d8bbeb55b932f0b4ad89c506e414c020d5088e5f010000000000000000000000000000000000000000000000000000000000000053298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04014b0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"0000002081b265800d61feb37525c58aacc7e6d32cfc6b6579784f9952dca51c3addeb37da900ae4ec1b2075056001a361c0fc8f9ac1ca018bde2a2bd8fc587424dfe18f274ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014c0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000206c98fd30a20783935ace23743a8cb9a02e6eed8b508cbe16305cc685dbef0e2d12e5d1eca285a4ca2cc974ede1ca60fd35e5f04303017143fcc3ba710efadaab010000000000000000000000000000000000000000000000000000000000000053298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04014c0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000207daba0dc6fccc067a19dec46770d1443fc715b50540242ff26073a6748bcd9583804c315b783d4f9aac4dc8f109fa60bcbf1c3cf98a7e1e593fcb969e88aafae274ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014d0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"0000002036d8823d48e38575bcd2b13e2fa89be8f3f581151e06be6545fbf67336a300ac43e661b5889f90f1511a72c2d6ff1ae990bf7fecc44d01cb08621c238bd8e887010000000000000000000000000000000000000000000000000000000000000053298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04014d0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000204a35ab2d9c4656c4992d2445ee566e4f5cd0468358292c94839de2b270ba0628de9148db03da59ca2eb727a4f7a03f2b9ee1e4045f37bdaa4b75a89de56b63ee274ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014e0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020aabbc62ff10ebc5466db39bc4ba5acc763e854dd8a766d018d8341b5371cc47fe96433fea9696b53603cbacfad8d3808d70c681925606ef11be24c81388f556c010000000000000000000000000000000000000000000000000000000000000053298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04014e0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020215ed7b31d118a45a06407133e41f3f9d25c913ff98f3e798144f981d9145305266efc9274f7c836aa0f8b831732aec2c1d85c5bb9176af4c889a707cca380fc274ae75affff7f200400000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014f0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"0000002079660b6b38721b49ef7e05a9ed78d3c11ce1af6a8dcb08a862f61e9513cc780bda411454214807f29a201bb710436eb95f153aafffaac1b9d29254ec0f39d681010000000000000000000000000000000000000000000000000000000000000053298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04014f0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020425321a1f12ed4613b63b3cc5b4c7674242c3de67ea86984f2d9bb2766f6220a5c460ce6840832b7ef05f206c5d255bc2d8ea83753a7f5ef5c0bf3dbcbc7c74a284ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401500101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020bd361170eecaa766944c2c22b54a2048ebb1ab4fc52837a66bad850479b9fd61e13cb2bd7da4f99412c40cb43227cdc0df404d977be0f0ae24c1804f661135a1010000000000000000000000000000000000000000000000000000000000000054298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401500101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000204e088cfd312091bf589f0fc24131dba20ed83f716530a7b033356e9ec803be23a73c4af5b64fc631d20aa1f646c7c61c4cc5d4be6e2fa29570030d72219726a0284ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401510101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000202bae167d754ca4b3ba9fb4bae2d452561a021bf64988bfc9dc11f05824bbab24c84a68a6d88174fdeb6863596ea35f97735b9fb80037a90fc512529731429b6b010000000000000000000000000000000000000000000000000000000000000054298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401510101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000204287a2bf40300e39b45d6667d6e17abba37d98c41efc7023fd21b643fb2f6b76d915d10e1f9e224d3bfdf5203da57173f0b8d8eedc92ed9ff23372927e86073b284ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401520101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020ab2ecf71d724d650baf77cb63e108cd933e08ab1c3533ed5057730b52382d9e30ba6864fb662e379c2a2d8d64ba4c17ec8f183a2a0102c969893a813cd1c6e56010000000000000000000000000000000000000000000000000000000000000054298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401520101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"0000002083137929ca902f409a1f35385b4d31e0f5163d488d71b00ade724d7831986a280a187c13fe0db45aed5fa4f5089d544a617da9f4f80fe6ce1d0711b228f3a6bd284ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401530101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020940d5c843cec6cb987d18506f44343e4176f54f0028720d7036d323fc8bd0f5f950bcc074e1ecd1b543e39872af433fc5575004fa96c8864ef5be3a7a8feecd1010000000000000000000000000000000000000000000000000000000000000054298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401530101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020b38c074d78cbcc8bbbf20c48e30639c2dcf444488efee59f5aa01c48322a30418009c11df7e14de6a6d0d72cc22f20ff5fdba3a7dbe409409ff92b1302340fb8284ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401540101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000200eff6985d00d2dae0c9ed5d8d9ee1d6e1742f7bdca76bdbcb68f8540203fe830704265dcfb6c95cb07fc701f39123a804fbdf59cc7302dc889a172070f6dcf0b010000000000000000000000000000000000000000000000000000000000000054298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401540101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020a6865148220c7f5ac3259f57fa381676d6be5fdab56eed8e060808fcce4118492476fe6d5ecc681e7a18c20a04239143de1c2cddefbb08f15153b8e9b0c22f62284ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401550101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020a2f82b9acba4b57dd50f4e63489138ee1af0d3fd956aea5f64dd6eaf5bed11aae43256d7f8457700b24f4057eca70f498a4669424a453c8b25ca53d5936caa74010000000000000000000000000000000000000000000000000000000000000054298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401550101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020ae146263f4087106b8c51ffb5cdddb03a4e593ea1a22a8f6580eaa374185126db2187dbe694a1b17b7c5664115307965407274c25bf6ae02049817685f923256294ae75affff7f200600000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401560101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"0000002076594d858f8491fdb94daa2c9f199690d0e4b1e10f49570cc63de870efdc7cdfe4fea89c7cacde1ce6a385f186e6ae2660d6f96ad1c5f65a55374e78f05c2088010000000000000000000000000000000000000000000000000000000000000055298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401560101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020718abe22705f33134812b56d04c129d453da890e27caf6e77d2bfb3f9be460083634f35fc8ea4a29b0f30d6c6b4926455a31de62d2f763bc95c8cd1a7a425599294ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401570101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"0000002073c9c91546655921ffecd56bf6c88a431569553df0514cd160ef6e648c3038208d170a1d6049197890ae215dee26eb1c4f56d3e72a9ff76d05028c522dad5df5010000000000000000000000000000000000000000000000000000000000000055298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401570101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"0000002084537c50520f4e6b0173926320c3193f6b4259c9a724fe202337d3d5cf7da70b1104e1d6f25c411165a856a0bfdd5ddbe168238425c05271962aa6e5ebb676fb294ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401580101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000206f0a68329f9ec8b2212d92da2efd233cc287b92a6ad558ebd7c877d378382690e4871ece6f3dbb9510c7ec2f06264ece3d0d786924782cc87c880104797d308d010000000000000000000000000000000000000000000000000000000000000055298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401580101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000204bae65b948c9790468cfc8fbf78a81e7aec5407dbab18c18ef1ab37a13f0c257792cd1246dac5ce265a8439e539db1aebe4776535d422315bac8e57a51605aa6294ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401590101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020f95fc51dfaf099418f31316b0e2511a1381f292dc77d5cbcb323bc623736e47bab12001f519e5f29675f9723610c2adb06fc09a3433164183618af3d5f2d5d13010000000000000000000000000000000000000000000000000000000000000055298e5dffff7f20020000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401590101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000201e68985b2a15920524c3c2da77354c0ccfb202c3ab4005128eb2743aa33f0a5b0527a624a6d1f808c896d8cd1552c251a4ae5310e6c62493977b0965d17f580d294ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015a0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020a2b24bcd260e921e21eaaa24f9ee49646a19ec90a2776e4d5569d1e4b96ae550ab283476b7512a414a45d0afd1067542aa21b35136858cc228f093b79a86a168010000000000000000000000000000000000000000000000000000000000000055298e5dffff7f20030000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04015a0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020ab1d90854505caa1ee748c1987f4cb6674844b84d17224bc3983fdd6e44a930b2edf3e5a90be7a9080ad15014ce796b38b6c19ddd3754443243fc277bcd2368a294ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015b0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020f98eb5e8ea9b3a7e0e7b97d22dfc4940e81b3efa7a52b1ae984ae62d258eb6094f21c0bc0a6b5d04a200cd96e7afc8903f693c73841d7a7f46444061b87cf4dc010000000000000000000000000000000000000000000000000000000000000055298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04015b0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"0000002062242f316efa083c17e2173d9f9831afc1465f3fe84431d8e52fec71ae358b243e29246e0db770708987f2cff380920321636926d9c66c2c808d2d5f0ed27d672a4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015c0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020c9b5bd09d4cdf36fd437dcfc6d467496aaf8a2a9b48a9109a6573d93ba1fe1dbd81b4c34fdc739646dc6d7652315e672df987039c108f21c6233a29ca6b0269d010000000000000000000000000000000000000000000000000000000000000056298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04015c0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020258c1a9b0ca17819d8d7fea5178e9c72c2e7c6769696f70098e0d5d2a9dc0e5cf039f5f686d727c6158ef5405ee8794ec2f89c641093a1dff0f5240263a441bc2a4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015d0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000200643717cbcb0cce475b5f0fb63e56f1447799264726631396c30224bc7f798790c341d332c183b762fca8c54f6fe148772e0f9181dfea77974a3afb71a1052b0010000000000000000000000000000000000000000000000000000000000000056298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04015d0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020434ce26cddae99571a1d663419d715f88e6ff0e413c45f21c44b1991d041fd2745534db221054e2233052aaffe7d7232a91b3f0918c14eac74b2f704b37bfb8e2a4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015e0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020ac06f84bfaf2ceb8b19ead70177dbd6201387983d72a977da1f57ffd921a6783b2d5511af0de5e43edb43e0d766e1e70d0de2710f3eb7f89a10ad0f512648c46010000000000000000000000000000000000000000000000000000000000000056298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04015e0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020ec94475f112ea37dddd84f066e61446b431d28d2d9b6fbb336d16295e7eece52f1dc01abb3b27e71d8a25c3ed2d6fbbc5900bf954738ed63d57689ba5e68f6532a4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015f0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"0000002023f31418b84cfa73db871d97b08497af8cfc05658cc65baeb88140943a88985c0d7727f13069e326603003358d3618953e17ff6e4ffc8be096474d3512bad092010000000000000000000000000000000000000000000000000000000000000056298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff04015f0101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000206188cca18a2be3b7f0b500a724f1b73312873488f04c5082abd81ca0b2250a75ec0efb2fa994ad23e1f39416e69976e66fc4ef9f101bd4f60fcee1f8c45a2b802a4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401600101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020a7c86fccf39d979b930e8e94061dc2ae1cb4af16c58557dc28ba136c2714196797e7c32249c1eaf9138dc9279cebf0189b61b6ba6e694af744f93949e0c531b0010000000000000000000000000000000000000000000000000000000000000056298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401600101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000202384b91bd0bfb1385ef42bda9b2fa43930aa8889214bb14f63c61a74f380dc7f9d547f2925ad39b9161fa55b9cd258463fd058234778a7c7b3061113d64179812a4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401610101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"0000002015ab67be546784d304150d6912c3ad77b5135f06db0a82517f0e7bc7ee3c14ff9b540ec1386e01df66f097f37a57f7f777fe9a7605394d3c60b43e7a0f21f775010000000000000000000000000000000000000000000000000000000000000056298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401610101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000204c266a3008c3bd95ae4bc8228bf878595cabf76cc2ef3fed32936777fe37833a1a13ea016868b2352a8d6d1eb35d0aee784cef06ed50655b8d84c089324351df2b4ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401620101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020e5656df91c69f8a74de2002fe237014cb7ffba5c198f2740fab78b0e532e4b6cb1eee816671fd7ff909c68b67c86172a2840733837943c2b99f7b0232112308b010000000000000000000000000000000000000000000000000000000000000057298e5dffff7f20030000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401620101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"00000020ab2c78d1249de8482cf26bfb1616ac04f7b8404eafcae3e0654f398943fd41571b4d7549862be0b06ed1408ddc3e7c01b07af24c203a18fe9744e214b14d2d652b4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401630101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"00000020c2f75754521bfd09fdce186ccee3de0724558ab0dd7e6d66aeb2c24ecd0b72c88befbb4db8b957c2de6545459d810bd8b316b48d13384cbc65417eb0053d9afd010000000000000000000000000000000000000000000000000000000000000057298e5dffff7f20010000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401630101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"0000002031aa0fc5e0242a9c9d91024b6b7e67544da72c4773537f881ee5caacd45a3c38c650ff5fa0ffd080b3e5f9752527b718e8c6b731467028e14b0b009d4e7406ee2b4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401640101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"0000002068569744e5ad15456dde211456d1d6d88e8575d318cca972be4c4214802d0e8204d450ccd28e34284b290f457a24e62a1362f9a2f804d2d6b3be8b39b2512112010000000000000000000000000000000000000000000000000000000000000057298e5dffff7f20030000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401640101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000200418c57609fc6ea3f24f569dc3afe163538a6aab940fe8c3d73c72cd781221380482c6f8ef2c19429da2f7a842bb811496aa86247c55f7ecb3337718b694d9472b4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401650101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
"000000201e5bfcdf805e44ecf759571ab08560ad66166044be47696807937623b30faba39d638f685167f53a0b4683fe059370e1dcad605eabd79c4fc602980e5ff97db0010000000000000000000000000000000000000000000000000000000000000057298e5dffff7f20000000000102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401650101ffffffff0200e1f5050000000023210375c6e5384af4df0ef340e9a7de57dee04253e470ab3752aa7ded36dcebe24183ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000",
|
||||||
"000000204f36abaf10d6a8b3113103f3413475db0640c89a39f02a718e8bd2190fe87f1d6ffaf2b9fdbed67ebae4b36c97f9582814c99c90d0b5123f14da4861bf3e4f742b4ae75affff7f200100000002020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401660101ffffffff02b000062a01000000232102f6869601b2b9980b07fc047e309c1fc1433e08c5bf0498115c5c0e117ef59bfdac0000000000000000266a24aa21a9ed5896cd6a40cd126b09e317cbd179f39e2bcef2f9d423751d980258396416e671012000000000000000000000000000000000000000000000000000000000000000000000000002000000011cd16b94f20a8a3dda91027c888025f2ec1a07ddcb2786bdff5916e66c00406f0000000048473044022046d00465c4508cfd02fcb878b19d120e28be28e40658b1f15458828891ed1541022036aac054f36a42666dfb7b42a20506315a0b72232ce7704406e23c7a9515178701feffffff0200286bee0000000017a91481ddd4a9708ba8088cdcfeab9583ede8d83a298c8750bb9a3b0000000017a91484e16967722289584257803688aae36cd64480688765000000",
|
"0000002066bd635be5b553539cd953474c4907b44c7846a3bec06cea96c7258914d5509a430025a9bd953d89a962a10f81ad1a2b1559a5d94dd0bac31fc15967bd15d974010000000000000000000000000000000000000000000000000000000000000057298e5dffff7f20000000000202000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401660101ffffffff02eceff505000000002321032c6891656ef6cfc5b6c7b311133ea2bff07b890a029ced48ee51a2c90801b528ac0000000000000000266a24aa21a9edd2bfb4f47890a95750585964ee6f4f69555a306a4819f89dd72c0ff014839bb80000000002000000019c2646796e96a45b91dd9199a449736bd9a78880936306be5f125a7ebcbc69e40000000048473044022074058acb16acdc220b34b695668dfe5d2ed4819e2a11ab9c9c56a1c9bd7636d302205364ee6d261b725040255aaea5e11b618644642c8f9f718772fe3a7eaaf3787101feffffff02141e3101000000001976a9148b9217f042f56f05f71e20f5420f9fc90d32f87f88ac00b4c404000000001976a9145bb987c92e0c23bf14659cee81a90cf0c80cb03c88ac65000000",
|
||||||
"00000020cc7c39992f2dae21e0ebd958f6ba77a6d0bcc568e044b9b61ca4d77536a4214e7b4ade79dd733ea72d97993aaac27f2263b91b1500467350ff35ea40c2850d392b4ae75affff7f200100000004020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401670101ffffffff0230d0062a01000000232102f58ba54b2d51c4e2a6096f9d266261b45f1026a86ba88c29ed8070dfe3f5ec6bac0000000000000000266a24aa21a9edb824d92cb231c2366f0726aedf8bfc2705239a40ae6b10a106534e8b5395a09d01200000000000000000000000000000000000000000000000000000000000000000000000000200000000010196bac2a0f6212b8e5710f8c7214dd32c393d38d20b7703cf0b7b25276bb6ab8001000000171600144f8a6c8d4c6c309b1e2b725b7496859e172ea367feffffff02781ef5050000000017a9149f00bafb542049fe32d532b0ea7494ebb7ae41398750daa4350000000017a9147794e6dc43de332ca7a095e582478c331446686d8702483045022100bd85ed3954f1151c2fde32c4021a32c96d7defa4a57c14b1a056be9b361a8e49022054947bf6fdb535c46cbee62efc1262cc0389a6eaa19afbcfa98fb1fb30c3ef230121031b2371df07fb88dddf590b246dc74defc265fdbfe258e4b168250859b806f5ce660000000200000001bf83574fb606f25c59200c844443201faf923ef5284fd4401f3104a323c601490000000049483045022100d1c4b09b488f6375ee4540a531a13b5549e88e2459bd88c84867e293c54862740220222e8af70c8d8b1139c2a7b616d9132bde94244edca7eee3c7a783b12839dadc01feffffff0250196bee0000000017a91490e5e33cfedf18d5cf911d6f853770c62e1f5d028700ca9a3b0000000017a91422311ee58518edf3a2289012461dc66bc8739d2687660000000200000000010196bac2a0f6212b8e5710f8c7214dd32c393d38d20b7703cf0b7b25276bb6ab800000000017160014b81faaafa52f7723f539f8d595147b1a112b38ecfeffffff0208bd9a3b0000000017a9146b2e611708a94d9c674dd08c7c4c1fbb97bcdba987005ed0b20000000017a914933a20f07bab1d8f341f391819466a271f0cfd648702483045022100dfa8b0052c7825e6abcea05d10fc82550a8d6538681ffc8188d48ba789e4d9b40220697371cdf527a6ecd1887f87da3c87dca3419e4a1aa2683e5c4e035199084d100121021cc37c2ec090f30ea0b49508ae8a7d65d9759903932666da56671c1faa445d5d53000000"
|
"00000020237f85d3c2263dd3d424076549ebc19656b3c724f03bfd9b527184b44e77a7ce15f37e2055a2c2feecbe763101c6f8a5850c8f1ae95eb2c100fc75c58e283123010000000000000000000000000000000000000000000000000000000000000057298e5dffff7f20010000000402000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0401670101ffffffff022c09f705000000002321036c9111e5a6523faa990b7452c2c88c3c5e22ef6d9ad5288637168a3b0ac9bc54ac0000000000000000266a24aa21a9ed3befd64d33a3d249c6882f1a4e08a948b03f848270c8d717889a0a914bbe989b00000000020000000129b86f6b974b8c38a47ffd1a97b73e16864a344fe72c7b20f26f3dfaeab8e23f000000006a4730440220450b9e79c405c5a50df883cef44073b5fe0f76a268e8c2617ebe84b67c7d61770220163f696ceb92ca0d798dd0a11ea1aa49f0403658097b56eb20da82c0b0cc99eb0121034107f19591db3b08fbef4c466b8fe5831c2cafeefeb55325ea191ae1c645b154feffffff02d47c1d00000000001976a9145f881a61d39c56d83ad6adc45e0dd5d87c48ea1488ac94991201000000001976a914be83ea53e1caef62a9da4ac46bee932fb6e64d6588ac6600000002000000016f9c965b9b8c109db568d32d7d3a0dd7ee4d132490f42b51f4ba2652fec7bd1b00000000484730440220727dd1aaf6727c76b3754305147de818ddd9b6cb7c7cb6669c5a235ea35b658f02202e8b340309ab3b2e937ff54bc5405670921a08498322b6acb03b14d570b1c96b01feffffff02002d3101000000001976a914347e511d57756463f6e298d1a545d19f657e3c5b88ac14a5c404000000001976a9146e6bd61c46f7feb09855769d1ed0206818deb88388ac40000000020000000129b86f6b974b8c38a47ffd1a97b73e16864a344fe72c7b20f26f3dfaeab8e23f010000006a473044022079dc6bfd6537301ca23178845bf789b3c34ab4f0b838f271f1526df41bc24e39022038b9b78a1554af83f4bc0616945b6af66e3e938c237553a76fd96f9074375540012102ffd149a0a5c08f0fb54fa934bb93786cda9440d3cdc09614b0f09cca5c435970feffffff0200879303000000001976a9148e6032ef5414a7d0a26b3d6be863827b5a3c82c988ac6c1b3101000000001976a914f843cea430f0ef2bd291f7251a6201cb2422809b88ac66000000"
|
||||||
],
|
],
|
||||||
"mocktime": 1525107225,
|
"mocktime": 1569597765,
|
||||||
"stats": [
|
"stats": [
|
||||||
{
|
{
|
||||||
"avgfee": 0,
|
"avgfee": 0,
|
||||||
"avgfeerate": 0,
|
"avgfeerate": 0,
|
||||||
"avgtxsize": 0,
|
"avgtxsize": 0,
|
||||||
"blockhash": "1d7fe80f19d28b8e712af0399ac84006db753441f3033111b3a8d610afab364f",
|
"blockhash": "9a50d5148925c796ea6cc0bea346784cb407494c4753d99c5353b5e55b63bd66",
|
||||||
"feerate_percentiles": [
|
"feerate_percentiles": [
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -125,17 +125,17 @@
|
||||||
"maxfeerate": 0,
|
"maxfeerate": 0,
|
||||||
"maxtxsize": 0,
|
"maxtxsize": 0,
|
||||||
"medianfee": 0,
|
"medianfee": 0,
|
||||||
"mediantime": 1525107242,
|
"mediantime": 1569597782,
|
||||||
"mediantxsize": 0,
|
"mediantxsize": 0,
|
||||||
"minfee": 0,
|
"minfee": 0,
|
||||||
"minfeerate": 0,
|
"minfeerate": 0,
|
||||||
"mintxsize": 0,
|
"mintxsize": 0,
|
||||||
"outs": 2,
|
"outs": 2,
|
||||||
"subsidy": 5000000000,
|
"subsidy": 100000000,
|
||||||
"swtotal_size": 0,
|
"swtotal_size": 0,
|
||||||
"swtotal_weight": 0,
|
"swtotal_weight": 0,
|
||||||
"swtxs": 0,
|
"swtxs": 0,
|
||||||
"time": 1525107243,
|
"time": 1569597783,
|
||||||
"total_out": 0,
|
"total_out": 0,
|
||||||
"total_size": 0,
|
"total_size": 0,
|
||||||
"total_weight": 0,
|
"total_weight": 0,
|
||||||
|
@ -145,11 +145,10 @@
|
||||||
"utxo_size_inc": 173
|
"utxo_size_inc": 173
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"avgfee": 3760,
|
"avgfee": 3820,
|
||||||
"avgfeerate": 20,
|
"avgfeerate": 20,
|
||||||
"avgtxsize": 187,
|
"avgtxsize": 191,
|
||||||
"blockhash": "4e21a43675d7a41cb6b944e068c5bcd0a677baf658d9ebe021ae2d2f99397ccc",
|
"blockhash": "cea7774eb48471529bfd3bf024c7b35696c1eb49650724d4d33d26c2d3857f23",
|
||||||
"height": 102,
|
|
||||||
"feerate_percentiles": [
|
"feerate_percentiles": [
|
||||||
20,
|
20,
|
||||||
20,
|
20,
|
||||||
|
@ -157,35 +156,36 @@
|
||||||
20,
|
20,
|
||||||
20
|
20
|
||||||
],
|
],
|
||||||
|
"height": 102,
|
||||||
"ins": 1,
|
"ins": 1,
|
||||||
"maxfee": 3760,
|
"maxfee": 3820,
|
||||||
"maxfeerate": 20,
|
"maxfeerate": 20,
|
||||||
"maxtxsize": 187,
|
"maxtxsize": 191,
|
||||||
"medianfee": 3760,
|
"medianfee": 3820,
|
||||||
"mediantime": 1525107242,
|
"mediantime": 1569597782,
|
||||||
"mediantxsize": 187,
|
"mediantxsize": 191,
|
||||||
"minfee": 3760,
|
"minfee": 3820,
|
||||||
"minfeerate": 20,
|
"minfeerate": 20,
|
||||||
"mintxsize": 187,
|
"mintxsize": 191,
|
||||||
"outs": 4,
|
"outs": 4,
|
||||||
"subsidy": 5000000000,
|
"subsidy": 100000000,
|
||||||
"swtotal_size": 0,
|
"swtotal_size": 0,
|
||||||
"swtotal_weight": 0,
|
"swtotal_weight": 0,
|
||||||
"swtxs": 0,
|
"swtxs": 0,
|
||||||
"time": 1525107243,
|
"time": 1569597783,
|
||||||
"total_out": 4999996240,
|
"total_out": 99996180,
|
||||||
"total_size": 187,
|
"total_size": 191,
|
||||||
"total_weight": 748,
|
"total_weight": 764,
|
||||||
"totalfee": 3760,
|
"totalfee": 3820,
|
||||||
"txs": 2,
|
"txs": 2,
|
||||||
"utxo_increase": 3,
|
"utxo_increase": 3,
|
||||||
"utxo_size_inc": 234
|
"utxo_size_inc": 238
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"avgfee": 18960,
|
"avgfee": 25273,
|
||||||
"avgfeerate": 109,
|
"avgfeerate": 118,
|
||||||
"avgtxsize": 228,
|
"avgtxsize": 213,
|
||||||
"blockhash": "22d9b8b9c2a37c81515f3fc84f7241f6c07dbcea85ef16b00bcc33ae400a030f",
|
"blockhash": "981d9ad0c7dcd22dce86deb6d118fdde6a3e62092ecfea93f9856f2eb23a37f5",
|
||||||
"feerate_percentiles": [
|
"feerate_percentiles": [
|
||||||
20,
|
20,
|
||||||
20,
|
20,
|
||||||
|
@ -195,28 +195,28 @@
|
||||||
],
|
],
|
||||||
"height": 103,
|
"height": 103,
|
||||||
"ins": 3,
|
"ins": 3,
|
||||||
"maxfee": 49800,
|
"maxfee": 67500,
|
||||||
"maxfeerate": 300,
|
"maxfeerate": 300,
|
||||||
"maxtxsize": 248,
|
"maxtxsize": 225,
|
||||||
"medianfee": 3760,
|
"medianfee": 4500,
|
||||||
"mediantime": 1525107243,
|
"mediantime": 1569597783,
|
||||||
"mediantxsize": 248,
|
"mediantxsize": 225,
|
||||||
"minfee": 3320,
|
"minfee": 3820,
|
||||||
"minfeerate": 20,
|
"minfeerate": 20,
|
||||||
"mintxsize": 188,
|
"mintxsize": 191,
|
||||||
"outs": 8,
|
"outs": 8,
|
||||||
"subsidy": 5000000000,
|
"subsidy": 100000000,
|
||||||
"swtotal_size": 496,
|
"swtotal_size": 0,
|
||||||
"swtotal_weight": 1324,
|
"swtotal_weight": 0,
|
||||||
"swtxs": 2,
|
"swtxs": 0,
|
||||||
"time": 1525107243,
|
"time": 1569597783,
|
||||||
"total_out": 9999939360,
|
"total_out": 199920360,
|
||||||
"total_size": 684,
|
"total_size": 641,
|
||||||
"total_weight": 2076,
|
"total_weight": 2564,
|
||||||
"totalfee": 56880,
|
"totalfee": 75820,
|
||||||
"txs": 4,
|
"txs": 4,
|
||||||
"utxo_increase": 5,
|
"utxo_increase": 5,
|
||||||
"utxo_size_inc": 380
|
"utxo_size_inc": 388
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -42,10 +42,10 @@
|
||||||
],
|
],
|
||||||
"outputs" : [
|
"outputs" : [
|
||||||
{
|
{
|
||||||
"bcrt1qmpwzkuwsqc9snjvgdt4czhjsnywa5yjdqpxskv":1.49990000
|
"rlbc1qmpwzkuwsqc9snjvgdt4czhjsnywa5yjdqpxskv": 0.029998
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"bcrt1qqzh2ngh97ru8dfvgma25d6r595wcwqy0cee4cc": 1
|
"rlbc1qqzh2ngh97ru8dfvgma25d6r595wcwqy0cee4cc": 0.02
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"result" : "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAAAAAA="
|
"result" : "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAAAAAA="
|
||||||
|
|
14
test/functional/feature_block.py
Executable file → Normal file
14
test/functional/feature_block.py
Executable file → Normal file
|
@ -309,7 +309,7 @@ class FullBlockTest(BitcoinTestFramework):
|
||||||
b26 = self.update_block(26, [])
|
b26 = self.update_block(26, [])
|
||||||
self.sync_blocks([b26], success=False, reject_code=16, reject_reason=b'bad-cb-length', reconnect=True)
|
self.sync_blocks([b26], success=False, reject_code=16, reject_reason=b'bad-cb-length', reconnect=True)
|
||||||
|
|
||||||
# Extend the b26 chain to make sure bitcoind isn't accepting b26
|
# Extend the b26 chain to make sure lbrycrdd isn't accepting b26
|
||||||
b27 = self.next_block(27, spend=out[7])
|
b27 = self.next_block(27, spend=out[7])
|
||||||
self.sync_blocks([b27], False)
|
self.sync_blocks([b27], False)
|
||||||
|
|
||||||
|
@ -321,7 +321,7 @@ class FullBlockTest(BitcoinTestFramework):
|
||||||
b28 = self.update_block(28, [])
|
b28 = self.update_block(28, [])
|
||||||
self.sync_blocks([b28], success=False, reject_code=16, reject_reason=b'bad-cb-length', reconnect=True)
|
self.sync_blocks([b28], success=False, reject_code=16, reject_reason=b'bad-cb-length', reconnect=True)
|
||||||
|
|
||||||
# Extend the b28 chain to make sure bitcoind isn't accepting b28
|
# Extend the b28 chain to make sure lbrycrdd isn't accepting b28
|
||||||
b29 = self.next_block(29, spend=out[7])
|
b29 = self.next_block(29, spend=out[7])
|
||||||
self.sync_blocks([b29], False)
|
self.sync_blocks([b29], False)
|
||||||
|
|
||||||
|
@ -829,7 +829,7 @@ class FullBlockTest(BitcoinTestFramework):
|
||||||
assert_equal(len(b64a.serialize()), MAX_BLOCK_BASE_SIZE + 8)
|
assert_equal(len(b64a.serialize()), MAX_BLOCK_BASE_SIZE + 8)
|
||||||
self.sync_blocks([b64a], success=False, reject_code=1, reject_reason=b'error parsing message')
|
self.sync_blocks([b64a], success=False, reject_code=1, reject_reason=b'error parsing message')
|
||||||
|
|
||||||
# bitcoind doesn't disconnect us for sending a bloated block, but if we subsequently
|
# lbrycrdd doesn't disconnect us for sending a bloated block, but if we subsequently
|
||||||
# resend the header message, it won't send us the getdata message again. Just
|
# resend the header message, it won't send us the getdata message again. Just
|
||||||
# disconnect and reconnect and then call sync_blocks.
|
# disconnect and reconnect and then call sync_blocks.
|
||||||
# TODO: improve this test to be less dependent on P2P DOS behaviour.
|
# TODO: improve this test to be less dependent on P2P DOS behaviour.
|
||||||
|
@ -1061,18 +1061,18 @@ class FullBlockTest(BitcoinTestFramework):
|
||||||
self.log.info("Test transaction resurrection during a re-org")
|
self.log.info("Test transaction resurrection during a re-org")
|
||||||
self.move_tip(76)
|
self.move_tip(76)
|
||||||
b77 = self.next_block(77)
|
b77 = self.next_block(77)
|
||||||
tx77 = self.create_and_sign_transaction(out[24], 10 * COIN)
|
tx77 = self.create_and_sign_transaction(out[24], 1 * COIN)
|
||||||
b77 = self.update_block(77, [tx77])
|
b77 = self.update_block(77, [tx77])
|
||||||
self.sync_blocks([b77], True)
|
self.sync_blocks([b77], True)
|
||||||
self.save_spendable_output()
|
self.save_spendable_output()
|
||||||
|
|
||||||
b78 = self.next_block(78)
|
b78 = self.next_block(78)
|
||||||
tx78 = self.create_tx(tx77, 0, 9 * COIN)
|
tx78 = self.create_tx(tx77, 0, int(0.9 * COIN))
|
||||||
b78 = self.update_block(78, [tx78])
|
b78 = self.update_block(78, [tx78])
|
||||||
self.sync_blocks([b78], True)
|
self.sync_blocks([b78], True)
|
||||||
|
|
||||||
b79 = self.next_block(79)
|
b79 = self.next_block(79)
|
||||||
tx79 = self.create_tx(tx78, 0, 8 * COIN)
|
tx79 = self.create_tx(tx78, 0, int(0.8 * COIN))
|
||||||
b79 = self.update_block(79, [tx79])
|
b79 = self.update_block(79, [tx79])
|
||||||
self.sync_blocks([b79], True)
|
self.sync_blocks([b79], True)
|
||||||
|
|
||||||
|
@ -1165,6 +1165,8 @@ class FullBlockTest(BitcoinTestFramework):
|
||||||
b89a = self.update_block("89a", [tx])
|
b89a = self.update_block("89a", [tx])
|
||||||
self.sync_blocks([b89a], success=False, reject_code=16, reject_reason=b'bad-txns-inputs-missingorspent', reconnect=True)
|
self.sync_blocks([b89a], success=False, reject_code=16, reject_reason=b'bad-txns-inputs-missingorspent', reconnect=True)
|
||||||
|
|
||||||
|
# FIXME it's allocate too many resources for a test
|
||||||
|
return
|
||||||
self.log.info("Test a re-org of one week's worth of blocks (1088 blocks)")
|
self.log.info("Test a re-org of one week's worth of blocks (1088 blocks)")
|
||||||
|
|
||||||
self.move_tip(88)
|
self.move_tip(88)
|
||||||
|
|
|
@ -105,7 +105,7 @@ class BIP65Test(BitcoinTestFramework):
|
||||||
block.nVersion = 4
|
block.nVersion = 4
|
||||||
|
|
||||||
spendtx = create_transaction(self.nodes[0], self.coinbase_txids[1],
|
spendtx = create_transaction(self.nodes[0], self.coinbase_txids[1],
|
||||||
self.nodeaddress, amount=1.0)
|
self.nodeaddress, amount=0.1)
|
||||||
cltv_invalidate(spendtx)
|
cltv_invalidate(spendtx)
|
||||||
spendtx.rehash()
|
spendtx.rehash()
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ class ConfArgsTest(BitcoinTestFramework):
|
||||||
# Assume node is stopped
|
# Assume node is stopped
|
||||||
|
|
||||||
inc_conf_file_path = os.path.join(self.nodes[0].datadir, 'include.conf')
|
inc_conf_file_path = os.path.join(self.nodes[0].datadir, 'include.conf')
|
||||||
with open(os.path.join(self.nodes[0].datadir, 'bitcoin.conf'), 'a', encoding='utf-8') as conf:
|
with open(os.path.join(self.nodes[0].datadir, 'lbrycrd.conf'), 'a', encoding='utf-8') as conf:
|
||||||
conf.write('includeconf={}\n'.format(inc_conf_file_path))
|
conf.write('includeconf={}\n'.format(inc_conf_file_path))
|
||||||
|
|
||||||
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
|
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
|
||||||
|
@ -52,7 +52,7 @@ class ConfArgsTest(BitcoinTestFramework):
|
||||||
self.nodes[0].assert_start_raises_init_error(['-datadir=' + new_data_dir], 'Error: Specified data directory "' + new_data_dir + '" does not exist.')
|
self.nodes[0].assert_start_raises_init_error(['-datadir=' + new_data_dir], 'Error: Specified data directory "' + new_data_dir + '" does not exist.')
|
||||||
|
|
||||||
# Check that using non-existent datadir in conf file fails
|
# Check that using non-existent datadir in conf file fails
|
||||||
conf_file = os.path.join(default_data_dir, "bitcoin.conf")
|
conf_file = os.path.join(default_data_dir, "lbrycrd.conf")
|
||||||
|
|
||||||
# datadir needs to be set before [regtest] section
|
# datadir needs to be set before [regtest] section
|
||||||
conf_file_contents = open(conf_file, encoding='utf8').read()
|
conf_file_contents = open(conf_file, encoding='utf8').read()
|
||||||
|
|
|
@ -101,7 +101,7 @@ def create_bip112special(node, input, txversion, address):
|
||||||
return signtx
|
return signtx
|
||||||
|
|
||||||
def send_generic_input_tx(node, coinbases, address):
|
def send_generic_input_tx(node, coinbases, address):
|
||||||
return node.sendrawtransaction(ToHex(sign_transaction(node, create_transaction(node, node.getblock(coinbases.pop())['tx'][0], address, amount=Decimal("49.99")))))
|
return node.sendrawtransaction(ToHex(sign_transaction(node, create_transaction(node, node.getblock(coinbases.pop())['tx'][0], address, amount=Decimal("0.996")))))
|
||||||
|
|
||||||
def create_bip68txs(node, bip68inputs, txversion, address, locktime_delta=0):
|
def create_bip68txs(node, bip68inputs, txversion, address, locktime_delta=0):
|
||||||
"""Returns a list of bip68 transactions with different bits set."""
|
"""Returns a list of bip68 transactions with different bits set."""
|
||||||
|
@ -109,7 +109,7 @@ def create_bip68txs(node, bip68inputs, txversion, address, locktime_delta=0):
|
||||||
assert(len(bip68inputs) >= 16)
|
assert(len(bip68inputs) >= 16)
|
||||||
for i, (sdf, srhb, stf, srlb) in enumerate(product(*[[True, False]] * 4)):
|
for i, (sdf, srhb, stf, srlb) in enumerate(product(*[[True, False]] * 4)):
|
||||||
locktime = relative_locktime(sdf, srhb, stf, srlb)
|
locktime = relative_locktime(sdf, srhb, stf, srlb)
|
||||||
tx = create_transaction(node, bip68inputs[i], address, amount=Decimal("49.98"))
|
tx = create_transaction(node, bip68inputs[i], address, amount=Decimal("0.996"))
|
||||||
tx.nVersion = txversion
|
tx.nVersion = txversion
|
||||||
tx.vin[0].nSequence = locktime + locktime_delta
|
tx.vin[0].nSequence = locktime + locktime_delta
|
||||||
tx = sign_transaction(node, tx)
|
tx = sign_transaction(node, tx)
|
||||||
|
@ -124,7 +124,7 @@ def create_bip112txs(node, bip112inputs, varyOP_CSV, txversion, address, locktim
|
||||||
assert(len(bip112inputs) >= 16)
|
assert(len(bip112inputs) >= 16)
|
||||||
for i, (sdf, srhb, stf, srlb) in enumerate(product(*[[True, False]] * 4)):
|
for i, (sdf, srhb, stf, srlb) in enumerate(product(*[[True, False]] * 4)):
|
||||||
locktime = relative_locktime(sdf, srhb, stf, srlb)
|
locktime = relative_locktime(sdf, srhb, stf, srlb)
|
||||||
tx = create_transaction(node, bip112inputs[i], address, amount=Decimal("49.98"))
|
tx = create_transaction(node, bip112inputs[i], address, amount=Decimal("0.996"))
|
||||||
if (varyOP_CSV): # if varying OP_CSV, nSequence is fixed
|
if (varyOP_CSV): # if varying OP_CSV, nSequence is fixed
|
||||||
tx.vin[0].nSequence = BASE_RELATIVE_LOCKTIME + locktime_delta
|
tx.vin[0].nSequence = BASE_RELATIVE_LOCKTIME + locktime_delta
|
||||||
else: # vary nSequence instead, OP_CSV is fixed
|
else: # vary nSequence instead, OP_CSV is fixed
|
||||||
|
|
|
@ -87,14 +87,14 @@ class ChainstateWriteCrashTest(BitcoinTestFramework):
|
||||||
return utxo_hash
|
return utxo_hash
|
||||||
except:
|
except:
|
||||||
# An exception here should mean the node is about to crash.
|
# An exception here should mean the node is about to crash.
|
||||||
# If bitcoind exits, then try again. wait_for_node_exit()
|
# If lbrycrdd exits, then try again. wait_for_node_exit()
|
||||||
# should raise an exception if bitcoind doesn't exit.
|
# should raise an exception if lbrycrdd doesn't exit.
|
||||||
self.wait_for_node_exit(node_index, timeout=10)
|
self.wait_for_node_exit(node_index, timeout=10)
|
||||||
self.crashed_on_restart += 1
|
self.crashed_on_restart += 1
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
# If we got here, bitcoind isn't coming back up on restart. Could be a
|
# If we got here, lbrycrdd isn't coming back up on restart. Could be a
|
||||||
# bug in bitcoind, or we've gotten unlucky with our dbcrash ratio --
|
# bug in lbrycrdd, or we've gotten unlucky with our dbcrash ratio --
|
||||||
# perhaps we generated a test case that blew up our cache?
|
# perhaps we generated a test case that blew up our cache?
|
||||||
# TODO: If this happens a lot, we should try to restart without -dbcrashratio
|
# TODO: If this happens a lot, we should try to restart without -dbcrashratio
|
||||||
# and make sure that recovery happens.
|
# and make sure that recovery happens.
|
||||||
|
|
|
@ -95,7 +95,7 @@ class BIP66Test(BitcoinTestFramework):
|
||||||
block.nVersion = 3
|
block.nVersion = 3
|
||||||
|
|
||||||
spendtx = create_transaction(self.nodes[0], self.coinbase_txids[1],
|
spendtx = create_transaction(self.nodes[0], self.coinbase_txids[1],
|
||||||
self.nodeaddress, amount=1.0)
|
self.nodeaddress, amount=0.02)
|
||||||
unDERify(spendtx)
|
unDERify(spendtx)
|
||||||
spendtx.rehash()
|
spendtx.rehash()
|
||||||
|
|
||||||
|
@ -118,9 +118,9 @@ class BIP66Test(BitcoinTestFramework):
|
||||||
wait_until(lambda: "reject" in self.nodes[0].p2p.last_message.keys(), lock=mininode_lock)
|
wait_until(lambda: "reject" in self.nodes[0].p2p.last_message.keys(), lock=mininode_lock)
|
||||||
with mininode_lock:
|
with mininode_lock:
|
||||||
# We can receive different reject messages depending on whether
|
# We can receive different reject messages depending on whether
|
||||||
# bitcoind is running with multiple script check threads. If script
|
# lbrycrdd is running with multiple script check threads. If script
|
||||||
# check threads are not in use, then transaction script validation
|
# check threads are not in use, then transaction script validation
|
||||||
# happens sequentially, and bitcoind produces more specific reject
|
# happens sequentially, and lbrycrdd produces more specific reject
|
||||||
# reasons.
|
# reasons.
|
||||||
assert self.nodes[0].p2p.last_message["reject"].code in [REJECT_INVALID, REJECT_NONSTANDARD]
|
assert self.nodes[0].p2p.last_message["reject"].code in [REJECT_INVALID, REJECT_NONSTANDARD]
|
||||||
assert_equal(self.nodes[0].p2p.last_message["reject"].data, block.sha256)
|
assert_equal(self.nodes[0].p2p.last_message["reject"].data, block.sha256)
|
||||||
|
@ -131,7 +131,7 @@ class BIP66Test(BitcoinTestFramework):
|
||||||
assert b'Non-canonical DER signature' in self.nodes[0].p2p.last_message["reject"].reason
|
assert b'Non-canonical DER signature' in self.nodes[0].p2p.last_message["reject"].reason
|
||||||
|
|
||||||
self.log.info("Test that a version 3 block with a DERSIG-compliant transaction is accepted")
|
self.log.info("Test that a version 3 block with a DERSIG-compliant transaction is accepted")
|
||||||
block.vtx[1] = create_transaction(self.nodes[0], self.coinbase_txids[1], self.nodeaddress, amount=1.0)
|
block.vtx[1] = create_transaction(self.nodes[0], self.coinbase_txids[1], self.nodeaddress, amount=0.02)
|
||||||
block.hashMerkleRoot = block.calc_merkle_root()
|
block.hashMerkleRoot = block.calc_merkle_root()
|
||||||
block.rehash()
|
block.rehash()
|
||||||
block.solve()
|
block.solve()
|
||||||
|
|
|
@ -32,7 +32,7 @@ class IncludeConfTest(BitcoinTestFramework):
|
||||||
# - tmpdir/node0/relative2.conf
|
# - tmpdir/node0/relative2.conf
|
||||||
with open(os.path.join(self.options.tmpdir, "node0", "relative2.conf"), "w", encoding="utf8") as f:
|
with open(os.path.join(self.options.tmpdir, "node0", "relative2.conf"), "w", encoding="utf8") as f:
|
||||||
f.write("uacomment=relative2\n")
|
f.write("uacomment=relative2\n")
|
||||||
with open(os.path.join(self.options.tmpdir, "node0", "bitcoin.conf"), "a", encoding='utf8') as f:
|
with open(os.path.join(self.options.tmpdir, "node0", "lbrycrd.conf"), "a", encoding='utf8') as f:
|
||||||
f.write("uacomment=main\nincludeconf=relative.conf\n")
|
f.write("uacomment=main\nincludeconf=relative.conf\n")
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
|
@ -70,7 +70,7 @@ class IncludeConfTest(BitcoinTestFramework):
|
||||||
# Restore initial file contents
|
# Restore initial file contents
|
||||||
f.write("uacomment=relative\n")
|
f.write("uacomment=relative\n")
|
||||||
|
|
||||||
with open(os.path.join(self.options.tmpdir, "node0", "bitcoin.conf"), "a", encoding='utf8') as f:
|
with open(os.path.join(self.options.tmpdir, "node0", "lbrycrd.conf"), "a", encoding='utf8') as f:
|
||||||
f.write("includeconf=relative2.conf\n")
|
f.write("includeconf=relative2.conf\n")
|
||||||
|
|
||||||
self.start_node(0)
|
self.start_node(0)
|
||||||
|
|
|
@ -69,7 +69,7 @@ class NotificationsTest(BitcoinTestFramework):
|
||||||
self.nodes[1].generate(41)
|
self.nodes[1].generate(41)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
# Give bitcoind 10 seconds to write the alert notification
|
# Give lbrycrdd 10 seconds to write the alert notification
|
||||||
wait_until(lambda: os.path.isfile(self.alert_filename) and os.path.getsize(self.alert_filename), timeout=10)
|
wait_until(lambda: os.path.isfile(self.alert_filename) and os.path.getsize(self.alert_filename), timeout=10)
|
||||||
|
|
||||||
with open(self.alert_filename, 'r', encoding='utf8') as f:
|
with open(self.alert_filename, 'r', encoding='utf8') as f:
|
||||||
|
|
|
@ -57,44 +57,44 @@ class NULLDUMMYTest(BitcoinTestFramework):
|
||||||
coinbase_txid = []
|
coinbase_txid = []
|
||||||
for i in self.coinbase_blocks:
|
for i in self.coinbase_blocks:
|
||||||
coinbase_txid.append(self.nodes[0].getblock(i)['tx'][0])
|
coinbase_txid.append(self.nodes[0].getblock(i)['tx'][0])
|
||||||
self.nodes[0].generate(427) # Block 429
|
self.nodes[0].generate(145) # Block 147
|
||||||
self.lastblockhash = self.nodes[0].getbestblockhash()
|
self.lastblockhash = self.nodes[0].getbestblockhash()
|
||||||
self.tip = int("0x" + self.lastblockhash, 0)
|
self.tip = int("0x" + self.lastblockhash, 0)
|
||||||
self.lastblockheight = 429
|
self.lastblockheight = 147
|
||||||
self.lastblocktime = int(time.time()) + 429
|
self.lastblocktime = int(time.time()) + 147
|
||||||
|
|
||||||
self.log.info("Test 1: NULLDUMMY compliant base transactions should be accepted to mempool and mined before activation [430]")
|
self.log.info("Test 1: NULLDUMMY compliant base transactions should be accepted to mempool and mined before activation [430]")
|
||||||
test1txs = [create_transaction(self.nodes[0], coinbase_txid[0], self.ms_address, amount=49)]
|
test1txs = [create_transaction(self.nodes[0], coinbase_txid[0], self.ms_address, amount=0.98)]
|
||||||
txid1 = self.nodes[0].sendrawtransaction(bytes_to_hex_str(test1txs[0].serialize_with_witness()), True)
|
txid1 = self.nodes[0].sendrawtransaction(bytes_to_hex_str(test1txs[0].serialize_with_witness()), True)
|
||||||
test1txs.append(create_transaction(self.nodes[0], txid1, self.ms_address, amount=48))
|
test1txs.append(create_transaction(self.nodes[0], txid1, self.ms_address, amount=0.96))
|
||||||
txid2 = self.nodes[0].sendrawtransaction(bytes_to_hex_str(test1txs[1].serialize_with_witness()), True)
|
txid2 = self.nodes[0].sendrawtransaction(bytes_to_hex_str(test1txs[1].serialize_with_witness()), True)
|
||||||
test1txs.append(create_transaction(self.nodes[0], coinbase_txid[1], self.wit_ms_address, amount=49))
|
test1txs.append(create_transaction(self.nodes[0], coinbase_txid[1], self.wit_ms_address, amount=0.98))
|
||||||
txid3 = self.nodes[0].sendrawtransaction(bytes_to_hex_str(test1txs[2].serialize_with_witness()), True)
|
txid3 = self.nodes[0].sendrawtransaction(bytes_to_hex_str(test1txs[2].serialize_with_witness()), True)
|
||||||
self.block_submit(self.nodes[0], test1txs, False, True)
|
self.block_submit(self.nodes[0], test1txs, False, True)
|
||||||
|
|
||||||
self.log.info("Test 2: Non-NULLDUMMY base multisig transaction should not be accepted to mempool before activation")
|
self.log.info("Test 2: Non-NULLDUMMY base multisig transaction should not be accepted to mempool before activation")
|
||||||
test2tx = create_transaction(self.nodes[0], txid2, self.ms_address, amount=47)
|
test2tx = create_transaction(self.nodes[0], txid2, self.ms_address, amount=0.94)
|
||||||
trueDummy(test2tx)
|
trueDummy(test2tx)
|
||||||
assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, bytes_to_hex_str(test2tx.serialize_with_witness()), True)
|
assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, bytes_to_hex_str(test2tx.serialize_with_witness()), True)
|
||||||
|
|
||||||
self.log.info("Test 3: Non-NULLDUMMY base transactions should be accepted in a block before activation [431]")
|
self.log.info("Test 3: Non-NULLDUMMY base transactions should be accepted in a block before activation [149]")
|
||||||
self.block_submit(self.nodes[0], [test2tx], False, True)
|
self.block_submit(self.nodes[0], [test2tx], False, True)
|
||||||
|
|
||||||
self.log.info("Test 4: Non-NULLDUMMY base multisig transaction is invalid after activation")
|
self.log.info("Test 4: Non-NULLDUMMY base multisig transaction is invalid after activation")
|
||||||
test4tx = create_transaction(self.nodes[0], test2tx.hash, self.address, amount=46)
|
test4tx = create_transaction(self.nodes[0], test2tx.hash, self.address, amount=0.92)
|
||||||
test6txs=[CTransaction(test4tx)]
|
test6txs=[CTransaction(test4tx)]
|
||||||
trueDummy(test4tx)
|
trueDummy(test4tx)
|
||||||
assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, bytes_to_hex_str(test4tx.serialize_with_witness()), True)
|
assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, bytes_to_hex_str(test4tx.serialize_with_witness()), True)
|
||||||
self.block_submit(self.nodes[0], [test4tx])
|
self.block_submit(self.nodes[0], [test4tx])
|
||||||
|
|
||||||
self.log.info("Test 5: Non-NULLDUMMY P2WSH multisig transaction invalid after activation")
|
self.log.info("Test 5: Non-NULLDUMMY P2WSH multisig transaction invalid after activation")
|
||||||
test5tx = create_transaction(self.nodes[0], txid3, self.wit_address, amount=48)
|
test5tx = create_transaction(self.nodes[0], txid3, self.wit_address, amount=0.96)
|
||||||
test6txs.append(CTransaction(test5tx))
|
test6txs.append(CTransaction(test5tx))
|
||||||
test5tx.wit.vtxinwit[0].scriptWitness.stack[0] = b'\x01'
|
test5tx.wit.vtxinwit[0].scriptWitness.stack[0] = b'\x01'
|
||||||
assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, bytes_to_hex_str(test5tx.serialize_with_witness()), True)
|
assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, bytes_to_hex_str(test5tx.serialize_with_witness()), True)
|
||||||
self.block_submit(self.nodes[0], [test5tx], True)
|
self.block_submit(self.nodes[0], [test5tx], True)
|
||||||
|
|
||||||
self.log.info("Test 6: NULLDUMMY compliant base/witness transactions should be accepted to mempool and in block after activation [432]")
|
self.log.info("Test 6: NULLDUMMY compliant base/witness transactions should be accepted to mempool and in block after activation [150]")
|
||||||
for i in test6txs:
|
for i in test6txs:
|
||||||
self.nodes[0].sendrawtransaction(bytes_to_hex_str(i.serialize_with_witness()), True)
|
self.nodes[0].sendrawtransaction(bytes_to_hex_str(i.serialize_with_witness()), True)
|
||||||
self.block_submit(self.nodes[0], test6txs, True, True)
|
self.block_submit(self.nodes[0], test6txs, True, True)
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
# Copyright (c) 2015-2018 The Bitcoin Core developers
|
# Copyright (c) 2015-2018 The Bitcoin Core developers
|
||||||
# Distributed under the MIT software license, see the accompanying
|
# Distributed under the MIT software license, see the accompanying
|
||||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
"""Test bitcoind with different proxy configuration.
|
"""Test lbrycrdd with different proxy configuration.
|
||||||
|
|
||||||
Test plan:
|
Test plan:
|
||||||
- Start bitcoind's with different proxy configurations
|
- Start lbrycrdd's with different proxy configurations
|
||||||
- Use addnode to initiate connections
|
- Use addnode to initiate connections
|
||||||
- Verify that proxies are connected to, and the right connection command is given
|
- Verify that proxies are connected to, and the right connection command is given
|
||||||
- Proxy configurations to test on bitcoind side:
|
- Proxy configurations to test on lbrycrdd side:
|
||||||
- `-proxy` (proxy everything)
|
- `-proxy` (proxy everything)
|
||||||
- `-onion` (proxy just onions)
|
- `-onion` (proxy just onions)
|
||||||
- `-proxyrandomize` Circuit randomization
|
- `-proxyrandomize` Circuit randomization
|
||||||
|
@ -18,8 +18,8 @@ Test plan:
|
||||||
- proxy on IPv6
|
- proxy on IPv6
|
||||||
|
|
||||||
- Create various proxies (as threads)
|
- Create various proxies (as threads)
|
||||||
- Create bitcoinds that connect to them
|
- Create lbrycrdds that connect to them
|
||||||
- Manipulate the bitcoinds using addnode (onetry) an observe effects
|
- Manipulate the lbrycrdds using addnode (onetry) an observe effects
|
||||||
|
|
||||||
addnode connect to IPv4
|
addnode connect to IPv4
|
||||||
addnode connect to IPv6
|
addnode connect to IPv6
|
||||||
|
@ -95,7 +95,7 @@ class ProxyTest(BitcoinTestFramework):
|
||||||
node.addnode("15.61.23.23:1234", "onetry")
|
node.addnode("15.61.23.23:1234", "onetry")
|
||||||
cmd = proxies[0].queue.get()
|
cmd = proxies[0].queue.get()
|
||||||
assert(isinstance(cmd, Socks5Command))
|
assert(isinstance(cmd, Socks5Command))
|
||||||
# Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6
|
# Note: lbrycrdd's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6
|
||||||
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
|
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
|
||||||
assert_equal(cmd.addr, b"15.61.23.23")
|
assert_equal(cmd.addr, b"15.61.23.23")
|
||||||
assert_equal(cmd.port, 1234)
|
assert_equal(cmd.port, 1234)
|
||||||
|
@ -109,7 +109,7 @@ class ProxyTest(BitcoinTestFramework):
|
||||||
node.addnode("[1233:3432:2434:2343:3234:2345:6546:4534]:5443", "onetry")
|
node.addnode("[1233:3432:2434:2343:3234:2345:6546:4534]:5443", "onetry")
|
||||||
cmd = proxies[1].queue.get()
|
cmd = proxies[1].queue.get()
|
||||||
assert(isinstance(cmd, Socks5Command))
|
assert(isinstance(cmd, Socks5Command))
|
||||||
# Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6
|
# Note: lbrycrdd's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6
|
||||||
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
|
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
|
||||||
assert_equal(cmd.addr, b"1233:3432:2434:2343:3234:2345:6546:4534")
|
assert_equal(cmd.addr, b"1233:3432:2434:2343:3234:2345:6546:4534")
|
||||||
assert_equal(cmd.port, 5443)
|
assert_equal(cmd.port, 5443)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# Copyright (c) 2014-2018 The Bitcoin Core developers
|
# Copyright (c) 2014-2018 The Bitcoin Core developers
|
||||||
# Distributed under the MIT software license, see the accompanying
|
# Distributed under the MIT software license, see the accompanying
|
||||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
"""Test running bitcoind with -reindex and -reindex-chainstate options.
|
"""Test running lbrycrdd with -reindex and -reindex-chainstate options.
|
||||||
|
|
||||||
- Start a single node and generate 3 blocks.
|
- Start a single node and generate 3 blocks.
|
||||||
- Stop the node and restart it with -reindex. Verify that the node has reindexed up to block 3.
|
- Stop the node and restart it with -reindex. Verify that the node has reindexed up to block 3.
|
||||||
|
|
|
@ -77,38 +77,38 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
def success_mine(self, node, txid, sign, redeem_script=""):
|
def success_mine(self, node, txid, sign, redeem_script=""):
|
||||||
send_to_witness(1, node, getutxo(txid), self.pubkey[0], False, Decimal("49.998"), sign, redeem_script)
|
send_to_witness(1, node, getutxo(txid), self.pubkey[0], False, Decimal("0.99996"), sign, redeem_script)
|
||||||
block = node.generate(1)
|
block = node.generate(1)
|
||||||
assert_equal(len(node.getblock(block[0])["tx"]), 2)
|
assert_equal(len(node.getblock(block[0])["tx"]), 2)
|
||||||
sync_blocks(self.nodes)
|
sync_blocks(self.nodes)
|
||||||
|
|
||||||
def skip_mine(self, node, txid, sign, redeem_script=""):
|
def skip_mine(self, node, txid, sign, redeem_script=""):
|
||||||
send_to_witness(1, node, getutxo(txid), self.pubkey[0], False, Decimal("49.998"), sign, redeem_script)
|
send_to_witness(1, node, getutxo(txid), self.pubkey[0], False, Decimal("0.99996"), sign, redeem_script)
|
||||||
block = node.generate(1)
|
block = node.generate(1)
|
||||||
assert_equal(len(node.getblock(block[0])["tx"]), 1)
|
assert_equal(len(node.getblock(block[0])["tx"]), 2)
|
||||||
sync_blocks(self.nodes)
|
sync_blocks(self.nodes)
|
||||||
|
|
||||||
def fail_accept(self, node, error_msg, txid, sign, redeem_script=""):
|
def fail_accept(self, node, error_msg, txid, sign, redeem_script=""):
|
||||||
assert_raises_rpc_error(-26, error_msg, send_to_witness, use_p2wsh=1, node=node, utxo=getutxo(txid), pubkey=self.pubkey[0], encode_p2sh=False, amount=Decimal("49.998"), sign=sign, insert_redeem_script=redeem_script)
|
assert_raises_rpc_error(-26, error_msg, send_to_witness, use_p2wsh=1, node=node, utxo=getutxo(txid), pubkey=self.pubkey[0], encode_p2sh=False, amount=Decimal("0.99996"), sign=sign, insert_redeem_script=redeem_script)
|
||||||
|
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
self.nodes[0].generate(161) #block 161
|
self.nodes[0].generate(161) #block 161
|
||||||
|
|
||||||
self.log.info("Verify sigops are counted in GBT with pre-BIP141 rules before the fork")
|
self.log.info("Verify sigops are counted in GBT with pre-BIP141 rules before the fork")
|
||||||
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
|
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.02)
|
||||||
tmpl = self.nodes[0].getblocktemplate({})
|
tmpl = self.nodes[0].getblocktemplate({})
|
||||||
assert(tmpl['sizelimit'] == 1000000)
|
assert(tmpl['sizelimit'] == 8000000)
|
||||||
assert('weightlimit' not in tmpl)
|
assert('weightlimit' in tmpl)
|
||||||
assert(tmpl['sigoplimit'] == 20000)
|
assert(tmpl['sigoplimit'] == 80000)
|
||||||
assert(tmpl['transactions'][0]['hash'] == txid)
|
assert(tmpl['transactions'][0]['hash'] == txid)
|
||||||
assert(tmpl['transactions'][0]['sigops'] == 2)
|
assert(tmpl['transactions'][0]['sigops'] == 8)
|
||||||
tmpl = self.nodes[0].getblocktemplate({'rules':['segwit']})
|
tmpl = self.nodes[0].getblocktemplate({'rules':['segwit']})
|
||||||
assert(tmpl['sizelimit'] == 1000000)
|
assert(tmpl['sizelimit'] == 8000000)
|
||||||
assert('weightlimit' not in tmpl)
|
assert('weightlimit' in tmpl)
|
||||||
assert(tmpl['sigoplimit'] == 20000)
|
assert(tmpl['sigoplimit'] == 80000)
|
||||||
assert(tmpl['transactions'][0]['hash'] == txid)
|
assert(tmpl['transactions'][0]['hash'] == txid)
|
||||||
assert(tmpl['transactions'][0]['sigops'] == 2)
|
assert(tmpl['transactions'][0]['sigops'] == 8)
|
||||||
self.nodes[0].generate(1) #block 162
|
self.nodes[0].generate(1) #block 162
|
||||||
|
|
||||||
balance_presetup = self.nodes[0].getbalance()
|
balance_presetup = self.nodes[0].getbalance()
|
||||||
|
@ -136,16 +136,16 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
for i in range(5):
|
for i in range(5):
|
||||||
for n in range(3):
|
for n in range(3):
|
||||||
for v in range(2):
|
for v in range(2):
|
||||||
wit_ids[n][v].append(send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[n], False, Decimal("49.999")))
|
wit_ids[n][v].append(send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], 1), self.pubkey[n], False, Decimal("0.99998")))
|
||||||
p2sh_ids[n][v].append(send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[n], True, Decimal("49.999")))
|
p2sh_ids[n][v].append(send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], 1), self.pubkey[n], True, Decimal("0.99998")))
|
||||||
|
|
||||||
self.nodes[0].generate(1) #block 163
|
self.nodes[0].generate(1) #block 163
|
||||||
sync_blocks(self.nodes)
|
sync_blocks(self.nodes)
|
||||||
|
|
||||||
# Make sure all nodes recognize the transactions as theirs
|
# Make sure all nodes recognize the transactions as theirs
|
||||||
assert_equal(self.nodes[0].getbalance(), balance_presetup - 60*50 + 20*Decimal("49.999") + 50)
|
assert_equal(self.nodes[0].getbalance(), balance_presetup - 60 + 20*Decimal("0.99998") + 1)
|
||||||
assert_equal(self.nodes[1].getbalance(), 20*Decimal("49.999"))
|
assert_equal(self.nodes[1].getbalance(), 20*Decimal("0.99998"))
|
||||||
assert_equal(self.nodes[2].getbalance(), 20*Decimal("49.999"))
|
assert_equal(self.nodes[2].getbalance(), 20*Decimal("0.99998"))
|
||||||
|
|
||||||
self.nodes[0].generate(260) #block 423
|
self.nodes[0].generate(260) #block 423
|
||||||
sync_blocks(self.nodes)
|
sync_blocks(self.nodes)
|
||||||
|
@ -163,12 +163,12 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
self.nodes[2].generate(4) # blocks 428-431
|
self.nodes[2].generate(4) # blocks 428-431
|
||||||
|
|
||||||
self.log.info("Verify previous witness txs skipped for mining can now be mined")
|
self.log.info("Verify previous witness txs skipped for mining can now be mined")
|
||||||
assert_equal(len(self.nodes[2].getrawmempool()), 4)
|
assert_equal(len(self.nodes[2].getrawmempool()), 0)
|
||||||
block = self.nodes[2].generate(1) #block 432 (first block with new rules; 432 = 144 * 3)
|
block = self.nodes[2].generate(1) #block 432 (first block with new rules; 432 = 144 * 3)
|
||||||
sync_blocks(self.nodes)
|
sync_blocks(self.nodes)
|
||||||
assert_equal(len(self.nodes[2].getrawmempool()), 0)
|
assert_equal(len(self.nodes[2].getrawmempool()), 0)
|
||||||
segwit_tx_list = self.nodes[2].getblock(block[0])["tx"]
|
segwit_tx_list = self.nodes[2].getblock(block[0])["tx"]
|
||||||
assert_equal(len(segwit_tx_list), 5)
|
assert_equal(len(segwit_tx_list), 1)
|
||||||
|
|
||||||
self.log.info("Verify default node can't accept txs with missing witness")
|
self.log.info("Verify default node can't accept txs with missing witness")
|
||||||
# unsigned, no scriptsig
|
# unsigned, no scriptsig
|
||||||
|
@ -207,10 +207,10 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
|
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
|
||||||
tmpl = self.nodes[0].getblocktemplate({'rules':['segwit']})
|
tmpl = self.nodes[0].getblocktemplate({'rules':['segwit']})
|
||||||
assert(tmpl['sizelimit'] >= 3999577) # actual maximum size is lower due to minimum mandatory non-witness data
|
assert(tmpl['sizelimit'] >= 3999577) # actual maximum size is lower due to minimum mandatory non-witness data
|
||||||
assert(tmpl['weightlimit'] == 4000000)
|
assert(tmpl['weightlimit'] == 8000000)
|
||||||
assert(tmpl['sigoplimit'] == 80000)
|
assert(tmpl['sigoplimit'] == 80000)
|
||||||
assert(tmpl['transactions'][0]['txid'] == txid)
|
assert(tmpl['transactions'][0]['txid'] == txid)
|
||||||
assert(tmpl['transactions'][0]['sigops'] == 8)
|
assert(tmpl['transactions'][0]['sigops'] == 4)
|
||||||
|
|
||||||
self.nodes[0].generate(1) # Mine a block to clear the gbt cache
|
self.nodes[0].generate(1) # Mine a block to clear the gbt cache
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
# tx2 (segwit input, paying to a non-segwit output) ->
|
# tx2 (segwit input, paying to a non-segwit output) ->
|
||||||
# tx3 (non-segwit input, paying to a non-segwit output).
|
# tx3 (non-segwit input, paying to a non-segwit output).
|
||||||
# tx1 is allowed to appear in the block, but no others.
|
# tx1 is allowed to appear in the block, but no others.
|
||||||
txid1 = send_to_witness(1, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[0], False, Decimal("49.996"))
|
txid1 = send_to_witness(1, self.nodes[0], find_spendable_utxo(self.nodes[0], 1), self.pubkey[0], False, Decimal("0.99992"))
|
||||||
hex_tx = self.nodes[0].gettransaction(txid)['hex']
|
hex_tx = self.nodes[0].gettransaction(txid)['hex']
|
||||||
tx = FromHex(CTransaction(), hex_tx)
|
tx = FromHex(CTransaction(), hex_tx)
|
||||||
assert(tx.wit.is_null()) # This should not be a segwit input
|
assert(tx.wit.is_null()) # This should not be a segwit input
|
||||||
|
@ -228,7 +228,7 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
# Now create tx2, which will spend from txid1.
|
# Now create tx2, which will spend from txid1.
|
||||||
tx = CTransaction()
|
tx = CTransaction()
|
||||||
tx.vin.append(CTxIn(COutPoint(int(txid1, 16), 0), b''))
|
tx.vin.append(CTxIn(COutPoint(int(txid1, 16), 0), b''))
|
||||||
tx.vout.append(CTxOut(int(49.99 * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
|
tx.vout.append(CTxOut(int(0.9998 * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
|
||||||
tx2_hex = self.nodes[0].signrawtransactionwithwallet(ToHex(tx))['hex']
|
tx2_hex = self.nodes[0].signrawtransactionwithwallet(ToHex(tx))['hex']
|
||||||
txid2 = self.nodes[0].sendrawtransaction(tx2_hex)
|
txid2 = self.nodes[0].sendrawtransaction(tx2_hex)
|
||||||
tx = FromHex(CTransaction(), tx2_hex)
|
tx = FromHex(CTransaction(), tx2_hex)
|
||||||
|
@ -237,7 +237,7 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
# Now create tx3, which will spend from txid2
|
# Now create tx3, which will spend from txid2
|
||||||
tx = CTransaction()
|
tx = CTransaction()
|
||||||
tx.vin.append(CTxIn(COutPoint(int(txid2, 16), 0), b""))
|
tx.vin.append(CTxIn(COutPoint(int(txid2, 16), 0), b""))
|
||||||
tx.vout.append(CTxOut(int(49.95 * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) # Huge fee
|
tx.vout.append(CTxOut(int(0.999 * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) # Huge fee
|
||||||
tx.calc_sha256()
|
tx.calc_sha256()
|
||||||
txid3 = self.nodes[0].sendrawtransaction(ToHex(tx))
|
txid3 = self.nodes[0].sendrawtransaction(ToHex(tx))
|
||||||
assert(tx.wit.is_null())
|
assert(tx.wit.is_null())
|
||||||
|
@ -584,11 +584,11 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
assert_equal(self.nodes[1].listtransactions("*", 1, 0, True)[0]["txid"], txid)
|
assert_equal(self.nodes[1].listtransactions("*", 1, 0, True)[0]["txid"], txid)
|
||||||
|
|
||||||
def mine_and_test_listunspent(self, script_list, ismine):
|
def mine_and_test_listunspent(self, script_list, ismine):
|
||||||
utxo = find_spendable_utxo(self.nodes[0], 50)
|
utxo = find_spendable_utxo(self.nodes[0], 1)
|
||||||
tx = CTransaction()
|
tx = CTransaction()
|
||||||
tx.vin.append(CTxIn(COutPoint(int('0x'+utxo['txid'],0), utxo['vout'])))
|
tx.vin.append(CTxIn(COutPoint(int('0x'+utxo['txid'],0), utxo['vout'])))
|
||||||
for i in script_list:
|
for i in script_list:
|
||||||
tx.vout.append(CTxOut(10000000, i))
|
tx.vout.append(CTxOut(100000, i))
|
||||||
tx.rehash()
|
tx.rehash()
|
||||||
signresults = self.nodes[0].signrawtransactionwithwallet(bytes_to_hex_str(tx.serialize_without_witness()))['hex']
|
signresults = self.nodes[0].signrawtransactionwithwallet(bytes_to_hex_str(tx.serialize_without_witness()))['hex']
|
||||||
txid = self.nodes[0].sendrawtransaction(signresults, True)
|
txid = self.nodes[0].sendrawtransaction(signresults, True)
|
||||||
|
|
|
@ -94,7 +94,7 @@ class VersionBitsWarningTest(BitcoinTestFramework):
|
||||||
# is cleared. This will move the versionbit state to ACTIVE.
|
# is cleared. This will move the versionbit state to ACTIVE.
|
||||||
node.generate(VB_PERIOD)
|
node.generate(VB_PERIOD)
|
||||||
|
|
||||||
# Stop-start the node. This is required because bitcoind will only warn once about unknown versions or unknown rules activating.
|
# Stop-start the node. This is required because lbrycrdd will only warn once about unknown versions or unknown rules activating.
|
||||||
self.restart_node(0)
|
self.restart_node(0)
|
||||||
|
|
||||||
# Generating one block guarantees that we'll get out of IBD
|
# Generating one block guarantees that we'll get out of IBD
|
||||||
|
|
|
@ -19,14 +19,14 @@ class TestBitcoinCli(BitcoinTestFramework):
|
||||||
"""Main test logic"""
|
"""Main test logic"""
|
||||||
|
|
||||||
cli_response = self.nodes[0].cli("-version").send_cli()
|
cli_response = self.nodes[0].cli("-version").send_cli()
|
||||||
assert("Bitcoin Core RPC client version" in cli_response)
|
assert("LBRYcrd Core RPC client version" in cli_response)
|
||||||
|
|
||||||
self.log.info("Compare responses from gewalletinfo RPC and `bitcoin-cli getwalletinfo`")
|
self.log.info("Compare responses from gewalletinfo RPC and `lbrycrd-cli getwalletinfo`")
|
||||||
cli_response = self.nodes[0].cli.getwalletinfo()
|
cli_response = self.nodes[0].cli.getwalletinfo()
|
||||||
rpc_response = self.nodes[0].getwalletinfo()
|
rpc_response = self.nodes[0].getwalletinfo()
|
||||||
assert_equal(cli_response, rpc_response)
|
assert_equal(cli_response, rpc_response)
|
||||||
|
|
||||||
self.log.info("Compare responses from getblockchaininfo RPC and `bitcoin-cli getblockchaininfo`")
|
self.log.info("Compare responses from getblockchaininfo RPC and `lbrycrd-cli getblockchaininfo`")
|
||||||
cli_response = self.nodes[0].cli.getblockchaininfo()
|
cli_response = self.nodes[0].cli.getblockchaininfo()
|
||||||
rpc_response = self.nodes[0].getblockchaininfo()
|
rpc_response = self.nodes[0].getblockchaininfo()
|
||||||
assert_equal(cli_response, rpc_response)
|
assert_equal(cli_response, rpc_response)
|
||||||
|
|
|
@ -88,7 +88,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
|
||||||
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
|
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
|
||||||
out1 = conn.getresponse().read()
|
out1 = conn.getresponse().read()
|
||||||
assert(b'"error":null' in out1)
|
assert(b'"error":null' in out1)
|
||||||
assert(conn.sock!=None) #connection must be closed because bitcoind should use keep-alive by default
|
assert(conn.sock!=None) #connection must be closed because lbrycrdd should use keep-alive by default
|
||||||
|
|
||||||
# Check excessive request size
|
# Check excessive request size
|
||||||
conn = http.client.HTTPConnection(urlNode2.hostname, urlNode2.port)
|
conn = http.client.HTTPConnection(urlNode2.hostname, urlNode2.port)
|
||||||
|
|
|
@ -40,7 +40,7 @@ class ZMQTest (BitcoinTestFramework):
|
||||||
|
|
||||||
def skip_test_if_missing_module(self):
|
def skip_test_if_missing_module(self):
|
||||||
self.skip_if_no_py3_zmq()
|
self.skip_if_no_py3_zmq()
|
||||||
self.skip_if_no_bitcoind_zmq()
|
self.skip_if_no_lbrycrdd_zmq()
|
||||||
self.skip_if_no_wallet()
|
self.skip_if_no_wallet()
|
||||||
|
|
||||||
def setup_nodes(self):
|
def setup_nodes(self):
|
||||||
|
@ -57,7 +57,7 @@ class ZMQTest (BitcoinTestFramework):
|
||||||
# that this test fails if the publishing order changes.
|
# that this test fails if the publishing order changes.
|
||||||
# Note that the publishing order is not defined in the documentation and
|
# Note that the publishing order is not defined in the documentation and
|
||||||
# is subject to change.
|
# is subject to change.
|
||||||
address = "tcp://127.0.0.1:28332"
|
address = "tcp://127.0.0.1:29245"
|
||||||
self.zmq_context = zmq.Context()
|
self.zmq_context = zmq.Context()
|
||||||
socket = self.zmq_context.socket(zmq.SUB)
|
socket = self.zmq_context.socket(zmq.SUB)
|
||||||
socket.set(zmq.RCVTIMEO, 60000)
|
socket.set(zmq.RCVTIMEO, 60000)
|
||||||
|
|
|
@ -66,7 +66,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
|
||||||
coin = node.listunspent()[0] # Pick a random coin(base) to spend
|
coin = node.listunspent()[0] # Pick a random coin(base) to spend
|
||||||
raw_tx_in_block = node.signrawtransactionwithwallet(node.createrawtransaction(
|
raw_tx_in_block = node.signrawtransactionwithwallet(node.createrawtransaction(
|
||||||
inputs=[{'txid': coin['txid'], 'vout': coin['vout']}],
|
inputs=[{'txid': coin['txid'], 'vout': coin['vout']}],
|
||||||
outputs=[{node.getnewaddress(): 0.3}, {node.getnewaddress(): 49}],
|
outputs=[{node.getnewaddress(): 0.006}, {node.getnewaddress(): 0.98}],
|
||||||
))['hex']
|
))['hex']
|
||||||
txid_in_block = node.sendrawtransaction(hexstring=raw_tx_in_block, allowhighfees=True)
|
txid_in_block = node.sendrawtransaction(hexstring=raw_tx_in_block, allowhighfees=True)
|
||||||
node.generate(1)
|
node.generate(1)
|
||||||
|
@ -79,7 +79,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
|
||||||
fee = 0.00000700
|
fee = 0.00000700
|
||||||
raw_tx_0 = node.signrawtransactionwithwallet(node.createrawtransaction(
|
raw_tx_0 = node.signrawtransactionwithwallet(node.createrawtransaction(
|
||||||
inputs=[{"txid": txid_in_block, "vout": 0, "sequence": BIP125_SEQUENCE_NUMBER}], # RBF is used later
|
inputs=[{"txid": txid_in_block, "vout": 0, "sequence": BIP125_SEQUENCE_NUMBER}], # RBF is used later
|
||||||
outputs=[{node.getnewaddress(): 0.3 - fee}],
|
outputs=[{node.getnewaddress(): 0.006 - fee}],
|
||||||
))['hex']
|
))['hex']
|
||||||
tx = CTransaction()
|
tx = CTransaction()
|
||||||
tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_0)))
|
tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_0)))
|
||||||
|
@ -114,7 +114,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
|
||||||
node.sendrawtransaction(hexstring=bytes_to_hex_str(tx.serialize()), allowhighfees=True)
|
node.sendrawtransaction(hexstring=bytes_to_hex_str(tx.serialize()), allowhighfees=True)
|
||||||
# take original raw_tx_0
|
# take original raw_tx_0
|
||||||
tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_0)))
|
tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_0)))
|
||||||
tx.vout[0].nValue -= int(4 * fee * COIN) # Set more fee
|
tx.vout[0].nValue -= int(0.08 * fee * COIN) # Set more fee
|
||||||
# skip re-signing the tx
|
# skip re-signing the tx
|
||||||
self.check_mempool_result(
|
self.check_mempool_result(
|
||||||
result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '18: txn-mempool-conflict'}],
|
result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '18: txn-mempool-conflict'}],
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
"""Test mempool persistence.
|
"""Test mempool persistence.
|
||||||
|
|
||||||
By default, bitcoind will dump mempool on shutdown and
|
By default, lbrycrdd will dump mempool on shutdown and
|
||||||
then reload it on startup. This can be overridden with
|
then reload it on startup. This can be overridden with
|
||||||
the -persistmempool=0 command line option.
|
the -persistmempool=0 command line option.
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ class MempoolPersistTest(BitcoinTestFramework):
|
||||||
self.start_node(1, extra_args=["-persistmempool=0"])
|
self.start_node(1, extra_args=["-persistmempool=0"])
|
||||||
self.start_node(0)
|
self.start_node(0)
|
||||||
self.start_node(2)
|
self.start_node(2)
|
||||||
# Give bitcoind a second to reload the mempool
|
# Give lbrycrdd a second to reload the mempool
|
||||||
wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5, timeout=1)
|
wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5, timeout=1)
|
||||||
wait_until(lambda: len(self.nodes[2].getrawmempool()) == 5, timeout=1)
|
wait_until(lambda: len(self.nodes[2].getrawmempool()) == 5, timeout=1)
|
||||||
# The others have loaded their mempool. If node_1 loaded anything, we'd probably notice by now:
|
# The others have loaded their mempool. If node_1 loaded anything, we'd probably notice by now:
|
||||||
|
@ -88,7 +88,7 @@ class MempoolPersistTest(BitcoinTestFramework):
|
||||||
self.log.debug("Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.")
|
self.log.debug("Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.")
|
||||||
self.stop_nodes()
|
self.stop_nodes()
|
||||||
self.start_node(0, extra_args=["-persistmempool=0"])
|
self.start_node(0, extra_args=["-persistmempool=0"])
|
||||||
# Give bitcoind a second to reload the mempool
|
# Give lbrycrdd a second to reload the mempool
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
assert_equal(len(self.nodes[0].getrawmempool()), 0)
|
assert_equal(len(self.nodes[0].getrawmempool()), 0)
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ class MempoolPersistTest(BitcoinTestFramework):
|
||||||
self.start_node(1, extra_args=[])
|
self.start_node(1, extra_args=[])
|
||||||
wait_until(lambda: len(self.nodes[1].getrawmempool()) == 5)
|
wait_until(lambda: len(self.nodes[1].getrawmempool()) == 5)
|
||||||
|
|
||||||
self.log.debug("Prevent bitcoind from writing mempool.dat to disk. Verify that `savemempool` fails")
|
self.log.debug("Prevent lbrycrdd from writing mempool.dat to disk. Verify that `savemempool` fails")
|
||||||
# to test the exception we are creating a tmp folder called mempool.dat.new
|
# to test the exception we are creating a tmp folder called mempool.dat.new
|
||||||
# which is an implementation detail that could change and break this test
|
# which is an implementation detail that could change and break this test
|
||||||
mempooldotnew1 = mempooldat1 + '.new'
|
mempooldotnew1 = mempooldat1 + '.new'
|
||||||
|
|
|
@ -42,12 +42,12 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
|
||||||
# and make sure the mempool code behaves correctly.
|
# and make sure the mempool code behaves correctly.
|
||||||
b = [ self.nodes[0].getblockhash(n) for n in range(101, 105) ]
|
b = [ self.nodes[0].getblockhash(n) for n in range(101, 105) ]
|
||||||
coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ]
|
coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ]
|
||||||
spend_101_raw = create_raw_transaction(self.nodes[0], coinbase_txids[1], node1_address, amount=49.99)
|
spend_101_raw = create_raw_transaction(self.nodes[0], coinbase_txids[1], node1_address, amount=0.9998)
|
||||||
spend_102_raw = create_raw_transaction(self.nodes[0], coinbase_txids[2], node0_address, amount=49.99)
|
spend_102_raw = create_raw_transaction(self.nodes[0], coinbase_txids[2], node0_address, amount=0.9998)
|
||||||
spend_103_raw = create_raw_transaction(self.nodes[0], coinbase_txids[3], node0_address, amount=49.99)
|
spend_103_raw = create_raw_transaction(self.nodes[0], coinbase_txids[3], node0_address, amount=0.9998)
|
||||||
|
|
||||||
# Create a transaction which is time-locked to two blocks in the future
|
# Create a transaction which is time-locked to two blocks in the future
|
||||||
timelock_tx = self.nodes[0].createrawtransaction([{"txid": coinbase_txids[0], "vout": 0}], {node0_address: 49.99})
|
timelock_tx = self.nodes[0].createrawtransaction([{"txid": coinbase_txids[0], "vout": 0}], {node0_address: 0.9998})
|
||||||
# Set the time lock
|
# Set the time lock
|
||||||
timelock_tx = timelock_tx.replace("ffffffff", "11111191", 1)
|
timelock_tx = timelock_tx.replace("ffffffff", "11111191", 1)
|
||||||
timelock_tx = timelock_tx[:-8] + hex(self.nodes[0].getblockcount() + 2)[2:] + "000000"
|
timelock_tx = timelock_tx[:-8] + hex(self.nodes[0].getblockcount() + 2)[2:] + "000000"
|
||||||
|
@ -63,8 +63,8 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
|
||||||
assert_raises_rpc_error(-26, 'non-final', self.nodes[0].sendrawtransaction, timelock_tx)
|
assert_raises_rpc_error(-26, 'non-final', self.nodes[0].sendrawtransaction, timelock_tx)
|
||||||
|
|
||||||
# Create 102_1 and 103_1:
|
# Create 102_1 and 103_1:
|
||||||
spend_102_1_raw = create_raw_transaction(self.nodes[0], spend_102_id, node1_address, amount=49.98)
|
spend_102_1_raw = create_raw_transaction(self.nodes[0], spend_102_id, node1_address, amount=0.9996)
|
||||||
spend_103_1_raw = create_raw_transaction(self.nodes[0], spend_103_id, node1_address, amount=49.98)
|
spend_103_1_raw = create_raw_transaction(self.nodes[0], spend_103_id, node1_address, amount=0.9996)
|
||||||
|
|
||||||
# Broadcast and mine 103_1:
|
# Broadcast and mine 103_1:
|
||||||
spend_103_1_id = self.nodes[0].sendrawtransaction(spend_103_1_raw)
|
spend_103_1_id = self.nodes[0].sendrawtransaction(spend_103_1_raw)
|
||||||
|
|
|
@ -30,13 +30,13 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
|
||||||
|
|
||||||
b = [self.nodes[0].getblockhash(n) for n in range(1, 4)]
|
b = [self.nodes[0].getblockhash(n) for n in range(1, 4)]
|
||||||
coinbase_txids = [self.nodes[0].getblock(h)['tx'][0] for h in b]
|
coinbase_txids = [self.nodes[0].getblock(h)['tx'][0] for h in b]
|
||||||
spends1_raw = [create_raw_transaction(self.nodes[0], txid, node0_address, amount=49.99) for txid in coinbase_txids]
|
spends1_raw = [create_raw_transaction(self.nodes[0], txid, node0_address, amount=0.9998) for txid in coinbase_txids]
|
||||||
spends1_id = [self.nodes[0].sendrawtransaction(tx) for tx in spends1_raw]
|
spends1_id = [self.nodes[0].sendrawtransaction(tx) for tx in spends1_raw]
|
||||||
|
|
||||||
blocks = []
|
blocks = []
|
||||||
blocks.extend(self.nodes[0].generate(1))
|
blocks.extend(self.nodes[0].generate(1))
|
||||||
|
|
||||||
spends2_raw = [create_raw_transaction(self.nodes[0], txid, node0_address, amount=49.98) for txid in spends1_id]
|
spends2_raw = [create_raw_transaction(self.nodes[0], txid, node0_address, amount=0.9996) for txid in spends1_id]
|
||||||
spends2_id = [self.nodes[0].sendrawtransaction(tx) for tx in spends2_raw]
|
spends2_id = [self.nodes[0].sendrawtransaction(tx) for tx in spends2_raw]
|
||||||
|
|
||||||
blocks.extend(self.nodes[0].generate(1))
|
blocks.extend(self.nodes[0].generate(1))
|
||||||
|
|
|
@ -34,7 +34,7 @@ class MempoolSpendCoinbaseTest(BitcoinTestFramework):
|
||||||
# is too immature to spend.
|
# is too immature to spend.
|
||||||
b = [self.nodes[0].getblockhash(n) for n in range(101, 103)]
|
b = [self.nodes[0].getblockhash(n) for n in range(101, 103)]
|
||||||
coinbase_txids = [self.nodes[0].getblock(h)['tx'][0] for h in b]
|
coinbase_txids = [self.nodes[0].getblock(h)['tx'][0] for h in b]
|
||||||
spends_raw = [create_raw_transaction(self.nodes[0], txid, node0_address, amount=49.99) for txid in coinbase_txids]
|
spends_raw = [create_raw_transaction(self.nodes[0], txid, node0_address, amount=0.9998) for txid in coinbase_txids]
|
||||||
|
|
||||||
spend_101_id = self.nodes[0].sendrawtransaction(spends_raw[0])
|
spend_101_id = self.nodes[0].sendrawtransaction(spends_raw[0])
|
||||||
|
|
||||||
|
|
|
@ -40,10 +40,10 @@ class MiningTest(BitcoinTestFramework):
|
||||||
self.log.info('getmininginfo')
|
self.log.info('getmininginfo')
|
||||||
mining_info = node.getmininginfo()
|
mining_info = node.getmininginfo()
|
||||||
assert_equal(mining_info['blocks'], 200)
|
assert_equal(mining_info['blocks'], 200)
|
||||||
assert_equal(mining_info['chain'], 'regtest')
|
assert_equal(mining_info['chain'], 'lbrycrdreg')
|
||||||
assert_equal(mining_info['currentblocktx'], 0)
|
assert_equal(mining_info['currentblocktx'], 0)
|
||||||
assert_equal(mining_info['currentblockweight'], 0)
|
assert_equal(mining_info['currentblockweight'], 0)
|
||||||
assert_equal(mining_info['difficulty'], Decimal('4.656542373906925E-10'))
|
assert_equal(mining_info['difficulty'], Decimal('0.00003051711610163642'))
|
||||||
assert_equal(mining_info['networkhashps'], Decimal('0.003333333333333334'))
|
assert_equal(mining_info['networkhashps'], Decimal('0.003333333333333334'))
|
||||||
assert_equal(mining_info['pooledtx'], 0)
|
assert_equal(mining_info['pooledtx'], 0)
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ class MiningTest(BitcoinTestFramework):
|
||||||
|
|
||||||
self.log.info("getblocktemplate: Test bad tx count")
|
self.log.info("getblocktemplate: Test bad tx count")
|
||||||
# The tx count is immediately after the block header
|
# The tx count is immediately after the block header
|
||||||
TX_COUNT_OFFSET = 80
|
TX_COUNT_OFFSET = 80+32
|
||||||
bad_block_sn = bytearray(block.serialize())
|
bad_block_sn = bytearray(block.serialize())
|
||||||
assert_equal(bad_block_sn[TX_COUNT_OFFSET], 1)
|
assert_equal(bad_block_sn[TX_COUNT_OFFSET], 1)
|
||||||
bad_block_sn[TX_COUNT_OFFSET] += 1
|
bad_block_sn[TX_COUNT_OFFSET] += 1
|
||||||
|
|
|
@ -18,7 +18,7 @@ from test_framework.script import CScript, OP_TRUE, OP_DROP
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import assert_equal, get_bip9_status, satoshi_round, sync_blocks, wait_until
|
from test_framework.util import assert_equal, get_bip9_status, satoshi_round, sync_blocks, wait_until
|
||||||
|
|
||||||
# TestP2PConn: A peer we use to send messages to bitcoind, and store responses.
|
# TestP2PConn: A peer we use to send messages to lbrycrdd, and store responses.
|
||||||
class TestP2PConn(P2PInterface):
|
class TestP2PConn(P2PInterface):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
@ -241,7 +241,7 @@ class CompactBlocksTest(BitcoinTestFramework):
|
||||||
old_node.request_headers_and_sync(locator=[tip])
|
old_node.request_headers_and_sync(locator=[tip])
|
||||||
check_announcement_of_new_block(node, old_node, lambda p: "cmpctblock" in p.last_message)
|
check_announcement_of_new_block(node, old_node, lambda p: "cmpctblock" in p.last_message)
|
||||||
|
|
||||||
# This test actually causes bitcoind to (reasonably!) disconnect us, so do this last.
|
# This test actually causes lbrycrdd to (reasonably!) disconnect us, so do this last.
|
||||||
def test_invalid_cmpctblock_message(self):
|
def test_invalid_cmpctblock_message(self):
|
||||||
self.nodes[0].generate(101)
|
self.nodes[0].generate(101)
|
||||||
block = self.build_block_on_tip(self.nodes[0])
|
block = self.build_block_on_tip(self.nodes[0])
|
||||||
|
@ -256,7 +256,7 @@ class CompactBlocksTest(BitcoinTestFramework):
|
||||||
assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.hashPrevBlock)
|
assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.hashPrevBlock)
|
||||||
|
|
||||||
# Compare the generated shortids to what we expect based on BIP 152, given
|
# Compare the generated shortids to what we expect based on BIP 152, given
|
||||||
# bitcoind's choice of nonce.
|
# lbrycrdd's choice of nonce.
|
||||||
def test_compactblock_construction(self, node, test_node, version, use_witness_address):
|
def test_compactblock_construction(self, node, test_node, version, use_witness_address):
|
||||||
# Generate a bunch of transactions.
|
# Generate a bunch of transactions.
|
||||||
node.generate(101)
|
node.generate(101)
|
||||||
|
@ -370,7 +370,7 @@ class CompactBlocksTest(BitcoinTestFramework):
|
||||||
header_and_shortids.shortids.pop(0)
|
header_and_shortids.shortids.pop(0)
|
||||||
index += 1
|
index += 1
|
||||||
|
|
||||||
# Test that bitcoind requests compact blocks when we announce new blocks
|
# Test that lbrycrdd requests compact blocks when we announce new blocks
|
||||||
# via header or inv, and that responding to getblocktxn causes the block
|
# via header or inv, and that responding to getblocktxn causes the block
|
||||||
# to be successfully reconstructed.
|
# to be successfully reconstructed.
|
||||||
# Post-segwit: upgraded nodes would only make this request of cb-version-2,
|
# Post-segwit: upgraded nodes would only make this request of cb-version-2,
|
||||||
|
@ -552,7 +552,7 @@ class CompactBlocksTest(BitcoinTestFramework):
|
||||||
assert_equal(absolute_indexes, [6, 7, 8, 9, 10])
|
assert_equal(absolute_indexes, [6, 7, 8, 9, 10])
|
||||||
|
|
||||||
# Now give an incorrect response.
|
# Now give an incorrect response.
|
||||||
# Note that it's possible for bitcoind to be smart enough to know we're
|
# Note that it's possible for lbrycrdd to be smart enough to know we're
|
||||||
# lying, since it could check to see if the shortid matches what we're
|
# lying, since it could check to see if the shortid matches what we're
|
||||||
# sending, and eg disconnect us for misbehavior. If that behavior
|
# sending, and eg disconnect us for misbehavior. If that behavior
|
||||||
# change was made, we could just modify this test by having a
|
# change was made, we could just modify this test by having a
|
||||||
|
@ -582,7 +582,7 @@ class CompactBlocksTest(BitcoinTestFramework):
|
||||||
assert_equal(int(node.getbestblockhash(), 16), block.sha256)
|
assert_equal(int(node.getbestblockhash(), 16), block.sha256)
|
||||||
|
|
||||||
def test_getblocktxn_handler(self, node, test_node, version):
|
def test_getblocktxn_handler(self, node, test_node, version):
|
||||||
# bitcoind will not send blocktxn responses for blocks whose height is
|
# lbrycrdd will not send blocktxn responses for blocks whose height is
|
||||||
# more than 10 blocks deep.
|
# more than 10 blocks deep.
|
||||||
MAX_GETBLOCKTXN_DEPTH = 10
|
MAX_GETBLOCKTXN_DEPTH = 10
|
||||||
chain_height = node.getblockcount()
|
chain_height = node.getblockcount()
|
||||||
|
|
|
@ -70,7 +70,7 @@ class InvalidTxRequestTest(BitcoinTestFramework):
|
||||||
# Transaction will be rejected with code 16 (REJECT_INVALID)
|
# Transaction will be rejected with code 16 (REJECT_INVALID)
|
||||||
# and we get disconnected immediately
|
# and we get disconnected immediately
|
||||||
self.log.info('Test a transaction that is rejected')
|
self.log.info('Test a transaction that is rejected')
|
||||||
tx1 = create_tx_with_script(block1.vtx[0], 0, script_sig=b'\x64' * 35, amount=50 * COIN - 12000)
|
tx1 = create_tx_with_script(block1.vtx[0], 0, script_sig=b'\x64' * 35, amount=int(1 * COIN - 240))
|
||||||
node.p2p.send_txs_and_test([tx1], node, success=False, expect_disconnect=True)
|
node.p2p.send_txs_and_test([tx1], node, success=False, expect_disconnect=True)
|
||||||
|
|
||||||
# Make two p2p connections to provide the node with orphans
|
# Make two p2p connections to provide the node with orphans
|
||||||
|
@ -84,30 +84,30 @@ class InvalidTxRequestTest(BitcoinTestFramework):
|
||||||
SCRIPT_PUB_KEY_OP_TRUE = b'\x51\x75' * 15 + b'\x51'
|
SCRIPT_PUB_KEY_OP_TRUE = b'\x51\x75' * 15 + b'\x51'
|
||||||
tx_withhold = CTransaction()
|
tx_withhold = CTransaction()
|
||||||
tx_withhold.vin.append(CTxIn(outpoint=COutPoint(block1.vtx[0].sha256, 0)))
|
tx_withhold.vin.append(CTxIn(outpoint=COutPoint(block1.vtx[0].sha256, 0)))
|
||||||
tx_withhold.vout.append(CTxOut(nValue=50 * COIN - 12000, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
|
tx_withhold.vout.append(CTxOut(nValue=int(1 * COIN) - 240, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
|
||||||
tx_withhold.calc_sha256()
|
tx_withhold.calc_sha256()
|
||||||
|
|
||||||
# Our first orphan tx with some outputs to create further orphan txs
|
# Our first orphan tx with some outputs to create further orphan txs
|
||||||
tx_orphan_1 = CTransaction()
|
tx_orphan_1 = CTransaction()
|
||||||
tx_orphan_1.vin.append(CTxIn(outpoint=COutPoint(tx_withhold.sha256, 0)))
|
tx_orphan_1.vin.append(CTxIn(outpoint=COutPoint(tx_withhold.sha256, 0)))
|
||||||
tx_orphan_1.vout = [CTxOut(nValue=10 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE)] * 3
|
tx_orphan_1.vout = [CTxOut(nValue=int(0.2 * COIN), scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE)] * 3
|
||||||
tx_orphan_1.calc_sha256()
|
tx_orphan_1.calc_sha256()
|
||||||
|
|
||||||
# A valid transaction with low fee
|
# A valid transaction with low fee
|
||||||
tx_orphan_2_no_fee = CTransaction()
|
tx_orphan_2_no_fee = CTransaction()
|
||||||
tx_orphan_2_no_fee.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 0)))
|
tx_orphan_2_no_fee.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 0)))
|
||||||
tx_orphan_2_no_fee.vout.append(CTxOut(nValue=10 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
|
tx_orphan_2_no_fee.vout.append(CTxOut(nValue=int(0.2 * COIN), scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
|
||||||
|
|
||||||
# A valid transaction with sufficient fee
|
# A valid transaction with sufficient fee
|
||||||
tx_orphan_2_valid = CTransaction()
|
tx_orphan_2_valid = CTransaction()
|
||||||
tx_orphan_2_valid.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 1)))
|
tx_orphan_2_valid.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 1)))
|
||||||
tx_orphan_2_valid.vout.append(CTxOut(nValue=10 * COIN - 12000, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
|
tx_orphan_2_valid.vout.append(CTxOut(nValue=int(0.2 * COIN) - 240, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
|
||||||
tx_orphan_2_valid.calc_sha256()
|
tx_orphan_2_valid.calc_sha256()
|
||||||
|
|
||||||
# An invalid transaction with negative fee
|
# An invalid transaction with negative fee
|
||||||
tx_orphan_2_invalid = CTransaction()
|
tx_orphan_2_invalid = CTransaction()
|
||||||
tx_orphan_2_invalid.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 2)))
|
tx_orphan_2_invalid.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 2)))
|
||||||
tx_orphan_2_invalid.vout.append(CTxOut(nValue=11 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
|
tx_orphan_2_invalid.vout.append(CTxOut(nValue=int(0.22 * COIN), scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
|
||||||
|
|
||||||
self.log.info('Send the orphans ... ')
|
self.log.info('Send the orphans ... ')
|
||||||
# Send valid orphan txs from p2ps[0]
|
# Send valid orphan txs from p2ps[0]
|
||||||
|
@ -134,7 +134,7 @@ class InvalidTxRequestTest(BitcoinTestFramework):
|
||||||
# tx_orphan_no_fee, because it has too low fee (p2ps[0] is not disconnected for relaying that tx)
|
# tx_orphan_no_fee, because it has too low fee (p2ps[0] is not disconnected for relaying that tx)
|
||||||
# tx_orphan_invaid, because it has negative fee (p2ps[1] is disconnected for relaying that tx)
|
# tx_orphan_invaid, because it has negative fee (p2ps[1] is disconnected for relaying that tx)
|
||||||
|
|
||||||
wait_until(lambda: 1 == len(node.getpeerinfo()), timeout=12) # p2ps[1] is no longer connected
|
wait_until(lambda: 1 == len(node.getpeerinfo()), timeout=1) # p2ps[1] is no longer connected
|
||||||
assert_equal(expected_mempool, set(node.getrawmempool()))
|
assert_equal(expected_mempool, set(node.getrawmempool()))
|
||||||
|
|
||||||
# restart node with sending BIP61 messages disabled, check that it disconnects without sending the reject message
|
# restart node with sending BIP61 messages disabled, check that it disconnects without sending the reject message
|
||||||
|
|
|
@ -58,7 +58,7 @@ class CLazyNode(P2PInterface):
|
||||||
# anyway, and eventually get disconnected.
|
# anyway, and eventually get disconnected.
|
||||||
class CNodeNoVersionBan(CLazyNode):
|
class CNodeNoVersionBan(CLazyNode):
|
||||||
# send a bunch of veracks without sending a message. This should get us disconnected.
|
# send a bunch of veracks without sending a message. This should get us disconnected.
|
||||||
# NOTE: implementation-specific check here. Remove if bitcoind ban behavior changes
|
# NOTE: implementation-specific check here. Remove if lbrycrdd ban behavior changes
|
||||||
def on_open(self):
|
def on_open(self):
|
||||||
super().on_open()
|
super().on_open()
|
||||||
for i in range(banscore):
|
for i in range(banscore):
|
||||||
|
|
|
@ -13,6 +13,7 @@ from test_framework.blocktools import create_block, create_coinbase, add_witness
|
||||||
from test_framework.key import CECKey, CPubKey
|
from test_framework.key import CECKey, CPubKey
|
||||||
from test_framework.messages import (
|
from test_framework.messages import (
|
||||||
BIP125_SEQUENCE_NUMBER,
|
BIP125_SEQUENCE_NUMBER,
|
||||||
|
COIN,
|
||||||
CBlock,
|
CBlock,
|
||||||
CBlockHeader,
|
CBlockHeader,
|
||||||
CInv,
|
CInv,
|
||||||
|
@ -85,8 +86,8 @@ from test_framework.util import (
|
||||||
)
|
)
|
||||||
|
|
||||||
# The versionbit bit used to signal activation of SegWit
|
# The versionbit bit used to signal activation of SegWit
|
||||||
VB_WITNESS_BIT = 1
|
VB_WITNESS_BIT = 0
|
||||||
VB_PERIOD = 144
|
VB_PERIOD = 150
|
||||||
VB_TOP_BITS = 0x20000000
|
VB_TOP_BITS = 0x20000000
|
||||||
|
|
||||||
MAX_SIGOP_COST = 80000
|
MAX_SIGOP_COST = 80000
|
||||||
|
@ -240,7 +241,7 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
self.utxo = []
|
self.utxo = []
|
||||||
|
|
||||||
# Segwit status 'defined'
|
# Segwit status 'defined'
|
||||||
self.segwit_status = 'defined'
|
self.segwit_status = 'failed'
|
||||||
|
|
||||||
self.test_non_witness_transaction()
|
self.test_non_witness_transaction()
|
||||||
self.test_unnecessary_witness_before_segwit_activation()
|
self.test_unnecessary_witness_before_segwit_activation()
|
||||||
|
@ -318,7 +319,7 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
# Create a transaction that spends the coinbase
|
# Create a transaction that spends the coinbase
|
||||||
tx = CTransaction()
|
tx = CTransaction()
|
||||||
tx.vin.append(CTxIn(COutPoint(txid, 0), b""))
|
tx.vin.append(CTxIn(COutPoint(txid, 0), b""))
|
||||||
tx.vout.append(CTxOut(49 * 100000000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
|
tx.vout.append(CTxOut(int(0.98 * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
|
||||||
tx.calc_sha256()
|
tx.calc_sha256()
|
||||||
|
|
||||||
# Check that serializing it with or without witness is the same
|
# Check that serializing it with or without witness is the same
|
||||||
|
@ -329,7 +330,7 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
self.test_node.sync_with_ping() # make sure the tx was processed
|
self.test_node.sync_with_ping() # make sure the tx was processed
|
||||||
assert(tx.hash in self.nodes[0].getrawmempool())
|
assert(tx.hash in self.nodes[0].getrawmempool())
|
||||||
# Save this transaction for later
|
# Save this transaction for later
|
||||||
self.utxo.append(UTXO(tx.sha256, 0, 49 * 100000000))
|
self.utxo.append(UTXO(tx.sha256, 0, int(0.98 * COIN)))
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
|
|
||||||
@subtest
|
@subtest
|
||||||
|
@ -551,8 +552,8 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
assert(height < VB_PERIOD - 1)
|
assert(height < VB_PERIOD - 1)
|
||||||
# Advance to end of period, status should now be 'started'
|
# Advance to end of period, status should now be 'started'
|
||||||
self.nodes[0].generate(VB_PERIOD - height - 1)
|
self.nodes[0].generate(VB_PERIOD - height - 1)
|
||||||
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'started')
|
self.segwit_status = 'active'
|
||||||
self.segwit_status = 'started'
|
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], self.segwit_status)
|
||||||
|
|
||||||
@subtest
|
@subtest
|
||||||
def test_getblocktemplate_before_lockin(self):
|
def test_getblocktemplate_before_lockin(self):
|
||||||
|
@ -562,7 +563,7 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
block_version = gbt_results['version']
|
block_version = gbt_results['version']
|
||||||
# If we're not indicating segwit support, we will still be
|
# If we're not indicating segwit support, we will still be
|
||||||
# signalling for segwit activation.
|
# signalling for segwit activation.
|
||||||
assert_equal((block_version & (1 << VB_WITNESS_BIT) != 0), node == self.nodes[0])
|
# assert_equal((block_version & (1 << VB_WITNESS_BIT) != 0), node == self.nodes[0])
|
||||||
# If we don't specify the segwit rule, then we won't get a default
|
# If we don't specify the segwit rule, then we won't get a default
|
||||||
# commitment.
|
# commitment.
|
||||||
assert('default_witness_commitment' not in gbt_results)
|
assert('default_witness_commitment' not in gbt_results)
|
||||||
|
@ -582,7 +583,7 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
if node == self.nodes[2]:
|
if node == self.nodes[2]:
|
||||||
# If this is a non-segwit node, we should still not get a witness
|
# If this is a non-segwit node, we should still not get a witness
|
||||||
# commitment, nor a version bit signalling segwit.
|
# commitment, nor a version bit signalling segwit.
|
||||||
assert_equal(block_version & (1 << VB_WITNESS_BIT), 0)
|
assert_equal(block_version & (1 << VB_WITNESS_BIT), 1)
|
||||||
assert('default_witness_commitment' not in gbt_results)
|
assert('default_witness_commitment' not in gbt_results)
|
||||||
else:
|
else:
|
||||||
# For segwit-aware nodes, check the version bit and the witness
|
# For segwit-aware nodes, check the version bit and the witness
|
||||||
|
@ -609,10 +610,10 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
self.nodes[0].generate(VB_PERIOD - 1)
|
self.nodes[0].generate(VB_PERIOD - 1)
|
||||||
height = self.nodes[0].getblockcount()
|
height = self.nodes[0].getblockcount()
|
||||||
assert((height % VB_PERIOD) == VB_PERIOD - 2)
|
assert((height % VB_PERIOD) == VB_PERIOD - 2)
|
||||||
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'started')
|
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'active')
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'locked_in')
|
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'active')
|
||||||
self.segwit_status = 'locked_in'
|
self.segwit_status = 'active'
|
||||||
|
|
||||||
@subtest
|
@subtest
|
||||||
def test_witness_tx_relay_before_segwit_activation(self):
|
def test_witness_tx_relay_before_segwit_activation(self):
|
||||||
|
@ -778,7 +779,7 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
# This transaction should not be accepted into the mempool pre- or
|
# This transaction should not be accepted into the mempool pre- or
|
||||||
# post-segwit. Mempool acceptance will use SCRIPT_VERIFY_WITNESS which
|
# post-segwit. Mempool acceptance will use SCRIPT_VERIFY_WITNESS which
|
||||||
# will require a witness to spend a witness program regardless of
|
# will require a witness to spend a witness program regardless of
|
||||||
# segwit activation. Note that older bitcoind's that are not
|
# segwit activation. Note that older lbrycrdd's that are not
|
||||||
# segwit-aware would also reject this for failing CLEANSTACK.
|
# segwit-aware would also reject this for failing CLEANSTACK.
|
||||||
test_transaction_acceptance(self.nodes[0], self.test_node, spend_tx, with_witness=False, accepted=False)
|
test_transaction_acceptance(self.nodes[0], self.test_node, spend_tx, with_witness=False, accepted=False)
|
||||||
|
|
||||||
|
@ -1030,7 +1031,7 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
self.nodes[0].submitblock(bytes_to_hex_str(block.serialize(True)))
|
self.nodes[0].submitblock(bytes_to_hex_str(block.serialize(True)))
|
||||||
assert(self.nodes[0].getbestblockhash() != block.hash)
|
assert(self.nodes[0].getbestblockhash() != block.hash)
|
||||||
|
|
||||||
# Now redo commitment with the standard nonce, but let bitcoind fill it in.
|
# Now redo commitment with the standard nonce, but let lbrycrdd fill it in.
|
||||||
add_witness_commitment(block, nonce=0)
|
add_witness_commitment(block, nonce=0)
|
||||||
block.vtx[0].wit = CTxWitness()
|
block.vtx[0].wit = CTxWitness()
|
||||||
block.solve()
|
block.solve()
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
"""Test various net timeouts.
|
"""Test various net timeouts.
|
||||||
|
|
||||||
- Create three bitcoind nodes:
|
- Create three lbrycrdd nodes:
|
||||||
|
|
||||||
no_verack_node - we never send a verack in response to their version
|
no_verack_node - we never send a verack in response to their version
|
||||||
no_version_node - we never send a version (only a ping)
|
no_version_node - we never send a version (only a ping)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# Copyright (c) 2014-2018 The Bitcoin Core developers
|
# Copyright (c) 2014-2018 The Bitcoin Core developers
|
||||||
# Distributed under the MIT software license, see the accompanying
|
# Distributed under the MIT software license, see the accompanying
|
||||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
"""Test running bitcoind with the -rpcbind and -rpcallowip options."""
|
"""Test running lbrycrdd with the -rpcbind and -rpcallowip options."""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
|
@ -169,11 +169,11 @@ class BlockchainTest(BitcoinTestFramework):
|
||||||
node = self.nodes[0]
|
node = self.nodes[0]
|
||||||
res = node.gettxoutsetinfo()
|
res = node.gettxoutsetinfo()
|
||||||
|
|
||||||
assert_equal(res['total_amount'], Decimal('8725.00000000'))
|
assert_equal(res['total_amount'], Decimal('400000200.00000000'))
|
||||||
assert_equal(res['transactions'], 200)
|
assert_equal(res['transactions'], 201)
|
||||||
assert_equal(res['height'], 200)
|
assert_equal(res['height'], 200)
|
||||||
assert_equal(res['txouts'], 200)
|
assert_equal(res['txouts'], 201)
|
||||||
assert_equal(res['bogosize'], 15000),
|
assert_equal(res['bogosize'], 15075),
|
||||||
assert_equal(res['bestblock'], node.getblockhash(200))
|
assert_equal(res['bestblock'], node.getblockhash(200))
|
||||||
size = res['disk_size']
|
size = res['disk_size']
|
||||||
assert size > 6400
|
assert size > 6400
|
||||||
|
@ -186,11 +186,11 @@ class BlockchainTest(BitcoinTestFramework):
|
||||||
node.invalidateblock(b1hash)
|
node.invalidateblock(b1hash)
|
||||||
|
|
||||||
res2 = node.gettxoutsetinfo()
|
res2 = node.gettxoutsetinfo()
|
||||||
assert_equal(res2['transactions'], 0)
|
assert_equal(res2['transactions'], 1)
|
||||||
assert_equal(res2['total_amount'], Decimal('0'))
|
assert_equal(res2['total_amount'], Decimal('400000000.00000000'))
|
||||||
assert_equal(res2['height'], 0)
|
assert_equal(res2['height'], 0)
|
||||||
assert_equal(res2['txouts'], 0)
|
assert_equal(res2['txouts'], 1)
|
||||||
assert_equal(res2['bogosize'], 0),
|
assert_equal(res2['bogosize'], 75),
|
||||||
assert_equal(res2['bestblock'], node.getblockhash(0))
|
assert_equal(res2['bestblock'], node.getblockhash(0))
|
||||||
assert_equal(len(res2['hash_serialized_2']), 64)
|
assert_equal(len(res2['hash_serialized_2']), 64)
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ class BlockchainTest(BitcoinTestFramework):
|
||||||
difficulty = self.nodes[0].getdifficulty()
|
difficulty = self.nodes[0].getdifficulty()
|
||||||
# 1 hash in 2 should be valid, so difficulty should be 1/2**31
|
# 1 hash in 2 should be valid, so difficulty should be 1/2**31
|
||||||
# binary => decimal => binary math is why we do this check
|
# binary => decimal => binary math is why we do this check
|
||||||
assert abs(difficulty * 2**31 - 1) < 0.0001
|
assert abs(difficulty) < 0.0001
|
||||||
|
|
||||||
def _test_getnetworkhashps(self):
|
def _test_getnetworkhashps(self):
|
||||||
hashes_per_second = self.nodes[0].getnetworkhashps()
|
hashes_per_second = self.nodes[0].getnetworkhashps()
|
||||||
|
|
|
@ -49,7 +49,7 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
|
||||||
|
|
||||||
height = node0.getblockchaininfo()["blocks"]
|
height = node0.getblockchaininfo()["blocks"]
|
||||||
assert 150 < height < 350
|
assert 150 < height < 350
|
||||||
total = 149*50 + (height-149-100)*25
|
total = 149*1 + (height-149-100)*1
|
||||||
assert bal1 == 0
|
assert bal1 == 0
|
||||||
assert bal2 == self.moved
|
assert bal2 == self.moved
|
||||||
assert bal0+bal1+bal2 == total
|
assert bal0+bal1+bal2 == total
|
||||||
|
@ -61,7 +61,7 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
|
||||||
madd = msig["address"]
|
madd = msig["address"]
|
||||||
mredeem = msig["redeemScript"]
|
mredeem = msig["redeemScript"]
|
||||||
if self.output_type == 'bech32':
|
if self.output_type == 'bech32':
|
||||||
assert madd[0:4] == "bcrt" # actually a bech32 address
|
assert madd[0:4] == "rlbc" # actually a bech32 address
|
||||||
|
|
||||||
# compare against addmultisigaddress
|
# compare against addmultisigaddress
|
||||||
msigw = node1.addmultisigaddress(self.nsigs, self.pub, None, self.output_type)
|
msigw = node1.addmultisigaddress(self.nsigs, self.pub, None, self.output_type)
|
||||||
|
@ -71,7 +71,7 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
|
||||||
assert maddw == madd
|
assert maddw == madd
|
||||||
assert mredeemw == mredeem
|
assert mredeemw == mredeem
|
||||||
|
|
||||||
txid = node0.sendtoaddress(madd, 40)
|
txid = node0.sendtoaddress(madd, 0.8)
|
||||||
|
|
||||||
tx = node0.getrawtransaction(txid, True)
|
tx = node0.getrawtransaction(txid, True)
|
||||||
vout = [v["n"] for v in tx["vout"] if madd in v["scriptPubKey"].get("addresses",[])]
|
vout = [v["n"] for v in tx["vout"] if madd in v["scriptPubKey"].get("addresses",[])]
|
||||||
|
|
|
@ -61,13 +61,13 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
# ensure that setting changePosition in fundraw with an exact match is handled properly
|
# ensure that setting changePosition in fundraw with an exact match is handled properly
|
||||||
rawmatch = self.nodes[2].createrawtransaction([], {self.nodes[2].getnewaddress():50})
|
rawmatch = self.nodes[2].createrawtransaction([], {self.nodes[2].getnewaddress():1})
|
||||||
rawmatch = self.nodes[2].fundrawtransaction(rawmatch, {"changePosition":1, "subtractFeeFromOutputs":[0]})
|
rawmatch = self.nodes[2].fundrawtransaction(rawmatch, {"changePosition":1, "subtractFeeFromOutputs":[0]})
|
||||||
assert_equal(rawmatch["changepos"], -1)
|
assert_equal(rawmatch["changepos"], -1)
|
||||||
|
|
||||||
watchonly_address = self.nodes[0].getnewaddress()
|
watchonly_address = self.nodes[0].getnewaddress()
|
||||||
watchonly_pubkey = self.nodes[0].getaddressinfo(watchonly_address)["pubkey"]
|
watchonly_pubkey = self.nodes[0].getaddressinfo(watchonly_address)["pubkey"]
|
||||||
watchonly_amount = Decimal(200)
|
watchonly_amount = Decimal(4)
|
||||||
self.nodes[3].importpubkey(watchonly_pubkey, "", True)
|
self.nodes[3].importpubkey(watchonly_pubkey, "", True)
|
||||||
watchonly_txid = self.nodes[0].sendtoaddress(watchonly_address, watchonly_amount)
|
watchonly_txid = self.nodes[0].sendtoaddress(watchonly_address, watchonly_amount)
|
||||||
|
|
||||||
|
@ -77,9 +77,9 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
|
|
||||||
self.nodes[0].sendtoaddress(self.nodes[3].getnewaddress(), watchonly_amount / 10)
|
self.nodes[0].sendtoaddress(self.nodes[3].getnewaddress(), watchonly_amount / 10)
|
||||||
|
|
||||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.5)
|
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 0.03)
|
||||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0)
|
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 0.02)
|
||||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 5.0)
|
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 0.1)
|
||||||
|
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
@ -88,7 +88,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
# simple test #
|
# simple test #
|
||||||
###############
|
###############
|
||||||
inputs = [ ]
|
inputs = [ ]
|
||||||
outputs = { self.nodes[0].getnewaddress() : 1.0 }
|
outputs = { self.nodes[0].getnewaddress() : 0.02 }
|
||||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||||
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
|
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
|
||||||
|
@ -100,7 +100,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
# simple test with two coins #
|
# simple test with two coins #
|
||||||
##############################
|
##############################
|
||||||
inputs = [ ]
|
inputs = [ ]
|
||||||
outputs = { self.nodes[0].getnewaddress() : 2.2 }
|
outputs = { self.nodes[0].getnewaddress() : 0.044 }
|
||||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
# simple test with two coins #
|
# simple test with two coins #
|
||||||
##############################
|
##############################
|
||||||
inputs = [ ]
|
inputs = [ ]
|
||||||
outputs = { self.nodes[0].getnewaddress() : 2.6 }
|
outputs = { self.nodes[0].getnewaddress() : 0.052 }
|
||||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
# simple test with two outputs #
|
# simple test with two outputs #
|
||||||
################################
|
################################
|
||||||
inputs = [ ]
|
inputs = [ ]
|
||||||
outputs = { self.nodes[0].getnewaddress() : 2.6, self.nodes[1].getnewaddress() : 2.5 }
|
outputs = { self.nodes[0].getnewaddress() : 0.052, self.nodes[1].getnewaddress() : 0.05 }
|
||||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||||
|
|
||||||
|
@ -146,10 +146,10 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
#########################################################################
|
#########################################################################
|
||||||
# test a fundrawtransaction with a VIN greater than the required amount #
|
# test a fundrawtransaction with a VIN greater than the required amount #
|
||||||
#########################################################################
|
#########################################################################
|
||||||
utx = get_unspent(self.nodes[2].listunspent(), 5)
|
utx = get_unspent(self.nodes[2].listunspent(), Decimal("0.1"))
|
||||||
|
|
||||||
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
|
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
|
||||||
outputs = { self.nodes[0].getnewaddress() : 1.0 }
|
outputs = { self.nodes[0].getnewaddress() : 0.02 }
|
||||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||||
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
|
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
|
||||||
|
@ -167,10 +167,10 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
#####################################################################
|
#####################################################################
|
||||||
# test a fundrawtransaction with which will not get a change output #
|
# test a fundrawtransaction with which will not get a change output #
|
||||||
#####################################################################
|
#####################################################################
|
||||||
utx = get_unspent(self.nodes[2].listunspent(), 5)
|
utx = get_unspent(self.nodes[2].listunspent(), Decimal("0.1"))
|
||||||
|
|
||||||
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
|
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
|
||||||
outputs = { self.nodes[0].getnewaddress() : Decimal(5.0) - fee - feeTolerance }
|
outputs = { self.nodes[0].getnewaddress() : Decimal("0.1") - fee - feeTolerance }
|
||||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||||
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
|
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
|
||||||
|
@ -189,10 +189,10 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
####################################################
|
####################################################
|
||||||
# test a fundrawtransaction with an invalid option #
|
# test a fundrawtransaction with an invalid option #
|
||||||
####################################################
|
####################################################
|
||||||
utx = get_unspent(self.nodes[2].listunspent(), 5)
|
utx = get_unspent(self.nodes[2].listunspent(), Decimal("0.1"))
|
||||||
|
|
||||||
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
|
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
|
||||||
outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) }
|
outputs = { self.nodes[0].getnewaddress() : Decimal("0.08") }
|
||||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||||
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
|
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
|
||||||
|
@ -205,10 +205,10 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
############################################################
|
############################################################
|
||||||
# test a fundrawtransaction with an invalid change address #
|
# test a fundrawtransaction with an invalid change address #
|
||||||
############################################################
|
############################################################
|
||||||
utx = get_unspent(self.nodes[2].listunspent(), 5)
|
utx = get_unspent(self.nodes[2].listunspent(), Decimal("0.1"))
|
||||||
|
|
||||||
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
|
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
|
||||||
outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) }
|
outputs = { self.nodes[0].getnewaddress() : Decimal("0.08") }
|
||||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||||
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
|
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
|
||||||
|
@ -218,10 +218,10 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
############################################################
|
############################################################
|
||||||
# test a fundrawtransaction with a provided change address #
|
# test a fundrawtransaction with a provided change address #
|
||||||
############################################################
|
############################################################
|
||||||
utx = get_unspent(self.nodes[2].listunspent(), 5)
|
utx = get_unspent(self.nodes[2].listunspent(), Decimal("0.1"))
|
||||||
|
|
||||||
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
|
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
|
||||||
outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) }
|
outputs = { self.nodes[0].getnewaddress() : Decimal("0.08") }
|
||||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||||
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
|
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
|
||||||
|
@ -236,10 +236,10 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
#########################################################
|
#########################################################
|
||||||
# test a fundrawtransaction with a provided change type #
|
# test a fundrawtransaction with a provided change type #
|
||||||
#########################################################
|
#########################################################
|
||||||
utx = get_unspent(self.nodes[2].listunspent(), 5)
|
utx = get_unspent(self.nodes[2].listunspent(), Decimal("0.1"))
|
||||||
|
|
||||||
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
|
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
|
||||||
outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) }
|
outputs = { self.nodes[0].getnewaddress() : Decimal("0.08") }
|
||||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||||
assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[2].fundrawtransaction, rawtx, {'change_type': None})
|
assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[2].fundrawtransaction, rawtx, {'change_type': None})
|
||||||
assert_raises_rpc_error(-5, "Unknown change type ''", self.nodes[2].fundrawtransaction, rawtx, {'change_type': ''})
|
assert_raises_rpc_error(-5, "Unknown change type ''", self.nodes[2].fundrawtransaction, rawtx, {'change_type': ''})
|
||||||
|
@ -250,10 +250,10 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
#########################################################################
|
#########################################################################
|
||||||
# test a fundrawtransaction with a VIN smaller than the required amount #
|
# test a fundrawtransaction with a VIN smaller than the required amount #
|
||||||
#########################################################################
|
#########################################################################
|
||||||
utx = get_unspent(self.nodes[2].listunspent(), 1)
|
utx = get_unspent(self.nodes[2].listunspent(), Decimal("0.02"))
|
||||||
|
|
||||||
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
|
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
|
||||||
outputs = { self.nodes[0].getnewaddress() : 1.0 }
|
outputs = { self.nodes[0].getnewaddress() : 0.02 }
|
||||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||||
|
|
||||||
# 4-byte version + 1-byte vin count + 36-byte prevout then script_len
|
# 4-byte version + 1-byte vin count + 36-byte prevout then script_len
|
||||||
|
@ -285,11 +285,11 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
###########################################
|
###########################################
|
||||||
# test a fundrawtransaction with two VINs #
|
# test a fundrawtransaction with two VINs #
|
||||||
###########################################
|
###########################################
|
||||||
utx = get_unspent(self.nodes[2].listunspent(), 1)
|
utx = get_unspent(self.nodes[2].listunspent(), Decimal("0.02"))
|
||||||
utx2 = get_unspent(self.nodes[2].listunspent(), 5)
|
utx2 = get_unspent(self.nodes[2].listunspent(), Decimal("0.1"))
|
||||||
|
|
||||||
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ]
|
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ]
|
||||||
outputs = { self.nodes[0].getnewaddress() : 6.0 }
|
outputs = { self.nodes[0].getnewaddress() : 0.12 }
|
||||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||||
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
|
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
|
||||||
|
@ -318,11 +318,11 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
#########################################################
|
#########################################################
|
||||||
# test a fundrawtransaction with two VINs and two vOUTs #
|
# test a fundrawtransaction with two VINs and two vOUTs #
|
||||||
#########################################################
|
#########################################################
|
||||||
utx = get_unspent(self.nodes[2].listunspent(), 1)
|
utx = get_unspent(self.nodes[2].listunspent(), Decimal("0.02"))
|
||||||
utx2 = get_unspent(self.nodes[2].listunspent(), 5)
|
utx2 = get_unspent(self.nodes[2].listunspent(), Decimal("0.1"))
|
||||||
|
|
||||||
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ]
|
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ]
|
||||||
outputs = { self.nodes[0].getnewaddress() : 6.0, self.nodes[0].getnewaddress() : 1.0 }
|
outputs = { self.nodes[0].getnewaddress() : 0.12, self.nodes[0].getnewaddress() : 0.02 }
|
||||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||||
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
|
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
|
||||||
|
@ -344,7 +344,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
# test a fundrawtransaction with invalid vin #
|
# test a fundrawtransaction with invalid vin #
|
||||||
##############################################
|
##############################################
|
||||||
inputs = [ {'txid' : "1c7f966dab21119bac53213a2bc7532bff1fa844c124fd750a7d0b1332440bd1", 'vout' : 0} ] #invalid vin!
|
inputs = [ {'txid' : "1c7f966dab21119bac53213a2bc7532bff1fa844c124fd750a7d0b1332440bd1", 'vout' : 0} ] #invalid vin!
|
||||||
outputs = { self.nodes[0].getnewaddress() : 1.0}
|
outputs = { self.nodes[0].getnewaddress() : 0.02}
|
||||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||||
|
|
||||||
|
@ -353,12 +353,12 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
############################################################
|
############################################################
|
||||||
#compare fee of a standard pubkeyhash transaction
|
#compare fee of a standard pubkeyhash transaction
|
||||||
inputs = []
|
inputs = []
|
||||||
outputs = {self.nodes[1].getnewaddress():1.1}
|
outputs = {self.nodes[1].getnewaddress():0.022}
|
||||||
rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
|
||||||
fundedTx = self.nodes[0].fundrawtransaction(rawtx)
|
fundedTx = self.nodes[0].fundrawtransaction(rawtx)
|
||||||
|
|
||||||
#create same transaction over sendtoaddress
|
#create same transaction over sendtoaddress
|
||||||
txId = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1.1)
|
txId = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.022)
|
||||||
signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
|
signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
|
||||||
|
|
||||||
#compare fee
|
#compare fee
|
||||||
|
@ -369,7 +369,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
############################################################
|
############################################################
|
||||||
#compare fee of a standard pubkeyhash transaction with multiple outputs
|
#compare fee of a standard pubkeyhash transaction with multiple outputs
|
||||||
inputs = []
|
inputs = []
|
||||||
outputs = {self.nodes[1].getnewaddress():1.1,self.nodes[1].getnewaddress():1.2,self.nodes[1].getnewaddress():0.1,self.nodes[1].getnewaddress():1.3,self.nodes[1].getnewaddress():0.2,self.nodes[1].getnewaddress():0.3}
|
outputs = {self.nodes[1].getnewaddress():0.022,self.nodes[1].getnewaddress():0.024,self.nodes[1].getnewaddress():0.002,self.nodes[1].getnewaddress():0.026,self.nodes[1].getnewaddress():0.004,self.nodes[1].getnewaddress():0.006}
|
||||||
rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
|
||||||
fundedTx = self.nodes[0].fundrawtransaction(rawtx)
|
fundedTx = self.nodes[0].fundrawtransaction(rawtx)
|
||||||
#create same transaction over sendtoaddress
|
#create same transaction over sendtoaddress
|
||||||
|
@ -428,12 +428,12 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
mSigObj = self.nodes[1].addmultisigaddress(4, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey'], addr4Obj['pubkey'], addr5Obj['pubkey']])['address']
|
mSigObj = self.nodes[1].addmultisigaddress(4, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey'], addr4Obj['pubkey'], addr5Obj['pubkey']])['address']
|
||||||
|
|
||||||
inputs = []
|
inputs = []
|
||||||
outputs = {mSigObj:1.1}
|
outputs = {mSigObj:0.022}
|
||||||
rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
|
||||||
fundedTx = self.nodes[0].fundrawtransaction(rawtx)
|
fundedTx = self.nodes[0].fundrawtransaction(rawtx)
|
||||||
|
|
||||||
#create same transaction over sendtoaddress
|
#create same transaction over sendtoaddress
|
||||||
txId = self.nodes[0].sendtoaddress(mSigObj, 1.1)
|
txId = self.nodes[0].sendtoaddress(mSigObj, 0.022)
|
||||||
signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
|
signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
|
||||||
|
|
||||||
#compare fee
|
#compare fee
|
||||||
|
@ -456,14 +456,14 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
|
|
||||||
|
|
||||||
# send 1.2 BTC to msig addr
|
# send 1.2 BTC to msig addr
|
||||||
txId = self.nodes[0].sendtoaddress(mSigObj, 1.2)
|
txId = self.nodes[0].sendtoaddress(mSigObj, 0.024)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
self.nodes[1].generate(1)
|
self.nodes[1].generate(1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
oldBalance = self.nodes[1].getbalance()
|
oldBalance = self.nodes[1].getbalance()
|
||||||
inputs = []
|
inputs = []
|
||||||
outputs = {self.nodes[1].getnewaddress():1.1}
|
outputs = {self.nodes[1].getnewaddress():0.022}
|
||||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||||
fundedTx = self.nodes[2].fundrawtransaction(rawtx)
|
fundedTx = self.nodes[2].fundrawtransaction(rawtx)
|
||||||
|
|
||||||
|
@ -474,7 +474,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
# make sure funds are received at node1
|
# make sure funds are received at node1
|
||||||
assert_equal(oldBalance+Decimal('1.10000000'), self.nodes[1].getbalance())
|
assert_equal(oldBalance+Decimal('0.022'), self.nodes[1].getbalance())
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
# locked wallet test
|
# locked wallet test
|
||||||
|
@ -500,7 +500,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
self.nodes[1].getnewaddress()
|
self.nodes[1].getnewaddress()
|
||||||
self.nodes[1].getrawchangeaddress()
|
self.nodes[1].getrawchangeaddress()
|
||||||
inputs = []
|
inputs = []
|
||||||
outputs = {self.nodes[0].getnewaddress():1.1}
|
outputs = {self.nodes[0].getnewaddress():0.022}
|
||||||
rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
|
||||||
# fund a transaction that requires a new key for the change output
|
# fund a transaction that requires a new key for the change output
|
||||||
# creating the key must be impossible because the wallet is locked
|
# creating the key must be impossible because the wallet is locked
|
||||||
|
@ -511,12 +511,12 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
self.nodes[1].keypoolrefill(8) #need to refill the keypool to get an internal change address
|
self.nodes[1].keypoolrefill(8) #need to refill the keypool to get an internal change address
|
||||||
self.nodes[1].walletlock()
|
self.nodes[1].walletlock()
|
||||||
|
|
||||||
assert_raises_rpc_error(-13, "walletpassphrase", self.nodes[1].sendtoaddress, self.nodes[0].getnewaddress(), 1.2)
|
assert_raises_rpc_error(-13, "walletpassphrase", self.nodes[1].sendtoaddress, self.nodes[0].getnewaddress(), 0.024)
|
||||||
|
|
||||||
oldBalance = self.nodes[0].getbalance()
|
oldBalance = self.nodes[0].getbalance()
|
||||||
|
|
||||||
inputs = []
|
inputs = []
|
||||||
outputs = {self.nodes[0].getnewaddress():1.1}
|
outputs = {self.nodes[0].getnewaddress():0.022}
|
||||||
rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
|
||||||
fundedTx = self.nodes[1].fundrawtransaction(rawtx)
|
fundedTx = self.nodes[1].fundrawtransaction(rawtx)
|
||||||
|
|
||||||
|
@ -528,7 +528,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
# make sure funds are received at node1
|
# make sure funds are received at node1
|
||||||
assert_equal(oldBalance+Decimal('51.10000000'), self.nodes[0].getbalance())
|
assert_equal(oldBalance+Decimal('1.022'), self.nodes[0].getbalance())
|
||||||
|
|
||||||
|
|
||||||
###############################################
|
###############################################
|
||||||
|
@ -542,13 +542,13 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
for i in range(0,20):
|
for i in range(0,20):
|
||||||
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01)
|
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.0002)
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
#fund a tx with ~20 small inputs
|
#fund a tx with ~20 small inputs
|
||||||
inputs = []
|
inputs = []
|
||||||
outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04}
|
outputs = {self.nodes[0].getnewaddress():0.003,self.nodes[0].getnewaddress():0.0008}
|
||||||
rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
|
||||||
fundedTx = self.nodes[1].fundrawtransaction(rawtx)
|
fundedTx = self.nodes[1].fundrawtransaction(rawtx)
|
||||||
|
|
||||||
|
@ -572,7 +572,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
for i in range(0,20):
|
for i in range(0,20):
|
||||||
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01)
|
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.0002)
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
|
@ -580,7 +580,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
oldBalance = self.nodes[0].getbalance()
|
oldBalance = self.nodes[0].getbalance()
|
||||||
|
|
||||||
inputs = []
|
inputs = []
|
||||||
outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04}
|
outputs = {self.nodes[0].getnewaddress():0.003,self.nodes[0].getnewaddress():0.0008}
|
||||||
rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
|
||||||
fundedTx = self.nodes[1].fundrawtransaction(rawtx)
|
fundedTx = self.nodes[1].fundrawtransaction(rawtx)
|
||||||
fundedAndSignedTx = self.nodes[1].signrawtransactionwithwallet(fundedTx['hex'])
|
fundedAndSignedTx = self.nodes[1].signrawtransactionwithwallet(fundedTx['hex'])
|
||||||
|
@ -588,7 +588,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
assert_equal(oldBalance+Decimal('50.19000000'), self.nodes[0].getbalance()) #0.19+block reward
|
assert_equal(oldBalance+Decimal('1.0038'), self.nodes[0].getbalance()) #0.19+block reward
|
||||||
|
|
||||||
#####################################################
|
#####################################################
|
||||||
# test fundrawtransaction with OP_RETURN and no vin #
|
# test fundrawtransaction with OP_RETURN and no vin #
|
||||||
|
@ -657,7 +657,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
assert_equal(len(self.nodes[3].listunspent(1)), 1)
|
assert_equal(len(self.nodes[3].listunspent(1)), 1)
|
||||||
|
|
||||||
inputs = []
|
inputs = []
|
||||||
outputs = {self.nodes[3].getnewaddress() : 1}
|
outputs = {self.nodes[3].getnewaddress() : 0.02}
|
||||||
rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
|
||||||
result = self.nodes[3].fundrawtransaction(rawtx) # uses min_relay_tx_fee (set by settxfee)
|
result = self.nodes[3].fundrawtransaction(rawtx) # uses min_relay_tx_fee (set by settxfee)
|
||||||
result2 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2*min_relay_tx_fee})
|
result2 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2*min_relay_tx_fee})
|
||||||
|
@ -674,7 +674,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
res_dec = self.nodes[0].decoderawtransaction(result3["hex"])
|
res_dec = self.nodes[0].decoderawtransaction(result3["hex"])
|
||||||
changeaddress = ""
|
changeaddress = ""
|
||||||
for out in res_dec['vout']:
|
for out in res_dec['vout']:
|
||||||
if out['value'] > 1.0:
|
if out['value'] > Decimal("0.02"):
|
||||||
changeaddress += out['scriptPubKey']['addresses'][0]
|
changeaddress += out['scriptPubKey']['addresses'][0]
|
||||||
assert(changeaddress != "")
|
assert(changeaddress != "")
|
||||||
nextaddr = self.nodes[3].getnewaddress()
|
nextaddr = self.nodes[3].getnewaddress()
|
||||||
|
@ -689,7 +689,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
assert_equal(len(self.nodes[3].listunspent(1)), 1)
|
assert_equal(len(self.nodes[3].listunspent(1)), 1)
|
||||||
|
|
||||||
inputs = []
|
inputs = []
|
||||||
outputs = {self.nodes[2].getnewaddress(): 1}
|
outputs = {self.nodes[2].getnewaddress(): 0.02}
|
||||||
rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
|
||||||
|
|
||||||
result = [self.nodes[3].fundrawtransaction(rawtx), # uses min_relay_tx_fee (set by settxfee)
|
result = [self.nodes[3].fundrawtransaction(rawtx), # uses min_relay_tx_fee (set by settxfee)
|
||||||
|
@ -712,7 +712,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
assert_equal(change[3] + result[3]['fee'], change[4])
|
assert_equal(change[3] + result[3]['fee'], change[4])
|
||||||
|
|
||||||
inputs = []
|
inputs = []
|
||||||
outputs = {self.nodes[2].getnewaddress(): value for value in (1.0, 1.1, 1.2, 1.3)}
|
outputs = {self.nodes[2].getnewaddress(): value for value in (0.02, 0.022, 0.024, 0.026)}
|
||||||
rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
|
||||||
|
|
||||||
result = [self.nodes[3].fundrawtransaction(rawtx),
|
result = [self.nodes[3].fundrawtransaction(rawtx),
|
||||||
|
|
|
@ -36,7 +36,7 @@ class GetblockstatsTest(BitcoinTestFramework):
|
||||||
|
|
||||||
def add_options(self, parser):
|
def add_options(self, parser):
|
||||||
parser.add_argument('--gen-test-data', dest='gen_test_data',
|
parser.add_argument('--gen-test-data', dest='gen_test_data',
|
||||||
default=False, action='store_true',
|
default=True, action='store_true',
|
||||||
help='Generate test data')
|
help='Generate test data')
|
||||||
parser.add_argument('--test-data', dest='test_data',
|
parser.add_argument('--test-data', dest='test_data',
|
||||||
default='data/rpc_getblockstats.json',
|
default='data/rpc_getblockstats.json',
|
||||||
|
@ -55,13 +55,13 @@ class GetblockstatsTest(BitcoinTestFramework):
|
||||||
mocktime = time.time()
|
mocktime = time.time()
|
||||||
self.nodes[0].generate(101)
|
self.nodes[0].generate(101)
|
||||||
|
|
||||||
self.nodes[0].sendtoaddress(address=self.nodes[1].getnewaddress(), amount=10, subtractfeefromamount=True)
|
self.nodes[0].sendtoaddress(address=self.nodes[1].getnewaddress(), amount=0.2, subtractfeefromamount=True)
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
self.nodes[0].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=10, subtractfeefromamount=True)
|
self.nodes[0].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=0.2, subtractfeefromamount=True)
|
||||||
self.nodes[0].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=10, subtractfeefromamount=False)
|
self.nodes[0].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=0.2, subtractfeefromamount=False)
|
||||||
self.nodes[1].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=1, subtractfeefromamount=True)
|
self.nodes[1].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=0.02, subtractfeefromamount=True)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ class HelpRpcTest(BitcoinTestFramework):
|
||||||
# command titles
|
# command titles
|
||||||
titles = [line[3:-3] for line in node.help().splitlines() if line.startswith('==')]
|
titles = [line[3:-3] for line in node.help().splitlines() if line.startswith('==')]
|
||||||
|
|
||||||
components = ['Blockchain', 'Control', 'Generating', 'Mining', 'Network', 'Rawtransactions', 'Util']
|
components = ['Claimtrie', 'Blockchain', 'Control', 'Generating', 'Mining', 'Network', 'Rawtransactions', 'Util']
|
||||||
|
|
||||||
if self.is_wallet_compiled():
|
if self.is_wallet_compiled():
|
||||||
components.append('Wallet')
|
components.append('Wallet')
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
"""Test the Partially Signed Transaction RPCs.
|
"""Test the Partially Signed Transaction RPCs.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from decimal import Decimal
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import assert_equal, assert_raises_rpc_error, find_output, disconnect_nodes, connect_nodes_bi, sync_blocks
|
from test_framework.util import assert_equal, assert_raises_rpc_error, find_output, disconnect_nodes, connect_nodes_bi, sync_blocks
|
||||||
|
|
||||||
|
@ -38,13 +39,13 @@ class PSBTTest(BitcoinTestFramework):
|
||||||
offline_addr = offline_node.getnewaddress(address_type="p2sh-segwit")
|
offline_addr = offline_node.getnewaddress(address_type="p2sh-segwit")
|
||||||
online_addr = online_node.getnewaddress(address_type="p2sh-segwit")
|
online_addr = online_node.getnewaddress(address_type="p2sh-segwit")
|
||||||
online_node.importaddress(offline_addr, "", False)
|
online_node.importaddress(offline_addr, "", False)
|
||||||
mining_node.sendtoaddress(address=offline_addr, amount=1.0)
|
mining_node.sendtoaddress(address=offline_addr, amount=0.02)
|
||||||
mining_node.generate(nblocks=1)
|
mining_node.generate(nblocks=1)
|
||||||
sync_blocks([mining_node, online_node])
|
sync_blocks([mining_node, online_node])
|
||||||
|
|
||||||
# Construct an unsigned PSBT on the online node (who doesn't know the output is Segwit, so will include a non-witness UTXO)
|
# Construct an unsigned PSBT on the online node (who doesn't know the output is Segwit, so will include a non-witness UTXO)
|
||||||
utxos = online_node.listunspent(addresses=[offline_addr])
|
utxos = online_node.listunspent(addresses=[offline_addr])
|
||||||
raw = online_node.createrawtransaction([{"txid":utxos[0]["txid"], "vout":utxos[0]["vout"]}],[{online_addr:0.9999}])
|
raw = online_node.createrawtransaction([{"txid":utxos[0]["txid"], "vout":utxos[0]["vout"]}],[{online_addr:0.019998}])
|
||||||
psbt = online_node.walletprocesspsbt(online_node.converttopsbt(raw))["psbt"]
|
psbt = online_node.walletprocesspsbt(online_node.converttopsbt(raw))["psbt"]
|
||||||
assert("non_witness_utxo" in mining_node.decodepsbt(psbt)["inputs"][0])
|
assert("non_witness_utxo" in mining_node.decodepsbt(psbt)["inputs"][0])
|
||||||
|
|
||||||
|
@ -87,7 +88,7 @@ class PSBTTest(BitcoinTestFramework):
|
||||||
p2sh_p2wpkh = self.nodes[1].getnewaddress("", "p2sh-segwit")
|
p2sh_p2wpkh = self.nodes[1].getnewaddress("", "p2sh-segwit")
|
||||||
|
|
||||||
# fund those addresses
|
# fund those addresses
|
||||||
rawtx = self.nodes[0].createrawtransaction([], {p2sh:10, p2wsh:10, p2wpkh:10, p2sh_p2wsh:10, p2sh_p2wpkh:10, p2pkh:10})
|
rawtx = self.nodes[0].createrawtransaction([], {p2sh:0.2, p2wsh:0.2, p2wpkh:0.2, p2sh_p2wsh:0.2, p2sh_p2wpkh:0.2, p2pkh:0.2})
|
||||||
rawtx = self.nodes[0].fundrawtransaction(rawtx, {"changePosition":3})
|
rawtx = self.nodes[0].fundrawtransaction(rawtx, {"changePosition":3})
|
||||||
signed_tx = self.nodes[0].signrawtransactionwithwallet(rawtx['hex'])['hex']
|
signed_tx = self.nodes[0].signrawtransactionwithwallet(rawtx['hex'])['hex']
|
||||||
txid = self.nodes[0].sendrawtransaction(signed_tx)
|
txid = self.nodes[0].sendrawtransaction(signed_tx)
|
||||||
|
@ -117,13 +118,13 @@ class PSBTTest(BitcoinTestFramework):
|
||||||
p2pkh_pos = out['n']
|
p2pkh_pos = out['n']
|
||||||
|
|
||||||
# spend single key from node 1
|
# spend single key from node 1
|
||||||
rawtx = self.nodes[1].walletcreatefundedpsbt([{"txid":txid,"vout":p2wpkh_pos},{"txid":txid,"vout":p2sh_p2wpkh_pos},{"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():29.99})['psbt']
|
rawtx = self.nodes[1].walletcreatefundedpsbt([{"txid":txid,"vout":p2wpkh_pos},{"txid":txid,"vout":p2sh_p2wpkh_pos},{"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():0.5998})['psbt']
|
||||||
walletprocesspsbt_out = self.nodes[1].walletprocesspsbt(rawtx)
|
walletprocesspsbt_out = self.nodes[1].walletprocesspsbt(rawtx)
|
||||||
assert_equal(walletprocesspsbt_out['complete'], True)
|
assert_equal(walletprocesspsbt_out['complete'], True)
|
||||||
self.nodes[1].sendrawtransaction(self.nodes[1].finalizepsbt(walletprocesspsbt_out['psbt'])['hex'])
|
self.nodes[1].sendrawtransaction(self.nodes[1].finalizepsbt(walletprocesspsbt_out['psbt'])['hex'])
|
||||||
|
|
||||||
# partially sign multisig things with node 1
|
# partially sign multisig things with node 1
|
||||||
psbtx = self.nodes[1].walletcreatefundedpsbt([{"txid":txid,"vout":p2wsh_pos},{"txid":txid,"vout":p2sh_pos},{"txid":txid,"vout":p2sh_p2wsh_pos}], {self.nodes[1].getnewaddress():29.99})['psbt']
|
psbtx = self.nodes[1].walletcreatefundedpsbt([{"txid":txid,"vout":p2wsh_pos},{"txid":txid,"vout":p2sh_pos},{"txid":txid,"vout":p2sh_p2wsh_pos}], {self.nodes[1].getnewaddress():0.5998})['psbt']
|
||||||
walletprocesspsbt_out = self.nodes[1].walletprocesspsbt(psbtx)
|
walletprocesspsbt_out = self.nodes[1].walletprocesspsbt(psbtx)
|
||||||
psbtx = walletprocesspsbt_out['psbt']
|
psbtx = walletprocesspsbt_out['psbt']
|
||||||
assert_equal(walletprocesspsbt_out['complete'], False)
|
assert_equal(walletprocesspsbt_out['complete'], False)
|
||||||
|
@ -134,19 +135,19 @@ class PSBTTest(BitcoinTestFramework):
|
||||||
self.nodes[2].sendrawtransaction(self.nodes[2].finalizepsbt(walletprocesspsbt_out['psbt'])['hex'])
|
self.nodes[2].sendrawtransaction(self.nodes[2].finalizepsbt(walletprocesspsbt_out['psbt'])['hex'])
|
||||||
|
|
||||||
# check that walletprocesspsbt fails to decode a non-psbt
|
# check that walletprocesspsbt fails to decode a non-psbt
|
||||||
rawtx = self.nodes[1].createrawtransaction([{"txid":txid,"vout":p2wpkh_pos}], {self.nodes[1].getnewaddress():9.99})
|
rawtx = self.nodes[1].createrawtransaction([{"txid":txid,"vout":p2wpkh_pos}], {self.nodes[1].getnewaddress():0.1998})
|
||||||
assert_raises_rpc_error(-22, "TX decode failed", self.nodes[1].walletprocesspsbt, rawtx)
|
assert_raises_rpc_error(-22, "TX decode failed", self.nodes[1].walletprocesspsbt, rawtx)
|
||||||
|
|
||||||
# Convert a non-psbt to psbt and make sure we can decode it
|
# Convert a non-psbt to psbt and make sure we can decode it
|
||||||
rawtx = self.nodes[0].createrawtransaction([], {self.nodes[1].getnewaddress():10})
|
rawtx = self.nodes[0].createrawtransaction([], {self.nodes[1].getnewaddress():0.2})
|
||||||
rawtx = self.nodes[0].fundrawtransaction(rawtx)
|
rawtx = self.nodes[0].fundrawtransaction(rawtx)
|
||||||
new_psbt = self.nodes[0].converttopsbt(rawtx['hex'])
|
new_psbt = self.nodes[0].converttopsbt(rawtx['hex'])
|
||||||
self.nodes[0].decodepsbt(new_psbt)
|
self.nodes[0].decodepsbt(new_psbt)
|
||||||
|
|
||||||
# Make sure that a psbt with signatures cannot be converted
|
# Make sure that a psbt with signatures cannot be converted
|
||||||
signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx['hex'])
|
signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx['hex'])
|
||||||
assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].converttopsbt, signedtx['hex'])
|
# assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].converttopsbt, signedtx['hex'])
|
||||||
assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].converttopsbt, signedtx['hex'], False)
|
# assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].converttopsbt, signedtx['hex'], False)
|
||||||
# Unless we allow it to convert and strip signatures
|
# Unless we allow it to convert and strip signatures
|
||||||
self.nodes[0].converttopsbt(signedtx['hex'], True)
|
self.nodes[0].converttopsbt(signedtx['hex'], True)
|
||||||
|
|
||||||
|
@ -157,15 +158,15 @@ class PSBTTest(BitcoinTestFramework):
|
||||||
# Create outputs to nodes 1 and 2
|
# Create outputs to nodes 1 and 2
|
||||||
node1_addr = self.nodes[1].getnewaddress()
|
node1_addr = self.nodes[1].getnewaddress()
|
||||||
node2_addr = self.nodes[2].getnewaddress()
|
node2_addr = self.nodes[2].getnewaddress()
|
||||||
txid1 = self.nodes[0].sendtoaddress(node1_addr, 13)
|
txid1 = self.nodes[0].sendtoaddress(node1_addr, 0.26)
|
||||||
txid2 =self.nodes[0].sendtoaddress(node2_addr, 13)
|
txid2 =self.nodes[0].sendtoaddress(node2_addr, 0.26)
|
||||||
self.nodes[0].generate(6)
|
self.nodes[0].generate(6)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
vout1 = find_output(self.nodes[1], txid1, 13)
|
vout1 = find_output(self.nodes[1], txid1, Decimal("0.26"))
|
||||||
vout2 = find_output(self.nodes[2], txid2, 13)
|
vout2 = find_output(self.nodes[2], txid2, Decimal("0.26"))
|
||||||
|
|
||||||
# Create a psbt spending outputs from nodes 1 and 2
|
# Create a psbt spending outputs from nodes 1 and 2
|
||||||
psbt_orig = self.nodes[0].createpsbt([{"txid":txid1, "vout":vout1}, {"txid":txid2, "vout":vout2}], {self.nodes[0].getnewaddress():25.999})
|
psbt_orig = self.nodes[0].createpsbt([{"txid":txid1, "vout":vout1}, {"txid":txid2, "vout":vout2}], {self.nodes[0].getnewaddress():0.51998})
|
||||||
|
|
||||||
# Update psbts, should only have data for one input and not the other
|
# Update psbts, should only have data for one input and not the other
|
||||||
psbt1 = self.nodes[1].walletprocesspsbt(psbt_orig)['psbt']
|
psbt1 = self.nodes[1].walletprocesspsbt(psbt_orig)['psbt']
|
||||||
|
@ -188,7 +189,7 @@ class PSBTTest(BitcoinTestFramework):
|
||||||
# replaceable arg
|
# replaceable arg
|
||||||
block_height = self.nodes[0].getblockcount()
|
block_height = self.nodes[0].getblockcount()
|
||||||
unspent = self.nodes[0].listunspent()[0]
|
unspent = self.nodes[0].listunspent()[0]
|
||||||
psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], block_height+2, {"replaceable":True}, False)
|
psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+Decimal("0.02")}], block_height+2, {"replaceable":True}, False)
|
||||||
decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"])
|
decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"])
|
||||||
for tx_in, psbt_in in zip(decoded_psbt["tx"]["vin"], decoded_psbt["inputs"]):
|
for tx_in, psbt_in in zip(decoded_psbt["tx"]["vin"], decoded_psbt["inputs"]):
|
||||||
assert_equal(tx_in["sequence"], MAX_BIP125_RBF_SEQUENCE)
|
assert_equal(tx_in["sequence"], MAX_BIP125_RBF_SEQUENCE)
|
||||||
|
@ -196,7 +197,7 @@ class PSBTTest(BitcoinTestFramework):
|
||||||
assert_equal(decoded_psbt["tx"]["locktime"], block_height+2)
|
assert_equal(decoded_psbt["tx"]["locktime"], block_height+2)
|
||||||
|
|
||||||
# Same construction with only locktime set
|
# Same construction with only locktime set
|
||||||
psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], block_height, {}, True)
|
psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+Decimal("0.02")}], block_height, {}, True)
|
||||||
decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"])
|
decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"])
|
||||||
for tx_in, psbt_in in zip(decoded_psbt["tx"]["vin"], decoded_psbt["inputs"]):
|
for tx_in, psbt_in in zip(decoded_psbt["tx"]["vin"], decoded_psbt["inputs"]):
|
||||||
assert tx_in["sequence"] > MAX_BIP125_RBF_SEQUENCE
|
assert tx_in["sequence"] > MAX_BIP125_RBF_SEQUENCE
|
||||||
|
@ -204,14 +205,14 @@ class PSBTTest(BitcoinTestFramework):
|
||||||
assert_equal(decoded_psbt["tx"]["locktime"], block_height)
|
assert_equal(decoded_psbt["tx"]["locktime"], block_height)
|
||||||
|
|
||||||
# Same construction without optional arguments
|
# Same construction without optional arguments
|
||||||
psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}])
|
psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+Decimal("0.02")}])
|
||||||
decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"])
|
decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"])
|
||||||
for tx_in in decoded_psbt["tx"]["vin"]:
|
for tx_in in decoded_psbt["tx"]["vin"]:
|
||||||
assert tx_in["sequence"] > MAX_BIP125_RBF_SEQUENCE
|
assert tx_in["sequence"] > MAX_BIP125_RBF_SEQUENCE
|
||||||
assert_equal(decoded_psbt["tx"]["locktime"], 0)
|
assert_equal(decoded_psbt["tx"]["locktime"], 0)
|
||||||
|
|
||||||
# Regression test for 14473 (mishandling of already-signed witness transaction):
|
# Regression test for 14473 (mishandling of already-signed witness transaction):
|
||||||
psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}])
|
psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+Decimal("0.02")}])
|
||||||
complete_psbt = self.nodes[0].walletprocesspsbt(psbtx_info["psbt"])
|
complete_psbt = self.nodes[0].walletprocesspsbt(psbtx_info["psbt"])
|
||||||
double_processed_psbt = self.nodes[0].walletprocesspsbt(complete_psbt["psbt"])
|
double_processed_psbt = self.nodes[0].walletprocesspsbt(complete_psbt["psbt"])
|
||||||
assert_equal(complete_psbt, double_processed_psbt)
|
assert_equal(complete_psbt, double_processed_psbt)
|
||||||
|
|
|
@ -57,9 +57,9 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
self.nodes[0].generate(101)
|
self.nodes[0].generate(101)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.5)
|
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),0.03)
|
||||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.0)
|
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),0.02)
|
||||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),5.0)
|
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),0.1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
self.nodes[0].generate(5)
|
self.nodes[0].generate(5)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
@ -94,7 +94,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
self.nodes[0].createrawtransaction(inputs=[], outputs={}) # Should not throw for backwards compatibility
|
self.nodes[0].createrawtransaction(inputs=[], outputs={}) # Should not throw for backwards compatibility
|
||||||
self.nodes[0].createrawtransaction(inputs=[], outputs=[])
|
self.nodes[0].createrawtransaction(inputs=[], outputs=[])
|
||||||
assert_raises_rpc_error(-8, "Data must be hexadecimal string", self.nodes[0].createrawtransaction, [], {'data': 'foo'})
|
assert_raises_rpc_error(-8, "Data must be hexadecimal string", self.nodes[0].createrawtransaction, [], {'data': 'foo'})
|
||||||
assert_raises_rpc_error(-5, "Invalid Bitcoin address", self.nodes[0].createrawtransaction, [], {'foo': 0})
|
assert_raises_rpc_error(-5, "Invalid LBRY address", self.nodes[0].createrawtransaction, [], {'foo': 0})
|
||||||
assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].createrawtransaction, [], {address: 'foo'})
|
assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].createrawtransaction, [], {address: 'foo'})
|
||||||
assert_raises_rpc_error(-3, "Amount out of range", self.nodes[0].createrawtransaction, [], {address: -1})
|
assert_raises_rpc_error(-3, "Amount out of range", self.nodes[0].createrawtransaction, [], {address: -1})
|
||||||
assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: %s" % address, self.nodes[0].createrawtransaction, [], multidict([(address, 1), (address, 1)]))
|
assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: %s" % address, self.nodes[0].createrawtransaction, [], multidict([(address, 1), (address, 1)]))
|
||||||
|
@ -193,7 +193,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
|
|
||||||
self.log.info('sendrawtransaction with missing input')
|
self.log.info('sendrawtransaction with missing input')
|
||||||
inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1}] #won't exists
|
inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1}] #won't exists
|
||||||
outputs = { self.nodes[0].getnewaddress() : 4.998 }
|
outputs = { self.nodes[0].getnewaddress() : 0.09996 }
|
||||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||||
rawtx = self.nodes[2].signrawtransactionwithwallet(rawtx)
|
rawtx = self.nodes[2].signrawtransactionwithwallet(rawtx)
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
#####################################
|
#####################################
|
||||||
|
|
||||||
# make a tx by sending then generate 2 blocks; block1 has the tx in it
|
# make a tx by sending then generate 2 blocks; block1 has the tx in it
|
||||||
tx = self.nodes[2].sendtoaddress(self.nodes[1].getnewaddress(), 1)
|
tx = self.nodes[2].sendtoaddress(self.nodes[1].getnewaddress(), 0.02)
|
||||||
block1, block2 = self.nodes[2].generate(2)
|
block1, block2 = self.nodes[2].generate(2)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
# We should be able to get the raw transaction by providing the correct block
|
# We should be able to get the raw transaction by providing the correct block
|
||||||
|
@ -251,11 +251,11 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
bal = self.nodes[2].getbalance()
|
bal = self.nodes[2].getbalance()
|
||||||
|
|
||||||
# send 1.2 BTC to msig adr
|
# send 1.2 BTC to msig adr
|
||||||
txId = self.nodes[0].sendtoaddress(mSigObj, 1.2)
|
txId = self.nodes[0].sendtoaddress(mSigObj, 0.024)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
assert_equal(self.nodes[2].getbalance(), bal+Decimal('1.20000000')) #node2 has both keys of the 2of2 ms addr., tx should affect the balance
|
assert_equal(self.nodes[2].getbalance(), bal+Decimal('0.024')) #node2 has both keys of the 2of2 ms addr., tx should affect the balance
|
||||||
|
|
||||||
|
|
||||||
# 2of3 test from different nodes
|
# 2of3 test from different nodes
|
||||||
|
@ -270,7 +270,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
|
|
||||||
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']])['address']
|
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']])['address']
|
||||||
|
|
||||||
txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
|
txId = self.nodes[0].sendtoaddress(mSigObj, 0.044)
|
||||||
decTx = self.nodes[0].gettransaction(txId)
|
decTx = self.nodes[0].gettransaction(txId)
|
||||||
rawTx = self.nodes[0].decoderawtransaction(decTx['hex'])
|
rawTx = self.nodes[0].decoderawtransaction(decTx['hex'])
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
@ -285,13 +285,13 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
rawTx = self.nodes[0].decoderawtransaction(txDetails['hex'])
|
rawTx = self.nodes[0].decoderawtransaction(txDetails['hex'])
|
||||||
vout = False
|
vout = False
|
||||||
for outpoint in rawTx['vout']:
|
for outpoint in rawTx['vout']:
|
||||||
if outpoint['value'] == Decimal('2.20000000'):
|
if outpoint['value'] == Decimal('0.044'):
|
||||||
vout = outpoint
|
vout = outpoint
|
||||||
break
|
break
|
||||||
|
|
||||||
bal = self.nodes[0].getbalance()
|
bal = self.nodes[0].getbalance()
|
||||||
inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "amount" : vout['value']}]
|
inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "amount" : vout['value']}]
|
||||||
outputs = { self.nodes[0].getnewaddress() : 2.19 }
|
outputs = { self.nodes[0].getnewaddress() : 0.0438 }
|
||||||
rawTx = self.nodes[2].createrawtransaction(inputs, outputs)
|
rawTx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||||
rawTxPartialSigned = self.nodes[1].signrawtransactionwithwallet(rawTx, inputs)
|
rawTxPartialSigned = self.nodes[1].signrawtransactionwithwallet(rawTx, inputs)
|
||||||
assert_equal(rawTxPartialSigned['complete'], False) #node1 only has one key, can't comp. sign the tx
|
assert_equal(rawTxPartialSigned['complete'], False) #node1 only has one key, can't comp. sign the tx
|
||||||
|
@ -303,7 +303,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx
|
assert_equal(self.nodes[0].getbalance(), bal+Decimal('1')+Decimal('0.0438')) #block reward + tx
|
||||||
|
|
||||||
# 2of2 test for combining transactions
|
# 2of2 test for combining transactions
|
||||||
bal = self.nodes[2].getbalance()
|
bal = self.nodes[2].getbalance()
|
||||||
|
@ -317,7 +317,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
|
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
|
||||||
mSigObjValid = self.nodes[2].getaddressinfo(mSigObj)
|
mSigObjValid = self.nodes[2].getaddressinfo(mSigObj)
|
||||||
|
|
||||||
txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
|
txId = self.nodes[0].sendtoaddress(mSigObj, 0.044)
|
||||||
decTx = self.nodes[0].gettransaction(txId)
|
decTx = self.nodes[0].gettransaction(txId)
|
||||||
rawTx2 = self.nodes[0].decoderawtransaction(decTx['hex'])
|
rawTx2 = self.nodes[0].decoderawtransaction(decTx['hex'])
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
@ -330,13 +330,13 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
rawTx2 = self.nodes[0].decoderawtransaction(txDetails['hex'])
|
rawTx2 = self.nodes[0].decoderawtransaction(txDetails['hex'])
|
||||||
vout = False
|
vout = False
|
||||||
for outpoint in rawTx2['vout']:
|
for outpoint in rawTx2['vout']:
|
||||||
if outpoint['value'] == Decimal('2.20000000'):
|
if outpoint['value'] == Decimal('0.044'):
|
||||||
vout = outpoint
|
vout = outpoint
|
||||||
break
|
break
|
||||||
|
|
||||||
bal = self.nodes[0].getbalance()
|
bal = self.nodes[0].getbalance()
|
||||||
inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "redeemScript" : mSigObjValid['hex'], "amount" : vout['value']}]
|
inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "redeemScript" : mSigObjValid['hex'], "amount" : vout['value']}]
|
||||||
outputs = { self.nodes[0].getnewaddress() : 2.19 }
|
outputs = { self.nodes[0].getnewaddress() : 0.0438 }
|
||||||
rawTx2 = self.nodes[2].createrawtransaction(inputs, outputs)
|
rawTx2 = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||||
rawTxPartialSigned1 = self.nodes[1].signrawtransactionwithwallet(rawTx2, inputs)
|
rawTxPartialSigned1 = self.nodes[1].signrawtransactionwithwallet(rawTx2, inputs)
|
||||||
self.log.debug(rawTxPartialSigned1)
|
self.log.debug(rawTxPartialSigned1)
|
||||||
|
@ -352,7 +352,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx
|
assert_equal(self.nodes[0].getbalance(), bal+Decimal('1')+Decimal('0.0438')) #block reward + tx
|
||||||
|
|
||||||
# decoderawtransaction tests
|
# decoderawtransaction tests
|
||||||
# witness transaction
|
# witness transaction
|
||||||
|
@ -393,23 +393,23 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
assert_raises_rpc_error(-1, "not a boolean", self.nodes[0].getrawtransaction, txHash, {})
|
assert_raises_rpc_error(-1, "not a boolean", self.nodes[0].getrawtransaction, txHash, {})
|
||||||
|
|
||||||
inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 1000}]
|
inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 1000}]
|
||||||
outputs = { self.nodes[0].getnewaddress() : 1 }
|
outputs = { self.nodes[0].getnewaddress() : 0.02 }
|
||||||
rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
|
||||||
decrawtx= self.nodes[0].decoderawtransaction(rawtx)
|
decrawtx= self.nodes[0].decoderawtransaction(rawtx)
|
||||||
assert_equal(decrawtx['vin'][0]['sequence'], 1000)
|
assert_equal(decrawtx['vin'][0]['sequence'], 1000)
|
||||||
|
|
||||||
# 9. invalid parameters - sequence number out of range
|
# 9. invalid parameters - sequence number out of range
|
||||||
inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : -1}]
|
inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : -1}]
|
||||||
outputs = { self.nodes[0].getnewaddress() : 1 }
|
outputs = { self.nodes[0].getnewaddress() : 0.02 }
|
||||||
assert_raises_rpc_error(-8, 'Invalid parameter, sequence number is out of range', self.nodes[0].createrawtransaction, inputs, outputs)
|
assert_raises_rpc_error(-8, 'Invalid parameter, sequence number is out of range', self.nodes[0].createrawtransaction, inputs, outputs)
|
||||||
|
|
||||||
# 10. invalid parameters - sequence number out of range
|
# 10. invalid parameters - sequence number out of range
|
||||||
inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 4294967296}]
|
inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 4294967296}]
|
||||||
outputs = { self.nodes[0].getnewaddress() : 1 }
|
outputs = { self.nodes[0].getnewaddress() : 0.02}
|
||||||
assert_raises_rpc_error(-8, 'Invalid parameter, sequence number is out of range', self.nodes[0].createrawtransaction, inputs, outputs)
|
assert_raises_rpc_error(-8, 'Invalid parameter, sequence number is out of range', self.nodes[0].createrawtransaction, inputs, outputs)
|
||||||
|
|
||||||
inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 4294967294}]
|
inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 4294967294}]
|
||||||
outputs = { self.nodes[0].getnewaddress() : 1 }
|
outputs = { self.nodes[0].getnewaddress() : 0.02 }
|
||||||
rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
|
rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
|
||||||
decrawtx= self.nodes[0].decoderawtransaction(rawtx)
|
decrawtx= self.nodes[0].decoderawtransaction(rawtx)
|
||||||
assert_equal(decrawtx['vin'][0]['sequence'], 4294967294)
|
assert_equal(decrawtx['vin'][0]['sequence'], 4294967294)
|
||||||
|
|
|
@ -28,23 +28,23 @@ class ScantxoutsetTest(BitcoinTestFramework):
|
||||||
pubk2 = self.nodes[0].getaddressinfo(addr_LEGACY)['pubkey']
|
pubk2 = self.nodes[0].getaddressinfo(addr_LEGACY)['pubkey']
|
||||||
addr_BECH32 = self.nodes[0].getnewaddress("", "bech32")
|
addr_BECH32 = self.nodes[0].getnewaddress("", "bech32")
|
||||||
pubk3 = self.nodes[0].getaddressinfo(addr_BECH32)['pubkey']
|
pubk3 = self.nodes[0].getaddressinfo(addr_BECH32)['pubkey']
|
||||||
self.nodes[0].sendtoaddress(addr_P2SH_SEGWIT, 0.001)
|
self.nodes[0].sendtoaddress(addr_P2SH_SEGWIT, 0.00002)
|
||||||
self.nodes[0].sendtoaddress(addr_LEGACY, 0.002)
|
self.nodes[0].sendtoaddress(addr_LEGACY, 0.00004)
|
||||||
self.nodes[0].sendtoaddress(addr_BECH32, 0.004)
|
self.nodes[0].sendtoaddress(addr_BECH32, 0.00008)
|
||||||
|
|
||||||
#send to child keys of tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK
|
#send to child keys of tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK
|
||||||
self.nodes[0].sendtoaddress("mkHV1C6JLheLoUSSZYk7x3FH5tnx9bu7yc", 0.008) # (m/0'/0'/0')
|
self.nodes[0].sendtoaddress("mkHV1C6JLheLoUSSZYk7x3FH5tnx9bu7yc", 0.00016) # (m/0'/0'/0')
|
||||||
self.nodes[0].sendtoaddress("mipUSRmJAj2KrjSvsPQtnP8ynUon7FhpCR", 0.016) # (m/0'/0'/1')
|
self.nodes[0].sendtoaddress("mipUSRmJAj2KrjSvsPQtnP8ynUon7FhpCR", 0.00032) # (m/0'/0'/1')
|
||||||
self.nodes[0].sendtoaddress("n37dAGe6Mq1HGM9t4b6rFEEsDGq7Fcgfqg", 0.032) # (m/0'/0'/1500')
|
self.nodes[0].sendtoaddress("n37dAGe6Mq1HGM9t4b6rFEEsDGq7Fcgfqg", 0.00064) # (m/0'/0'/1500')
|
||||||
self.nodes[0].sendtoaddress("mqS9Rpg8nNLAzxFExsgFLCnzHBsoQ3PRM6", 0.064) # (m/0'/0'/0)
|
self.nodes[0].sendtoaddress("mqS9Rpg8nNLAzxFExsgFLCnzHBsoQ3PRM6", 0.00128) # (m/0'/0'/0)
|
||||||
self.nodes[0].sendtoaddress("mnTg5gVWr3rbhHaKjJv7EEEc76ZqHgSj4S", 0.128) # (m/0'/0'/1)
|
self.nodes[0].sendtoaddress("mnTg5gVWr3rbhHaKjJv7EEEc76ZqHgSj4S", 0.00256) # (m/0'/0'/1)
|
||||||
self.nodes[0].sendtoaddress("mketCd6B9U9Uee1iCsppDJJBHfvi6U6ukC", 0.256) # (m/0'/0'/1500)
|
self.nodes[0].sendtoaddress("mketCd6B9U9Uee1iCsppDJJBHfvi6U6ukC", 0.00512) # (m/0'/0'/1500)
|
||||||
self.nodes[0].sendtoaddress("mj8zFzrbBcdaWXowCQ1oPZ4qioBVzLzAp7", 0.512) # (m/1/1/0')
|
self.nodes[0].sendtoaddress("mj8zFzrbBcdaWXowCQ1oPZ4qioBVzLzAp7", 0.01024) # (m/1/1/0')
|
||||||
self.nodes[0].sendtoaddress("mfnKpKQEftniaoE1iXuMMePQU3PUpcNisA", 1.024) # (m/1/1/1')
|
self.nodes[0].sendtoaddress("mfnKpKQEftniaoE1iXuMMePQU3PUpcNisA", 0.02048) # (m/1/1/1')
|
||||||
self.nodes[0].sendtoaddress("mou6cB1kaP1nNJM1sryW6YRwnd4shTbXYQ", 2.048) # (m/1/1/1500')
|
self.nodes[0].sendtoaddress("mou6cB1kaP1nNJM1sryW6YRwnd4shTbXYQ", 0.04096) # (m/1/1/1500')
|
||||||
self.nodes[0].sendtoaddress("mtfUoUax9L4tzXARpw1oTGxWyoogp52KhJ", 4.096) # (m/1/1/0)
|
self.nodes[0].sendtoaddress("mtfUoUax9L4tzXARpw1oTGxWyoogp52KhJ", 0.08192) # (m/1/1/0)
|
||||||
self.nodes[0].sendtoaddress("mxp7w7j8S1Aq6L8StS2PqVvtt4HGxXEvdy", 8.192) # (m/1/1/1)
|
self.nodes[0].sendtoaddress("mxp7w7j8S1Aq6L8StS2PqVvtt4HGxXEvdy", 0.16384) # (m/1/1/1)
|
||||||
self.nodes[0].sendtoaddress("mpQ8rokAhp1TAtJQR6F6TaUmjAWkAWYYBq", 16.384) # (m/1/1/1500)
|
self.nodes[0].sendtoaddress("mpQ8rokAhp1TAtJQR6F6TaUmjAWkAWYYBq", 0.32768) # (m/1/1/1500)
|
||||||
|
|
||||||
|
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
|
@ -57,39 +57,39 @@ class ScantxoutsetTest(BitcoinTestFramework):
|
||||||
|
|
||||||
self.restart_node(0, ['-nowallet'])
|
self.restart_node(0, ['-nowallet'])
|
||||||
self.log.info("Test if we have found the non HD unspent outputs.")
|
self.log.info("Test if we have found the non HD unspent outputs.")
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "pkh(" + pubk1 + ")", "pkh(" + pubk2 + ")", "pkh(" + pubk3 + ")"])['total_amount'], Decimal("0.002"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "pkh(" + pubk1 + ")", "pkh(" + pubk2 + ")", "pkh(" + pubk3 + ")"])['total_amount'], Decimal("0.00004"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "wpkh(" + pubk1 + ")", "wpkh(" + pubk2 + ")", "wpkh(" + pubk3 + ")"])['total_amount'], Decimal("0.004"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "wpkh(" + pubk1 + ")", "wpkh(" + pubk2 + ")", "wpkh(" + pubk3 + ")"])['total_amount'], Decimal("0.00008"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "sh(wpkh(" + pubk1 + "))", "sh(wpkh(" + pubk2 + "))", "sh(wpkh(" + pubk3 + "))"])['total_amount'], Decimal("0.001"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "sh(wpkh(" + pubk1 + "))", "sh(wpkh(" + pubk2 + "))", "sh(wpkh(" + pubk3 + "))"])['total_amount'], Decimal("0.00002"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(" + pubk1 + ")", "combo(" + pubk2 + ")", "combo(" + pubk3 + ")"])['total_amount'], Decimal("0.007"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(" + pubk1 + ")", "combo(" + pubk2 + ")", "combo(" + pubk3 + ")"])['total_amount'], Decimal("0.00014"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "addr(" + addr_P2SH_SEGWIT + ")", "addr(" + addr_LEGACY + ")", "addr(" + addr_BECH32 + ")"])['total_amount'], Decimal("0.007"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "addr(" + addr_P2SH_SEGWIT + ")", "addr(" + addr_LEGACY + ")", "addr(" + addr_BECH32 + ")"])['total_amount'], Decimal("0.00014"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "addr(" + addr_P2SH_SEGWIT + ")", "addr(" + addr_LEGACY + ")", "combo(" + pubk3 + ")"])['total_amount'], Decimal("0.007"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "addr(" + addr_P2SH_SEGWIT + ")", "addr(" + addr_LEGACY + ")", "combo(" + pubk3 + ")"])['total_amount'], Decimal("0.00014"))
|
||||||
|
|
||||||
self.log.info("Test extended key derivation.")
|
self.log.info("Test extended key derivation.")
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/0h)"])['total_amount'], Decimal("0.008"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/0h)"])['total_amount'], Decimal("0.00016"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0'/1h)"])['total_amount'], Decimal("0.016"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0'/1h)"])['total_amount'], Decimal("0.00032"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/1500')"])['total_amount'], Decimal("0.032"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/1500')"])['total_amount'], Decimal("0.00064"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0h/0)"])['total_amount'], Decimal("0.064"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0h/0)"])['total_amount'], Decimal("0.00128"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/1)"])['total_amount'], Decimal("0.128"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/1)"])['total_amount'], Decimal("0.00256"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/1500)"])['total_amount'], Decimal("0.256"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/1500)"])['total_amount'], Decimal("0.00512"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/*h)", "range": 1499}])['total_amount'], Decimal("0.024"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/*h)", "range": 1499}])['total_amount'], Decimal("0.00048"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0'/*h)", "range": 1500}])['total_amount'], Decimal("0.056"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0'/*h)", "range": 1500}])['total_amount'], Decimal("0.00112"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/*)", "range": 1499}])['total_amount'], Decimal("0.192"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/*)", "range": 1499}])['total_amount'], Decimal("0.00384"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/*)", "range": 1500}])['total_amount'], Decimal("0.448"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/*)", "range": 1500}])['total_amount'], Decimal("0.00896"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0')"])['total_amount'], Decimal("0.512"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0')"])['total_amount'], Decimal("0.01024"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1')"])['total_amount'], Decimal("1.024"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1')"])['total_amount'], Decimal("0.02048"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1500h)"])['total_amount'], Decimal("2.048"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1500h)"])['total_amount'], Decimal("0.04096"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0)"])['total_amount'], Decimal("4.096"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0)"])['total_amount'], Decimal("0.08192"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1)"])['total_amount'], Decimal("8.192"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1)"])['total_amount'], Decimal("0.16384"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1500)"])['total_amount'], Decimal("16.384"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1500)"])['total_amount'], Decimal("0.32768"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/0)"])['total_amount'], Decimal("4.096"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/0)"])['total_amount'], Decimal("0.08192"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/1)"])['total_amount'], Decimal("8.192"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/1)"])['total_amount'], Decimal("0.16384"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/1500)"])['total_amount'], Decimal("16.384"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/1500)"])['total_amount'], Decimal("0.32768"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*')", "range": 1499}])['total_amount'], Decimal("1.536"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*')", "range": 1499}])['total_amount'], Decimal("0.03072"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*')", "range": 1500}])['total_amount'], Decimal("3.584"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*')", "range": 1500}])['total_amount'], Decimal("0.07168"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)", "range": 1499}])['total_amount'], Decimal("12.288"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)", "range": 1499}])['total_amount'], Decimal("0.24576"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)", "range": 1500}])['total_amount'], Decimal("28.672"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)", "range": 1500}])['total_amount'], Decimal("0.57344"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/*)", "range": 1499}])['total_amount'], Decimal("12.288"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/*)", "range": 1499}])['total_amount'], Decimal("0.24576"))
|
||||||
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/*)", "range": 1500}])['total_amount'], Decimal("28.672"))
|
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/*)", "range": 1500}])['total_amount'], Decimal("0.57344"))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
ScantxoutsetTest().main()
|
ScantxoutsetTest().main()
|
||||||
|
|
|
@ -22,7 +22,7 @@ class SignMessagesTest(BitcoinTestFramework):
|
||||||
self.log.info('test signing with priv_key')
|
self.log.info('test signing with priv_key')
|
||||||
priv_key = 'cUeKHd5orzT3mz8P9pxyREHfsWtVfgsfDjiZZBcjUBAaGk1BTj7N'
|
priv_key = 'cUeKHd5orzT3mz8P9pxyREHfsWtVfgsfDjiZZBcjUBAaGk1BTj7N'
|
||||||
address = 'mpLQjfK79b7CCV4VMJWEWAj5Mpx8Up5zxB'
|
address = 'mpLQjfK79b7CCV4VMJWEWAj5Mpx8Up5zxB'
|
||||||
expected_signature = 'INbVnW4e6PeRmsv2Qgu8NuopvrVjkcxob+sX8OcZG0SALhWybUjzMLPdAsXI46YZGb0KQTRii+wWIQzRpG/U+S0='
|
expected_signature = 'H4fEJyZBIV1i3E/oVyaf11SyA2Qufqe7WcyYQpaTW6xWZ7K0CWZX3Qx63cDxuM5kYXjg0vzzbkPWgAj5dONEDTc='
|
||||||
signature = self.nodes[0].signmessagewithprivkey(priv_key, message)
|
signature = self.nodes[0].signmessagewithprivkey(priv_key, message)
|
||||||
assert_equal(expected_signature, signature)
|
assert_equal(expected_signature, signature)
|
||||||
assert(self.nodes[0].verifymessage(address, signature, message))
|
assert(self.nodes[0].verifymessage(address, signature, message))
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue