diff --git a/.travis.yml b/.travis.yml index f60e6a9a7..293fbd9ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,70 +1,68 @@ matrix: - include: - - os: linux - sudo: required - dist: xenial - language: c - env: TARGET=linux - - os: linux - sudo: required - dist: xenial - language: c - env: TARGET=windows - - os: osx - language: c - osx_image: xcode8.3 - env: TARGET=osx + include: + - os: linux + sudo: required + dist: trusty + language: c + env: TARGET=linux + - os: linux + sudo: required + dist: trusty + language: c + env: TARGET=windows + - os: osx + language: c + osx_image: xcode7.3 + env: TARGET=osx + cache: apt: true ccache: true directories: - - build - - depends/built -git: - depth: false + - build + - depends/built + before_install: -- date +%s > "${TRAVIS_BUILD_DIR}/start_time" -- ls -lh build -- du -h -d 2 build -- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install ccache; fi -- if [ "$TRAVIS_OS_NAME" == "osx" ]; then export PATH="/usr/local/opt/ccache/libexec:$PATH"; fi + - date +%s > "${TRAVIS_BUILD_DIR}/start_time" + - ls -lh build + - du -h -d 2 build + install: true script: -- mkdir -p "dist/${TRAVIS_BRANCH}" -- if [[ "${TARGET}" == "osx" ]]; then ./reproducible_build.sh -t -o -c; fi -- if [[ "${TARGET}" == "linux" ]]; then ./reproducible_build.sh -t -o -c -f; fi -- if [[ "${TARGET}" == "windows" ]]; then ./packaging/build_windows.sh; fi -- if [[ "${TARGET}" == "osx" ]]; then zip -j "dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip" src/lbrycrdd src/lbrycrd-cli src/lbrycrd-tx; fi -- if [[ "${TARGET}" == "linux" ]]; then zip -j "dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip" src/lbrycrdd src/lbrycrd-cli src/lbrycrd-tx; fi -- if [[ "${TARGET}" == "windows" ]]; then zip -j "dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip" src/lbrycrdd.exe src/lbrycrd-cli.exe src/lbrycrd-tx.exe; fi -- if [[ "${TARGET}" == "osx" ]]; then shasum -a 256 dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip > dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}-sha256.txt; fi -- if [[ "${TARGET}" == "linux" ]]; then sha256sum -b dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip > dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}-sha256.txt; fi -- if [[ "${TARGET}" == "windows" ]]; then sha256sum -b dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip > dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}-sha256.txt; fi -- cat dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}-sha256.txt + - if [[ "${TARGET}" == "osx" ]]; then ./reproducible_build.sh -t -o -c; fi + - if [[ "${TARGET}" == "linux" ]]; then ./reproducible_build.sh -t -o -c -f; fi + - if [[ "${TARGET}" == "windows" ]]; then ./packaging/build_windows.sh; fi + - if [[ "${TARGET}" == "osx" ]]; then zip -j "lbrycrd-${TARGET}.zip" src/lbrycrdd src/lbrycrd-cli src/lbrycrd-tx; fi + - if [[ "${TARGET}" == "linux" ]]; then zip -j "lbrycrd-${TARGET}.zip" src/lbrycrdd src/lbrycrd-cli src/lbrycrd-tx; fi + - if [[ "${TARGET}" == "windows" ]]; then zip -j "lbrycrd-${TARGET}.zip" src/lbrycrdd.exe src/lbrycrd-cli.exe src/lbrycrd-tx.exe; fi + before_cache: -- ls -lh build -- du -h -d 2 build + - ls -lh build + - du -h -d 2 build + deploy: -- provider: releases - draft: true - file: "dist/${TRAVIS_BRANCH}/lbrycrd-${TARGET}.zip" - name: "${TRAVIS_BRANCH}" - skip_cleanup: true - target_commitish: $TRAVIS_COMMIT - tag_name: $TRAVIS_TAG - on: - tags: true - api_key: - secure: "Ni5WZNR5CefWXpyDUQLMQbQ2LH4Iot+0SqIoM9c4maW06al1M8vu57vWuj2cESsW7JsaBehCE45Cwmo5kWyEjAiZY8sIMmvixkMP/8uPWuLgNmnIbm7U+d0j652DmZshDYtt8EomqV2RhAx/rmBnzGkruLOw9WTp9ZdBN3WbTt/IpZ2gMgVbGWYGOx+uRw7/yGw8m4gShQheto/dycbyyR3XV2WP9wuLmNYkcQ6JumSoQdDWXcvVfbCwylGq2sLDKwhvfTr4iwYyYsWdmhfdEQl0WcIv5C8xgdiY2vzhi2LmLqFbS/fvKNC26Tfo4bOHFG/eOnvqc+yyEB8B/xqW9Gs+A0TUh/3N30vHYZGcpiDU35DwAN5bZ1+s+mr/ZrNzBJ5BgT8io3g0Ko8gykbDvFQVpg7kxFsqA1YCikEpG86lVGk6clTa5guJvAHse+DfnbWO1nfDxYQXW0md861m0txk8RpTC/TVNyH/lL/vsS7LB67EHhRdZY+O1+5sUGMdtvvhMoxJYCwQGpLkh43KRsKynkMUR94w2O9hc8cknXdV3wrndVz00XNdcur6y4D7HTll1tBrF68CA2yKUSY5hsjtPmdlN+DW8ou/rJiKOpQZ/Xzp69AQEheOFfDPItxQRYxWj0dMOk8eszf0wFvi1N7J/hT/IHnuX5ITfa/T4NE=" -- provider: s3 - access_key_id: AKIAICKFHNTR5RITASAQ - secret_access_key: - secure: Qfgs8vGnEUvgiZNP2S9zY8qHEzaDOceF/XTv32jRBOISWfTqOTE56DZbOp8WKHPAqn0dx04jKA1NfV9f06sXU1NVbiJ2VYISo6XAk0n3RBJL3/mhNxvut/zM2DHkFPljWTkWEColS0ZyA3m4eUyJvAw/i+mOBT/zDD/oIlS5Uo5l/x3LmF9fYBuei0ucwSQeNOr2wCMIl+pXrIU7B3lEzXh1asayW6A9y7DOqMLnrSQ7TLlSssbnhuhDVpFx0xxX/U2NPraotbGKdo3wwMbms/lluBe60I/LsDNp9/SZXMDXh2YLGUImr97octwpdzIMjF+kU7QAZJzM7grz8PU9+MQh2V5sn6Xsww2x4PdkmHGz/2FMzhrCrlPf5JCaPBH49G+w4/29HYmMrlimOOVx4qXCpQ/XtWWne/d6MF0qqT6JhdPuD9ohmTpxcHRkCe2fxUw6Yn3dj+/+YoCywAcwcBm5jLpAotmWoCmmcnm9rvB7bIuPPZAjJUZViCnyvwY4Tj3Fb+sOuK4b/O5D2+cuS+WgQRkN/RspYlXrXTIh8Efv/yhW5L9WdzG1OExJDw2hX5VTccRRgIKZxZp80U2eYqn2M07+1nU+ShX4kgiSon46k5cfacLgzLKWEyCxWSSTbsYcwRxvDEjtYy4wxAYx8+J3dgQPs/opDXoQTJMjud0= - bucket: build.lbry.io - upload-dir: lbrycrd - acl: public_read - local_dir: dist - skip_cleanup: true - on: - repo: lbryio/lbrycrd - all_branches: true + - provider: releases + file: lbrycrd-linux.zip + skip_cleanup: true + on: + tags: true + condition: "$TARGET = linux" + api_key: + secure: "ibN+PQg84f0tgJLV3KaHjkHmgFNOPqBLIrSU42moen22xxT2VIn0j7DkFaLLts1fs/+/gxmrvhOQ0vUFJqmflZ3kCeyedP/CVgZz7D7HRVK0cYUMJ2F9VWMZAFIX6A67OUlypqZqzKAKrZHx3HXky6Z8NBU23JgWqDm8PcrbbgMLvB2lvWVASjJVKreaL9BOxFOOOrAj6xAIm9ogTOnFVI/AhufNOKOTZaiprcbqMngwHeaILbwEJVqv5P2YUurC6Sq+QaH26tX00DtsYOW+n8AA3Fe48+L6rqa6Q8ru+dhPuR/Apr2+DTZ+npzY8leV3A7mYUeLo4JLaEH6n1TLVt65cX7nuesS7KsSKBSxs7q7bsqeapDcMskZz5JR4EK4S96CuHZEnn6+efpH8IrxWpbeO3EibJfyT8tMJKw7Zym5mPr+sz6xSlVMoBVcCm+7z9e7Zcqukdvdy8jM7sGP9qusqEhpojh0o+gPgr9p13SfR+6OCpj9gwxPCnZO8RBfh1cbz9vFSVlDyUYcpI2CCCpPazA1glTsEDk+VtznnUMmWksXWfxBFV81jQB2SnoZKlnsiEuNMwhiMCMEkRFo74+AsUr2UjmKJ5KC8ACwsn475PoLZBh2J6fyXBHMdbrGfK+Zt5K2IHRRtDaZVT4eHqYzxh8KhalsuBNxCo3FygI=" + - provider: releases + file: lbrycrd-osx.zip + skip_cleanup: true + on: + tags: true + condition: "$TARGET = osx" + api_key: + secure: "ibN+PQg84f0tgJLV3KaHjkHmgFNOPqBLIrSU42moen22xxT2VIn0j7DkFaLLts1fs/+/gxmrvhOQ0vUFJqmflZ3kCeyedP/CVgZz7D7HRVK0cYUMJ2F9VWMZAFIX6A67OUlypqZqzKAKrZHx3HXky6Z8NBU23JgWqDm8PcrbbgMLvB2lvWVASjJVKreaL9BOxFOOOrAj6xAIm9ogTOnFVI/AhufNOKOTZaiprcbqMngwHeaILbwEJVqv5P2YUurC6Sq+QaH26tX00DtsYOW+n8AA3Fe48+L6rqa6Q8ru+dhPuR/Apr2+DTZ+npzY8leV3A7mYUeLo4JLaEH6n1TLVt65cX7nuesS7KsSKBSxs7q7bsqeapDcMskZz5JR4EK4S96CuHZEnn6+efpH8IrxWpbeO3EibJfyT8tMJKw7Zym5mPr+sz6xSlVMoBVcCm+7z9e7Zcqukdvdy8jM7sGP9qusqEhpojh0o+gPgr9p13SfR+6OCpj9gwxPCnZO8RBfh1cbz9vFSVlDyUYcpI2CCCpPazA1glTsEDk+VtznnUMmWksXWfxBFV81jQB2SnoZKlnsiEuNMwhiMCMEkRFo74+AsUr2UjmKJ5KC8ACwsn475PoLZBh2J6fyXBHMdbrGfK+Zt5K2IHRRtDaZVT4eHqYzxh8KhalsuBNxCo3FygI=" + - provider: releases + file: lbrycrd-windows.zip + skip_cleanup: true + on: + tags: true + condition: "$TARGET = windows" + api_key: + secure: "ibN+PQg84f0tgJLV3KaHjkHmgFNOPqBLIrSU42moen22xxT2VIn0j7DkFaLLts1fs/+/gxmrvhOQ0vUFJqmflZ3kCeyedP/CVgZz7D7HRVK0cYUMJ2F9VWMZAFIX6A67OUlypqZqzKAKrZHx3HXky6Z8NBU23JgWqDm8PcrbbgMLvB2lvWVASjJVKreaL9BOxFOOOrAj6xAIm9ogTOnFVI/AhufNOKOTZaiprcbqMngwHeaILbwEJVqv5P2YUurC6Sq+QaH26tX00DtsYOW+n8AA3Fe48+L6rqa6Q8ru+dhPuR/Apr2+DTZ+npzY8leV3A7mYUeLo4JLaEH6n1TLVt65cX7nuesS7KsSKBSxs7q7bsqeapDcMskZz5JR4EK4S96CuHZEnn6+efpH8IrxWpbeO3EibJfyT8tMJKw7Zym5mPr+sz6xSlVMoBVcCm+7z9e7Zcqukdvdy8jM7sGP9qusqEhpojh0o+gPgr9p13SfR+6OCpj9gwxPCnZO8RBfh1cbz9vFSVlDyUYcpI2CCCpPazA1glTsEDk+VtznnUMmWksXWfxBFV81jQB2SnoZKlnsiEuNMwhiMCMEkRFo74+AsUr2UjmKJ5KC8ACwsn475PoLZBh2J6fyXBHMdbrGfK+Zt5K2IHRRtDaZVT4eHqYzxh8KhalsuBNxCo3FygI=" + diff --git a/CMakeLists.txt b/CMakeLists.txt index fa1258b08..ac283aec0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,11 +4,9 @@ project(lbrycrd_clion) # Do not use for full compile. This is for CLion syntax c set (CMAKE_CXX_STANDARD 98) # 03 is not supported by cmake, but this will soon be 11 (after upstream bitcoin merge) # I thought that setting the standard would disable the clang-tidy c++11 tips; nope. -if(EXISTS "build/boost") - set(BOOST_ROOT "build/boost" CACHE PATH "Boost library path") - set(Boost_NO_SYSTEM_PATHS on CACHE BOOL "Do not search system for Boost") -endif() -find_package(Boost REQUIRED COMPONENTS filesystem program_options thread chrono locale) +set(BOOST_ROOT "build/boost" CACHE PATH "Boost library path") +set(Boost_NO_SYSTEM_PATHS on CACHE BOOL "Do not search system for Boost") +find_package(Boost REQUIRED COMPONENTS filesystem program_options thread chrono) # locale coming shortly file(GLOB sources src/*.h src/*.cpp diff --git a/README.md b/README.md index 3aa30cb02..a9f8d06f7 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ LBRYcrd uses a blockchain similar to bitcoin's to implement an index and payment ## Installation -Latest binaries are available from https://github.com/lbryio/lbrycrd/releases. There is no installation procedure, the binaries will be run as-is. +Latest binaries are available from https://github.com/lbryio/lbrycrd/releases. There is no installation procedure, the binaries run as is. ## Usage @@ -18,13 +18,13 @@ the "--help" flag (e.g. `lbrycrd-cli --help`). Run `./lbrycrdd -server -daemon` to start lbrycrdd in the background. -Run `./lbrycrd-cli getinfo` to check for some basic information about your LBRYcrd node. +Run `./lbrycrd-cli getinfo` to check for some basic informations about your LBRYcrd node. 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` ### Data directory -Lbrycrdd will use the below default data directories: +Lbrycrdd will use the below default data directories Windows < Vista: C:\Documents and Settings\Username\Application Data\lbrycrd @@ -34,9 +34,9 @@ Mac: ~/Library/Application Support/lbrycrd Unix: ~/.lbrycrd -The data directory contains various things such as your default wallet (wallet.dat), debug logs (debug.log), and blockchain data. You can optionally create a configuration file lbrycrd.conf in the default data directory which will be used by default when running lbrycrdd. - -For a list of configuration parameters, run `./lbrycrdd --help`. Below is a sample lbrycrd.conf to enable JSON RPC server on lbrycrdd. +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. ```rpcuser=lbry rpcpassword=xyz123456790 @@ -55,10 +55,12 @@ If you encounter any errors, please check `doc/build-*.md` for further instructi Contributions to this project are welcome, encouraged, and compensated. For more details, see [lbry.io/faq/contributing](https://lbry.io/faq/contributing) -The codebase is in C++03. C++11 is currently not supported but we will be migrating to it in the near future. Recommended GCC version is 4.8 or greater. +The codebase is in C++03, C++11 is currently not supported but we will be migrating to it in the near future. Recommended GCC version is 4.8 or greater. We follow the same coding guidelines as documented by Bitcoin Core, see [here](/doc/developer-notes.md). To run an automated code formatting check, try: `git diff -U0 master -- '*.h' '*.cpp' | ./contrib/devtools/clang-format-diff.py -p1`. This will check any commits not on master for proper code formatting. -We try to avoid altering parts of the code that is inherited from Bitcoin Core unless absolutely necessary. This will make it easier to merge changes from Bitcoin Core. If commits are expected not to be merged upstream (i.e. we broke up a commit from Bitcoin Core in order to use a single feature in it), the commit message must contain the string "NOT FOR UPSTREAM MERGE". +We try to avoid altering parts of the code that is inherited from Bitcoin Core unless absolutely necessary. This will make it easier to merge changes from +Bitcoin Core. If commits are expected not to be merged upstream (i.e. we broke up a commit from Bitcoin Core in order to use a single feature in it), the commit +message must contain the string "NOT FOR UPSTREAM MERGE". The `master` branch is regularly built and tested, but is not guaranteed to be completely stable. [Releases](https://github.com/lbryio/lbrycrd/releases) are created @@ -75,7 +77,7 @@ The Travis CI system makes sure that every pull request is built, and that unit ### Testnet -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 kay@lbry.io or grin@lbry.io. +Testnet is maintained for testing purposes and can be accessed using the command `./lbrycrdd -testnet`. If you would like testnet credits, please contact kay@lbry.io or grin@lbry.io. ## License diff --git a/configure.ac b/configure.ac index d19f0eb32..7445545d5 100644 --- a/configure.ac +++ b/configure.ac @@ -2,8 +2,8 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 12) -define(_CLIENT_VERSION_REVISION, 3) -define(_CLIENT_VERSION_BUILD, 1) +define(_CLIENT_VERSION_REVISION, 2) +define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2016) define(_COPYRIGHT_HOLDERS,[The %s developers]) diff --git a/contrib/devtools/clang-format-diff.py b/contrib/devtools/clang-format-diff.py index b0dd9f59a..13d2573b9 100755 --- a/contrib/devtools/clang-format-diff.py +++ b/contrib/devtools/clang-format-diff.py @@ -144,8 +144,7 @@ def main(): command.extend(lines) command.extend(['-style=file', '-fallback-style=none']) p = subprocess.Popen(command, stdout=subprocess.PIPE, - stderr=None, - stdin=subprocess.PIPE) + stderr=None, stdin=subprocess.PIPE) stdout, stderr = p.communicate() if p.returncode != 0: sys.exit(p.returncode); diff --git a/reproducible_build.sh b/reproducible_build.sh index 2a929902f..4bd67a034 100755 --- a/reproducible_build.sh +++ b/reproducible_build.sh @@ -237,7 +237,7 @@ function install_apt_packages() { if [ "${CHECK_CODE_FORMAT}" = true ]; then $SUDO apt-get ${QUIET} install -y --no-install-recommends \ - clang-format-3.9 + clang-format-3.4 fi } @@ -327,7 +327,6 @@ function build_libevent() { } function build_dependency() { - pushd . PREFIX=$1 LOG=$2 BUILD=$3 @@ -338,7 +337,6 @@ function build_dependency() { "${BUILD}" "${LOG}" trap - INT TERM EXIT fi - popd } function build_lbrycrd() { @@ -372,7 +370,11 @@ function build_lbrycrd() { function clang_format_diff(){ # run a code formatting check on any commits not in master # requires clang-format - git diff -U0 origin/master -- '*.h' '*.cpp' | ./contrib/devtools/clang-format-diff.py -p1 + if ! git config remote.origin2.url > /dev/null; then + git remote add origin2 https://github.com/lbryio/lbrycrd.git + fi + git fetch origin2 + git diff -U0 origin2/master -- '*.h' '*.cpp' | ./contrib/devtools/clang-format-diff.py -p1 } # these variables are needed in both functions diff --git a/src/Makefile.am b/src/Makefile.am index a9f0a949c..0352c3df7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -119,6 +119,7 @@ BITCOIN_CORE_H = \ miner.h \ nameclaim.h \ claimtrie.h \ + claimtriedb.h \ lbry.h \ net.h \ netbase.h \ @@ -191,6 +192,7 @@ libbitcoin_server_a_SOURCES = \ merkleblock.cpp \ miner.cpp \ claimtrie.cpp \ + claimtriedb.cpp \ net.cpp \ noui.cpp \ policy/fees.cpp \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 05f88b3ea..4baf40724 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -62,6 +62,7 @@ BITCOIN_TESTS =\ test/multisig_tests.cpp \ test/claimtriecache_tests.cpp \ test/claimtriebranching_tests.cpp \ + test/claimtriedb_tests.cpp \ test/nameclaim_tests.cpp \ test/netbase_tests.cpp \ test/pmt_tests.cpp \ diff --git a/src/claimtrie.cpp b/src/claimtrie.cpp index f4b1ccd98..79e429108 100644 --- a/src/claimtrie.cpp +++ b/src/claimtrie.cpp @@ -2,9 +2,13 @@ #include "coins.h" #include "hash.h" -#include -#include #include +#include + +#define HASH_BLOCK 'h' +#define CURRENT_HEIGHT 't' + +const uint256 one = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); std::vector heightToVch(int n) { @@ -21,7 +25,7 @@ std::vector heightToVch(int n) return vchHeight; } -uint256 getValueHash(COutPoint outPoint, int nHeightOfLastTakeover) +uint256 getValueHash(const COutPoint& outPoint, int nHeightOfLastTakeover) { CHash256 txHasher; txHasher.Write(outPoint.hash.begin(), outPoint.hash.size()); @@ -32,7 +36,7 @@ uint256 getValueHash(COutPoint outPoint, int nHeightOfLastTakeover) std::stringstream ss; ss << outPoint.n; std::string snOut = ss.str(); - nOutHasher.Write((unsigned char*) snOut.data(), snOut.size()); + nOutHasher.Write((unsigned char*)snOut.data(), snOut.size()); std::vector vchnOutHash(nOutHasher.OUTPUT_SIZE); nOutHasher.Finalize(&(vchnOutHash[0])); @@ -53,7 +57,7 @@ uint256 getValueHash(COutPoint outPoint, int nHeightOfLastTakeover) return valueHash; } -bool CClaimTrieNode::insertClaim(CClaimValue claim) +bool CClaimTrieNode::insertClaim(const CClaimValue& claim) { LogPrintf("%s: Inserting %s:%d (amount: %d) into the claim trie\n", __func__, claim.outPoint.hash.ToString(), claim.outPoint.n, claim.nAmount); claims.push_back(claim); @@ -65,24 +69,18 @@ bool CClaimTrieNode::removeClaim(const COutPoint& outPoint, CClaimValue& claim) LogPrintf("%s: Removing txid: %s, nOut: %d from the claim trie\n", __func__, outPoint.hash.ToString(), outPoint.n); std::vector::iterator itClaims; - for (itClaims = claims.begin(); itClaims != claims.end(); ++itClaims) - { - if (itClaims->outPoint == outPoint) - { + for (itClaims = claims.begin(); itClaims != claims.end(); ++itClaims) { + if (itClaims->outPoint == outPoint) { std::swap(claim, *itClaims); break; } } - if (itClaims != claims.end()) - { + if (itClaims != claims.end()) { claims.erase(itClaims); - } - else - { + } else { LogPrintf("CClaimTrieNode::%s() : asked to remove a claim that doesn't exist\n", __func__); LogPrintf("CClaimTrieNode::%s() : claims that do exist:\n", __func__); - for (unsigned int i = 0; i < claims.size(); i++) - { + for (unsigned int i = 0; i < claims.size(); i++) { LogPrintf("\ttxhash: %s, nOut: %d:\n", claims[i].outPoint.hash.ToString(), claims[i].outPoint.n); } return false; @@ -92,12 +90,9 @@ bool CClaimTrieNode::removeClaim(const COutPoint& outPoint, CClaimValue& claim) bool CClaimTrieNode::getBestClaim(CClaimValue& claim) const { - if (claims.empty()) - { + if (claims.empty()) { return false; - } - else - { + } else { claim = claims.front(); return true; } @@ -105,10 +100,8 @@ bool CClaimTrieNode::getBestClaim(CClaimValue& claim) const bool CClaimTrieNode::haveClaim(const COutPoint& outPoint) const { - for (std::vector::const_iterator itclaim = claims.begin(); itclaim != claims.end(); ++itclaim) - { - if (itclaim->outPoint == outPoint) - return true; + for (std::vector::const_iterator itclaim = claims.begin(); itclaim != claims.end(); ++itclaim) { + if (itclaim->outPoint == outPoint) return true; } return false; } @@ -117,17 +110,13 @@ void CClaimTrieNode::reorderClaims(supportMapEntryType& supports) { std::vector::iterator itclaim; - for (itclaim = claims.begin(); itclaim != claims.end(); ++itclaim) - { + for (itclaim = claims.begin(); itclaim != claims.end(); ++itclaim) { itclaim->nEffectiveAmount = itclaim->nAmount; } - for (supportMapEntryType::iterator itsupport = supports.begin(); itsupport != supports.end(); ++itsupport) - { - for (itclaim = claims.begin(); itclaim != claims.end(); ++itclaim) - { - if (itsupport->supportedClaimId == itclaim->claimId) - { + for (supportMapEntryType::iterator itsupport = supports.begin(); itsupport != supports.end(); ++itsupport) { + for (itclaim = claims.begin(); itclaim != claims.end(); ++itclaim) { + if (itsupport->supportedClaimId == itclaim->claimId) { itclaim->nEffectiveAmount += itsupport->nAmount; break; } @@ -137,6 +126,20 @@ void CClaimTrieNode::reorderClaims(supportMapEntryType& supports) std::make_heap(claims.begin(), claims.end()); } +bool CClaimTrieNode::empty() const +{ + return children.empty() && claims.empty(); +} + +CClaimTrie::CClaimTrie(bool fMemory, bool fWipe, int nProportionalDelayFactor) + : nCurrentHeight(0), nExpirationTime(Params().GetConsensus().nOriginalClaimExpirationTime), nProportionalDelayFactor(nProportionalDelayFactor), db(fMemory, fWipe), root(one) +{ +} + +CClaimTrie::~CClaimTrie() +{ +} + uint256 CClaimTrie::getMerkleHash() { return root.hash; @@ -147,72 +150,24 @@ bool CClaimTrie::empty() const return root.empty(); } -template bool CClaimTrie::keyTypeEmpty(char keyType, K& dummy) const -{ - boost::scoped_ptr pcursor(const_cast(&db)->NewIterator()); - pcursor->SeekToFirst(); - - while (pcursor->Valid()) - { - std::pair key; - if (pcursor->GetKey(key)) - { - if (key.first == keyType) - { - return false; - } - } - else - { - break; - } - pcursor->Next(); - } - return true; -} - bool CClaimTrie::queueEmpty() const { - for (claimQueueType::const_iterator itRow = dirtyQueueRows.begin(); itRow != dirtyQueueRows.end(); ++itRow) - { - if (!itRow->second.empty()) - return false; - } - int dummy; - return keyTypeEmpty(CLAIM_QUEUE_ROW, dummy); + return db.keyTypeEmpty(); } bool CClaimTrie::expirationQueueEmpty() const { - for (expirationQueueType::const_iterator itRow = dirtyExpirationQueueRows.begin(); itRow != dirtyExpirationQueueRows.end(); ++itRow) - { - if (!itRow->second.empty()) - return false; - } - int dummy; - return keyTypeEmpty(EXP_QUEUE_ROW, dummy); + return db.keyTypeEmpty(); } bool CClaimTrie::supportEmpty() const { - for (supportMapType::const_iterator itNode = dirtySupportNodes.begin(); itNode != dirtySupportNodes.end(); ++itNode) - { - if (!itNode->second.empty()) - return false; - } - std::string dummy; - return keyTypeEmpty(SUPPORT, dummy); + return db.keyTypeEmpty(); } bool CClaimTrie::supportQueueEmpty() const { - for (supportQueueType::const_iterator itRow = dirtySupportQueueRows.begin(); itRow != dirtySupportQueueRows.end(); ++itRow) - { - if (!itRow->second.empty()) - return false; - } - int dummy; - return keyTypeEmpty(SUPPORT_QUEUE_ROW, dummy); + return db.keyTypeEmpty(); } void CClaimTrie::setExpirationTime(int t) @@ -228,37 +183,25 @@ void CClaimTrie::clear() void CClaimTrie::clear(CClaimTrieNode* current) { - for (nodeMapType::const_iterator itchildren = current->children.begin(); itchildren != current->children.end(); ++itchildren) - { + for (nodeMapType::const_iterator itchildren = current->children.begin(); itchildren != current->children.end(); ++itchildren) { clear(itchildren->second); delete itchildren->second; } + current->children.clear(); } bool CClaimTrie::haveClaim(const std::string& name, const COutPoint& outPoint) const { - const CClaimTrieNode* current = &root; - for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname) - { - nodeMapType::const_iterator itchildren = current->children.find(*itname); - if (itchildren == current->children.end()) - return false; - current = itchildren->second; - } - return current->haveClaim(outPoint); + const CClaimTrieNode* current = getNodeForName(name); + return current && current->haveClaim(outPoint); } bool CClaimTrie::haveSupport(const std::string& name, const COutPoint& outPoint) const { supportMapEntryType node; - if (!getSupportNode(name, node)) - { - return false; - } - for (supportMapEntryType::const_iterator itnode = node.begin(); itnode != node.end(); ++itnode) - { - if (itnode->outPoint == outPoint) - return true; + if (!db.getQueueRow(name, node)) return false; + for (supportMapEntryType::const_iterator itnode = node.begin(); itnode != node.end(); ++itnode) { + if (itnode->outPoint == outPoint) return true; } return false; } @@ -266,32 +209,20 @@ bool CClaimTrie::haveSupport(const std::string& name, const COutPoint& outPoint) bool CClaimTrie::haveClaimInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const { queueNameRowType nameRow; - if (!getQueueNameRow(name, nameRow)) - { - return false; - } + if (!db.getQueueRow(name, nameRow)) return false; queueNameRowType::const_iterator itNameRow; - for (itNameRow = nameRow.begin(); itNameRow != nameRow.end(); ++itNameRow) - { - if (itNameRow->outPoint == outPoint) - { + for (itNameRow = nameRow.begin(); itNameRow != nameRow.end(); ++itNameRow) { + if (itNameRow->outPoint == outPoint) { nValidAtHeight = itNameRow->nHeight; break; } } - if (itNameRow == nameRow.end()) - { - return false; - } + if (itNameRow == nameRow.end()) return false; claimQueueRowType row; - if (getQueueRow(nValidAtHeight, row)) - { - for (claimQueueRowType::const_iterator itRow = row.begin(); itRow != row.end(); ++itRow) - { - if (itRow->first == name && itRow->second.outPoint == outPoint) - { - if (itRow->second.nValidAtHeight != nValidAtHeight) - { + if (db.getQueueRow(nValidAtHeight, row)) { + for (claimQueueRowType::const_iterator itRow = row.begin(); itRow != row.end(); ++itRow) { + if (itRow->first == name && itRow->second.outPoint == outPoint) { + if (itRow->second.nValidAtHeight != nValidAtHeight) { LogPrintf("%s: An inconsistency was found in the claim queue. Please report this to the developers:\nDifferent nValidAtHeight between named queue and height queue\n: name: %s, txid: %s, nOut: %d, nValidAtHeight in named queue: %d, nValidAtHeight in height queue: %d current height: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nValidAtHeight, itRow->second.nValidAtHeight, nCurrentHeight); } return true; @@ -304,33 +235,21 @@ bool CClaimTrie::haveClaimInQueue(const std::string& name, const COutPoint& outP bool CClaimTrie::haveSupportInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const { - queueNameRowType nameRow; - if (!getSupportQueueNameRow(name, nameRow)) - { - return false; - } - queueNameRowType::const_iterator itNameRow; - for (itNameRow = nameRow.begin(); itNameRow != nameRow.end(); ++itNameRow) - { - if (itNameRow->outPoint == outPoint) - { + supportQueueNameRowType nameRow; + if (!db.getQueueRow(name, nameRow)) return false; + supportQueueNameRowType::const_iterator itNameRow; + for (itNameRow = nameRow.begin(); itNameRow != nameRow.end(); ++itNameRow) { + if (itNameRow->outPoint == outPoint) { nValidAtHeight = itNameRow->nHeight; break; } } - if (itNameRow == nameRow.end()) - { - return false; - } + if (itNameRow == nameRow.end()) return false; supportQueueRowType row; - if (getSupportQueueRow(nValidAtHeight, row)) - { - for (supportQueueRowType::const_iterator itRow = row.begin(); itRow != row.end(); ++itRow) - { - if (itRow->first == name && itRow->second.outPoint == outPoint) - { - if (itRow->second.nValidAtHeight != nValidAtHeight) - { + if (db.getQueueRow(nValidAtHeight, row)) { + for (supportQueueRowType::const_iterator itRow = row.begin(); itRow != row.end(); ++itRow) { + if (itRow->first == name && itRow->second.outPoint == outPoint) { + if (itRow->second.nValidAtHeight != nValidAtHeight) { LogPrintf("%s: An inconsistency was found in the support queue. Please report this to the developers:\nDifferent nValidAtHeight between named queue and height queue\n: name: %s, txid: %s, nOut: %d, nValidAtHeight in named queue: %d, nValidAtHeight in height queue: %d current height: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nValidAtHeight, itRow->second.nValidAtHeight, nCurrentHeight); } return true; @@ -343,8 +262,7 @@ bool CClaimTrie::haveSupportInQueue(const std::string& name, const COutPoint& ou unsigned int CClaimTrie::getTotalNamesInTrie() const { - if (empty()) - return 0; + if (empty()) return 0; const CClaimTrieNode* current = &root; return getTotalNamesRecursive(current); } @@ -352,10 +270,10 @@ unsigned int CClaimTrie::getTotalNamesInTrie() const unsigned int CClaimTrie::getTotalNamesRecursive(const CClaimTrieNode* current) const { unsigned int names_in_subtrie = 0; - if (!(current->claims.empty())) + if (!(current->claims.empty())) { names_in_subtrie += 1; - for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) - { + } + for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) { names_in_subtrie += getTotalNamesRecursive(it->second); } return names_in_subtrie; @@ -363,8 +281,7 @@ unsigned int CClaimTrie::getTotalNamesRecursive(const CClaimTrieNode* current) c unsigned int CClaimTrie::getTotalClaimsInTrie() const { - if (empty()) - return 0; + if (empty()) return 0; const CClaimTrieNode* current = &root; return getTotalClaimsRecursive(current); } @@ -372,8 +289,7 @@ unsigned int CClaimTrie::getTotalClaimsInTrie() const unsigned int CClaimTrie::getTotalClaimsRecursive(const CClaimTrieNode* current) const { unsigned int claims_in_subtrie = current->claims.size(); - for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) - { + for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) { claims_in_subtrie += getTotalClaimsRecursive(it->second); } return claims_in_subtrie; @@ -381,8 +297,7 @@ unsigned int CClaimTrie::getTotalClaimsRecursive(const CClaimTrieNode* current) CAmount CClaimTrie::getTotalValueOfClaimsInTrie(bool fControllingOnly) const { - if (empty()) - return 0; + if (empty()) return 0; const CClaimTrieNode* current = &root; return getTotalValueOfClaimsRecursive(current, fControllingOnly); } @@ -390,27 +305,42 @@ CAmount CClaimTrie::getTotalValueOfClaimsInTrie(bool fControllingOnly) const CAmount CClaimTrie::getTotalValueOfClaimsRecursive(const CClaimTrieNode* current, bool fControllingOnly) const { CAmount value_in_subtrie = 0; - for (std::vector::const_iterator itclaim = current->claims.begin(); itclaim != current->claims.end(); ++itclaim) - { + for (std::vector::const_iterator itclaim = current->claims.begin(); itclaim != current->claims.end(); ++itclaim) { value_in_subtrie += itclaim->nAmount; - if (fControllingOnly) - break; + if (fControllingOnly) break; } - for (nodeMapType::const_iterator itchild = current->children.begin(); itchild != current->children.end(); ++itchild) - { - value_in_subtrie += getTotalValueOfClaimsRecursive(itchild->second, fControllingOnly); - } - return value_in_subtrie; + for (nodeMapType::const_iterator itchild = current->children.begin(); itchild != current->children.end(); ++itchild) { + value_in_subtrie += getTotalValueOfClaimsRecursive(itchild->second, fControllingOnly); + } + return value_in_subtrie; +} + +bool CClaimTrie::recursiveFlattenTrie(const std::string& name, const CClaimTrieNode* current, std::vector& nodes) const +{ + nodes.push_back(namedNodeType(name, *current)); + for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) { + std::stringstream ss; + ss << name << it->first; + if (!recursiveFlattenTrie(ss.str(), it->second, nodes)) return false; + } + return true; +} + +std::vector CClaimTrie::flattenTrie() const +{ + std::vector nodes; + if (!recursiveFlattenTrie("", &root, nodes)) { + LogPrintf("%s: Something went wrong flattening the trie", __func__); + } + return nodes; } const CClaimTrieNode* CClaimTrie::getNodeForName(const std::string& name) const { const CClaimTrieNode* current = &root; - for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname) - { + for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname) { nodeMapType::const_iterator itchildren = current->children.find(*itname); - if (itchildren == current->children.end()) - return NULL; + if (itchildren == current->children.end()) return NULL; current = itchildren->second; } return current; @@ -419,22 +349,18 @@ const CClaimTrieNode* CClaimTrie::getNodeForName(const std::string& name) const bool CClaimTrie::getInfoForName(const std::string& name, CClaimValue& claim) const { const CClaimTrieNode* current = getNodeForName(name); - if (current) - { - return current->getBestClaim(claim); - } - return false; + return current && current->getBestClaim(claim); } bool CClaimTrie::getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const { const CClaimTrieNode* current = getNodeForName(name); - if (current && !current->claims.empty()) - { + if (current && !current->claims.empty()) { lastTakeoverHeight = current->nHeightOfLastTakeover; return true; + } else { + return false; } - return false; } claimsForNameType CClaimTrie::getClaimsForName(const std::string& name) const @@ -443,56 +369,41 @@ claimsForNameType CClaimTrie::getClaimsForName(const std::string& name) const std::vector supports; int nLastTakeoverHeight = 0; const CClaimTrieNode* current = getNodeForName(name); - if (current) - { - if (!current->claims.empty()) - { + if (current) { + if (!current->claims.empty()) { nLastTakeoverHeight = current->nHeightOfLastTakeover; } - for (std::vector::const_iterator itClaims = current->claims.begin(); itClaims != current->claims.end(); ++itClaims) - { + for (std::vector::const_iterator itClaims = current->claims.begin(); itClaims != current->claims.end(); ++itClaims) { claims.push_back(*itClaims); } } supportMapEntryType supportNode; - if (getSupportNode(name, supportNode)) - { - for (std::vector::const_iterator itSupports = supportNode.begin(); itSupports != supportNode.end(); ++itSupports) - { + if (db.getQueueRow(name, supportNode)) { + for (std::vector::const_iterator itSupports = supportNode.begin(); itSupports != supportNode.end(); ++itSupports) { supports.push_back(*itSupports); } } queueNameRowType namedClaimRow; - if (getQueueNameRow(name, namedClaimRow)) - { - for (queueNameRowType::const_iterator itClaimsForName = namedClaimRow.begin(); itClaimsForName != namedClaimRow.end(); ++itClaimsForName) - { + if (db.getQueueRow(name, namedClaimRow)) { + for (queueNameRowType::const_iterator itClaimsForName = namedClaimRow.begin(); itClaimsForName != namedClaimRow.end(); ++itClaimsForName) { claimQueueRowType claimRow; - if (getQueueRow(itClaimsForName->nHeight, claimRow)) - { - for (claimQueueRowType::const_iterator itClaimRow = claimRow.begin(); itClaimRow != claimRow.end(); ++itClaimRow) - { - if (itClaimRow->first == name && itClaimRow->second.outPoint == itClaimsForName->outPoint) - { - claims.push_back(itClaimRow->second); - break; - } - } + if (db.getQueueRow(itClaimsForName->nHeight, claimRow)) { + for (claimQueueRowType::const_iterator itClaimRow = claimRow.begin(); itClaimRow != claimRow.end(); ++itClaimRow) { + if (itClaimRow->first == name && itClaimRow->second.outPoint == itClaimsForName->outPoint) { + claims.push_back(itClaimRow->second); + break; + } + } } } } - queueNameRowType namedSupportRow; - if (getSupportQueueNameRow(name, namedSupportRow)) - { - for (queueNameRowType::const_iterator itSupportsForName = namedSupportRow.begin(); itSupportsForName != namedSupportRow.end(); ++itSupportsForName) - { + supportQueueNameRowType namedSupportRow; + if (db.getQueueRow(name, namedSupportRow)) { + for (supportQueueNameRowType::const_iterator itSupportsForName = namedSupportRow.begin(); itSupportsForName != namedSupportRow.end(); ++itSupportsForName) { supportQueueRowType supportRow; - if (getSupportQueueRow(itSupportsForName->nHeight, supportRow)) - { - for (supportQueueRowType::const_iterator itSupportRow = supportRow.begin(); itSupportRow != supportRow.end(); ++itSupportRow) - { - if (itSupportRow->first == name && itSupportRow->second.outPoint == itSupportsForName->outPoint) - { + if (db.getQueueRow(itSupportsForName->nHeight, supportRow)) { + for (supportQueueRowType::const_iterator itSupportRow = supportRow.begin(); itSupportRow != supportRow.end(); ++itSupportRow) { + if (itSupportRow->first == name && itSupportRow->second.outPoint == itSupportsForName->outPoint) { supports.push_back(itSupportRow->second); break; } @@ -505,33 +416,38 @@ claimsForNameType CClaimTrie::getClaimsForName(const std::string& name) const } //return effective amount from claim, retuns 0 if claim is not found -CAmount CClaimTrie::getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector* supports) const +CAmount CClaimTrie::getEffectiveAmountForClaim(const std::string& name, const uint160& claimId) const { - return getEffectiveAmountForClaim(getClaimsForName(name), claimId, supports); + std::vector supports; + return getEffectiveAmountForClaimWithSupports(name, claimId, supports); } -CAmount CClaimTrie::getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector* supports) const +//return effective amount from claim and the supports used as inputs, retuns 0 if claim is not found +CAmount CClaimTrie::getEffectiveAmountForClaimWithSupports(const std::string& name, const uint160& claimId, std::vector& supports) const { + claimsForNameType claims = getClaimsForName(name); CAmount effectiveAmount = 0; - for (std::vector::const_iterator it = claims.claims.begin(); it != claims.claims.end(); ++it) { + bool claim_found = false; + for (std::vector::iterator it = claims.claims.begin(); it != claims.claims.end(); ++it) { if (it->claimId == claimId && it->nValidAtHeight < nCurrentHeight) { effectiveAmount += it->nAmount; - for (std::vector::const_iterator it = claims.supports.begin(); it != claims.supports.end(); ++it) { - if (it->supportedClaimId == claimId && it->nValidAtHeight < nCurrentHeight) { - effectiveAmount += it->nAmount; - if (supports) supports->push_back(*it); - } - } + claim_found = true; break; } } + if (!claim_found) return effectiveAmount; + for (std::vector::iterator it = claims.supports.begin(); it != claims.supports.end(); ++it) { + if (it->supportedClaimId == claimId && it->nValidAtHeight < nCurrentHeight) { + effectiveAmount += it->nAmount; + supports.push_back(*it); + } + } return effectiveAmount; } bool CClaimTrie::checkConsistency() const { - if (empty()) - return true; + if (empty()) return true; return recursiveCheckConsistency(&root); } @@ -539,22 +455,19 @@ bool CClaimTrie::recursiveCheckConsistency(const CClaimTrieNode* node) const { std::vector vchToHash; - for (nodeMapType::const_iterator it = node->children.begin(); it != node->children.end(); ++it) - { - if (recursiveCheckConsistency(it->second)) - { + for (nodeMapType::const_iterator it = node->children.begin(); it != node->children.end(); ++it) { + if (recursiveCheckConsistency(it->second)) { vchToHash.push_back(it->first); vchToHash.insert(vchToHash.end(), it->second->hash.begin(), it->second->hash.end()); - } - else + } else { return false; + } } CClaimValue claim; bool hasClaim = node->getBestClaim(claim); - if (hasClaim) - { + if (hasClaim) { uint256 valueHash = getValueHash(claim.outPoint, node->nHeightOfLastTakeover); vchToHash.insert(vchToHash.end(), valueHash.begin(), valueHash.end()); } @@ -569,317 +482,76 @@ bool CClaimTrie::recursiveCheckConsistency(const CClaimTrieNode* node) const void CClaimTrie::addToClaimIndex(const std::string& name, const CClaimValue& claim) { - CClaimIndexElement element = { name, claim }; LogPrintf("%s: ClaimIndex[%s] updated %s\n", __func__, claim.claimId.GetHex(), name); - db.Write(std::make_pair(CLAIM_BY_ID, claim.claimId), element); + + CClaimIndexElement element = {name, claim}; + db.updateQueueRow(claim.claimId, element); } void CClaimTrie::removeFromClaimIndex(const CClaimValue& claim) { LogPrintf("%s: ClaimIndex[%s] removed\n", __func__, claim.claimId.GetHex()); - db.Erase(std::make_pair(CLAIM_BY_ID, claim.claimId)); + + CClaimIndexElement element; + db.updateQueueRow(claim.claimId, element); } -bool CClaimTrie::getClaimById(const uint160 claimId, std::string& name, CClaimValue& claim) const +bool CClaimTrie::getClaimById(const uint160& claimId, std::string& name, CClaimValue& claim) const { CClaimIndexElement element; - if (db.Read(std::make_pair(CLAIM_BY_ID, claimId), element)) - { - if (element.claim.claimId == claimId) { - name = element.name; - claim = element.claim; - return true; - } else { - LogPrintf("%s: ClaimIndex[%s] returned unmatched claimId %s when looking for %s\n", - __func__, claimId.GetHex(), element.claim.claimId.GetHex(), name); - } - } - return false; -} - -bool CClaimTrie::getQueueRow(int nHeight, claimQueueRowType& row) const -{ - claimQueueType::const_iterator itQueueRow = dirtyQueueRows.find(nHeight); - if (itQueueRow != dirtyQueueRows.end()) - { - row = itQueueRow->second; + if (db.getQueueRow(claimId, element) && !element.empty()) { + name = element.name; + claim = element.claim; return true; + } else { + LogPrintf("%s: ClaimIndex[%s] returned unmatched claimId %s when looking for %s\n", + __func__, claimId.GetHex(), element.claim.claimId.GetHex(), name); + return false; } - return db.Read(std::make_pair(CLAIM_QUEUE_ROW, nHeight), row); } -bool CClaimTrie::getQueueNameRow(const std::string& name, queueNameRowType& row) const -{ - queueNameType::const_iterator itQueueNameRow = dirtyQueueNameRows.find(name); - if (itQueueNameRow != dirtyQueueNameRows.end()) - { - row = itQueueNameRow->second; - return true; - } - return db.Read(std::make_pair(CLAIM_QUEUE_NAME_ROW, name), row); -} - -bool CClaimTrie::getExpirationQueueRow(int nHeight, expirationQueueRowType& row) const -{ - expirationQueueType::const_iterator itQueueRow = dirtyExpirationQueueRows.find(nHeight); - if (itQueueRow != dirtyExpirationQueueRows.end()) - { - row = itQueueRow->second; - return true; - } - return db.Read(std::make_pair(EXP_QUEUE_ROW, nHeight), row); -} - -void CClaimTrie::updateQueueRow(int nHeight, claimQueueRowType& row) -{ - claimQueueType::iterator itQueueRow = dirtyQueueRows.find(nHeight); - if (itQueueRow == dirtyQueueRows.end()) - { - claimQueueRowType newRow; - std::pair ret; - ret = dirtyQueueRows.insert(std::pair(nHeight, newRow)); - assert(ret.second); - itQueueRow = ret.first; - } - itQueueRow->second.swap(row); -} - -void CClaimTrie::updateQueueNameRow(const std::string& name, queueNameRowType& row) -{ - queueNameType::iterator itQueueRow = dirtyQueueNameRows.find(name); - if (itQueueRow == dirtyQueueNameRows.end()) - { - queueNameRowType newRow; - std::pair ret; - ret = dirtyQueueNameRows.insert(std::pair(name, newRow)); - assert(ret.second); - itQueueRow = ret.first; - } - itQueueRow->second.swap(row); -} - -void CClaimTrie::updateExpirationRow(int nHeight, expirationQueueRowType& row) -{ - expirationQueueType::iterator itQueueRow = dirtyExpirationQueueRows.find(nHeight); - if (itQueueRow == dirtyExpirationQueueRows.end()) - { - expirationQueueRowType newRow; - std::pair ret; - ret = dirtyExpirationQueueRows.insert(std::pair(nHeight, newRow)); - assert(ret.second); - itQueueRow = ret.first; - } - itQueueRow->second.swap(row); -} - -void CClaimTrie::updateSupportMap(const std::string& name, supportMapEntryType& node) -{ - supportMapType::iterator itNode = dirtySupportNodes.find(name); - if (itNode == dirtySupportNodes.end()) - { - supportMapEntryType newNode; - std::pair ret; - ret = dirtySupportNodes.insert(std::pair(name, newNode)); - assert(ret.second); - itNode = ret.first; - } - itNode->second.swap(node); -} - -void CClaimTrie::updateSupportQueue(int nHeight, supportQueueRowType& row) -{ - supportQueueType::iterator itQueueRow = dirtySupportQueueRows.find(nHeight); - if (itQueueRow == dirtySupportQueueRows.end()) - { - supportQueueRowType newRow; - std::pair ret; - ret = dirtySupportQueueRows.insert(std::pair(nHeight, newRow)); - assert(ret.second); - itQueueRow = ret.first; - } - itQueueRow->second.swap(row); -} - -void CClaimTrie::updateSupportNameQueue(const std::string& name, queueNameRowType& row) -{ - queueNameType::iterator itQueueRow = dirtySupportQueueNameRows.find(name); - if (itQueueRow == dirtySupportQueueNameRows.end()) - { - queueNameRowType newRow; - std::pair ret; - ret = dirtySupportQueueNameRows.insert(std::pair(name, newRow)); - assert(ret.second); - itQueueRow = ret.first; - } - itQueueRow->second.swap(row); -} - -void CClaimTrie::updateSupportExpirationQueue(int nHeight, expirationQueueRowType& row) -{ - expirationQueueType::iterator itQueueRow = dirtySupportExpirationQueueRows.find(nHeight); - if (itQueueRow == dirtySupportExpirationQueueRows.end()) - { - expirationQueueRowType newRow; - std::pair ret; - ret = dirtySupportExpirationQueueRows.insert(std::pair(nHeight, newRow)); - assert(ret.second); - itQueueRow = ret.first; - } - itQueueRow->second.swap(row); -} - -bool CClaimTrie::getSupportNode(std::string name, supportMapEntryType& node) const -{ - supportMapType::const_iterator itNode = dirtySupportNodes.find(name); - if (itNode != dirtySupportNodes.end()) - { - node = itNode->second; - return true; - } - return db.Read(std::make_pair(SUPPORT, name), node); -} - -bool CClaimTrie::getSupportQueueRow(int nHeight, supportQueueRowType& row) const -{ - supportQueueType::const_iterator itQueueRow = dirtySupportQueueRows.find(nHeight); - if (itQueueRow != dirtySupportQueueRows.end()) - { - row = itQueueRow->second; - return true; - } - return db.Read(std::make_pair(SUPPORT_QUEUE_ROW, nHeight), row); -} - -bool CClaimTrie::getSupportQueueNameRow(const std::string& name, queueNameRowType& row) const -{ - queueNameType::const_iterator itQueueNameRow = dirtySupportQueueNameRows.find(name); - if (itQueueNameRow != dirtySupportQueueNameRows.end()) - { - row = itQueueNameRow->second; - return true; - } - return db.Read(std::make_pair(SUPPORT_QUEUE_NAME_ROW, name), row); -} - -bool CClaimTrie::getSupportExpirationQueueRow(int nHeight, expirationQueueRowType& row) const -{ - expirationQueueType::const_iterator itQueueRow = dirtySupportExpirationQueueRows.find(nHeight); - if (itQueueRow != dirtySupportExpirationQueueRows.end()) - { - row = itQueueRow->second; - return true; - } - return db.Read(std::make_pair(SUPPORT_EXP_QUEUE_ROW, nHeight), row); -} - -bool CClaimTrie::update(nodeCacheType& cache, hashMapType& hashes, std::map& takeoverHeights, const uint256& hashBlockIn, claimQueueType& queueCache, queueNameType& queueNameCache, expirationQueueType& expirationQueueCache, int nNewHeight, supportMapType& supportCache, supportQueueType& supportQueueCache, queueNameType& supportQueueNameCache, expirationQueueType& supportExpirationQueueCache) -{ - for (nodeCacheType::iterator itcache = cache.begin(); itcache != cache.end(); ++itcache) - { - if (!updateName(itcache->first, itcache->second)) - { - LogPrintf("%s: Failed to update name for:%s\n", __func__, itcache->first); - return false; - } - } - for (hashMapType::iterator ithash = hashes.begin(); ithash != hashes.end(); ++ithash) - { - if (!updateHash(ithash->first, ithash->second)) - { - LogPrintf("%s: Failed to update hash for:%s\n", __func__, ithash->first); - return false; - } - } - for (std::map::iterator itheight = takeoverHeights.begin(); itheight != takeoverHeights.end(); ++itheight) - { - if (!updateTakeoverHeight(itheight->first, itheight->second)) - { - LogPrintf("%s: Failed to update takeover height for:%s\n", __func__, itheight->first); - return false; - } - } - for (claimQueueType::iterator itQueueCacheRow = queueCache.begin(); itQueueCacheRow != queueCache.end(); ++itQueueCacheRow) - { - updateQueueRow(itQueueCacheRow->first, itQueueCacheRow->second); - } - for (queueNameType::iterator itQueueNameCacheRow = queueNameCache.begin(); itQueueNameCacheRow != queueNameCache.end(); ++itQueueNameCacheRow) - { - updateQueueNameRow(itQueueNameCacheRow->first, itQueueNameCacheRow->second); - } - for (expirationQueueType::iterator itExpirationRow = expirationQueueCache.begin(); itExpirationRow != expirationQueueCache.end(); ++itExpirationRow) - { - updateExpirationRow(itExpirationRow->first, itExpirationRow->second); - } - for (supportMapType::iterator itSupportCache = supportCache.begin(); itSupportCache != supportCache.end(); ++itSupportCache) - { - updateSupportMap(itSupportCache->first, itSupportCache->second); - } - for (supportQueueType::iterator itSupportQueue = supportQueueCache.begin(); itSupportQueue != supportQueueCache.end(); ++itSupportQueue) - { - updateSupportQueue(itSupportQueue->first, itSupportQueue->second); - } - for (queueNameType::iterator itSupportNameQueue = supportQueueNameCache.begin(); itSupportNameQueue != supportQueueNameCache.end(); ++itSupportNameQueue) - { - updateSupportNameQueue(itSupportNameQueue->first, itSupportNameQueue->second); - } - for (expirationQueueType::iterator itSupportExpirationQueue = supportExpirationQueueCache.begin(); itSupportExpirationQueue != supportExpirationQueueCache.end(); ++itSupportExpirationQueue) - { - updateSupportExpirationQueue(itSupportExpirationQueue->first, itSupportExpirationQueue->second); - } - hashBlock = hashBlockIn; - nCurrentHeight = nNewHeight; - return true; -} - -void CClaimTrie::markNodeDirty(const std::string &name, CClaimTrieNode* node) +void CClaimTrie::markNodeDirty(const std::string& name, CClaimTrieNode* node) { std::pair ret; ret = dirtyNodes.insert(std::pair(name, node)); - if (ret.second == false) + if (ret.second == false) { ret.first->second = node; + } } -bool CClaimTrie::updateName(const std::string &name, CClaimTrieNode* updatedNode) +bool CClaimTrie::updateName(const std::string& name, CClaimTrieNode* updatedNode) { CClaimTrieNode* current = &root; - for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname) - { + for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname) { nodeMapType::iterator itchild = current->children.find(*itname); - if (itchild == current->children.end()) - { - if (itname + 1 == name.end()) - { + if (itchild == current->children.end()) { + if (itname + 1 == name.end()) { CClaimTrieNode* newNode = new CClaimTrieNode(); current->children[*itname] = newNode; current = newNode; - } - else + } else { return false; - } - else - { + } + } else { current = itchild->second; } } assert(current != NULL); current->claims.swap(updatedNode->claims); markNodeDirty(name, current); - for (nodeMapType::iterator itchild = current->children.begin(); itchild != current->children.end();) - { + for (nodeMapType::iterator itchild = current->children.begin(); itchild != current->children.end();) { nodeMapType::iterator itupdatechild = updatedNode->children.find(itchild->first); - if (itupdatechild == updatedNode->children.end()) - { + if (itupdatechild == updatedNode->children.end()) { // This character has apparently been deleted, so delete // all descendents from this child. std::stringstream ss; ss << name << itchild->first; std::string newName = ss.str(); - if (!recursiveNullify(itchild->second, newName)) - return false; + if (!recursiveNullify(itchild->second, newName)) return false; current->children.erase(itchild++); - } - else + } else { ++itchild; + } } return true; } @@ -887,13 +559,11 @@ bool CClaimTrie::updateName(const std::string &name, CClaimTrieNode* updatedNode bool CClaimTrie::recursiveNullify(CClaimTrieNode* node, std::string& name) { assert(node != NULL); - for (nodeMapType::iterator itchild = node->children.begin(); itchild != node->children.end(); ++itchild) - { + for (nodeMapType::iterator itchild = node->children.begin(); itchild != node->children.end(); ++itchild) { std::stringstream ss; ss << name << itchild->first; std::string newName = ss.str(); - if (!recursiveNullify(itchild->second, newName)) - return false; + if (!recursiveNullify(itchild->second, newName)) return false; } node->children.clear(); markNodeDirty(name, NULL); @@ -901,14 +571,12 @@ bool CClaimTrie::recursiveNullify(CClaimTrieNode* node, std::string& name) return true; } -bool CClaimTrie::updateHash(const std::string& name, uint256& hash) +bool CClaimTrie::updateHash(const std::string& name, const uint256& hash) { CClaimTrieNode* current = &root; - for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname) - { + for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname) { nodeMapType::iterator itchild = current->children.find(*itname); - if (itchild == current->children.end()) - return false; + if (itchild == current->children.end()) return false; current = itchild->second; } assert(current != NULL); @@ -920,11 +588,9 @@ bool CClaimTrie::updateHash(const std::string& name, uint256& hash) bool CClaimTrie::updateTakeoverHeight(const std::string& name, int nTakeoverHeight) { CClaimTrieNode* current = &root; - for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname) - { + for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname) { nodeMapType::iterator itchild = current->children.find(*itname); - if (itchild == current->children.end()) - return false; + if (itchild == current->children.end()) return false; current = itchild->second; } assert(current != NULL); @@ -933,160 +599,41 @@ bool CClaimTrie::updateTakeoverHeight(const std::string& name, int nTakeoverHeig return true; } -void CClaimTrie::BatchWriteNode(CDBBatch& batch, const std::string& name, const CClaimTrieNode* pNode) const -{ - if (pNode) - batch.Write(std::make_pair(TRIE_NODE, name), *pNode); - else - batch.Erase(std::make_pair(TRIE_NODE, name)); -} - -void CClaimTrie::BatchWriteQueueRows(CDBBatch& batch) -{ - for (claimQueueType::iterator itQueue = dirtyQueueRows.begin(); itQueue != dirtyQueueRows.end(); ++itQueue) - { - if (itQueue->second.empty()) - { - batch.Erase(std::make_pair(CLAIM_QUEUE_ROW, itQueue->first)); - } - else - { - batch.Write(std::make_pair(CLAIM_QUEUE_ROW, itQueue->first), itQueue->second); - } - } -} - -void CClaimTrie::BatchWriteQueueNameRows(CDBBatch& batch) -{ - for (queueNameType::iterator itQueue = dirtyQueueNameRows.begin(); itQueue != dirtyQueueNameRows.end(); ++itQueue) - { - if (itQueue->second.empty()) - { - batch.Erase(std::make_pair(CLAIM_QUEUE_NAME_ROW, itQueue->first)); - } - else - { - batch.Write(std::make_pair(CLAIM_QUEUE_NAME_ROW, itQueue->first), itQueue->second); - } - } -} - -void CClaimTrie::BatchWriteExpirationQueueRows(CDBBatch& batch) -{ - for (expirationQueueType::iterator itQueue = dirtyExpirationQueueRows.begin(); itQueue != dirtyExpirationQueueRows.end(); ++itQueue) - { - if (itQueue->second.empty()) - { - batch.Erase(std::make_pair(EXP_QUEUE_ROW, itQueue->first)); - } - else - { - batch.Write(std::make_pair(EXP_QUEUE_ROW, itQueue->first), itQueue->second); - } - } -} - -void CClaimTrie::BatchWriteSupportNodes(CDBBatch& batch) -{ - for (supportMapType::iterator itSupport = dirtySupportNodes.begin(); itSupport != dirtySupportNodes.end(); ++itSupport) - { - if (itSupport->second.empty()) - { - batch.Erase(std::make_pair(SUPPORT, itSupport->first)); - } - else - { - batch.Write(std::make_pair(SUPPORT, itSupport->first), itSupport->second); - } - } -} - -void CClaimTrie::BatchWriteSupportQueueRows(CDBBatch& batch) -{ - for (supportQueueType::iterator itQueue = dirtySupportQueueRows.begin(); itQueue != dirtySupportQueueRows.end(); ++itQueue) - { - if (itQueue->second.empty()) - { - batch.Erase(std::make_pair(SUPPORT_QUEUE_ROW, itQueue->first)); - } - else - { - batch.Write(std::make_pair(SUPPORT_QUEUE_ROW, itQueue->first), itQueue->second); - } - } -} - -void CClaimTrie::BatchWriteSupportQueueNameRows(CDBBatch& batch) -{ - for (queueNameType::iterator itQueue = dirtySupportQueueNameRows.begin(); itQueue != dirtySupportQueueNameRows.end(); ++itQueue) - { - if (itQueue->second.empty()) - { - batch.Erase(std::make_pair(SUPPORT_QUEUE_NAME_ROW, itQueue->first)); - } - else - { - batch.Write(std::make_pair(SUPPORT_QUEUE_NAME_ROW, itQueue->first), itQueue->second); - } - } -} - -void CClaimTrie::BatchWriteSupportExpirationQueueRows(CDBBatch& batch) -{ - for (expirationQueueType::iterator itQueue = dirtySupportExpirationQueueRows.begin(); itQueue != dirtySupportExpirationQueueRows.end(); ++itQueue) - { - if (itQueue->second.empty()) - { - batch.Erase(std::make_pair(SUPPORT_EXP_QUEUE_ROW, itQueue->first)); - } - else - { - batch.Write(std::make_pair(SUPPORT_EXP_QUEUE_ROW, itQueue->first), itQueue->second); - } - } -} - bool CClaimTrie::WriteToDisk() { - CDBBatch batch(&db.GetObfuscateKey()); - for (nodeCacheType::iterator itcache = dirtyNodes.begin(); itcache != dirtyNodes.end(); ++itcache) - BatchWriteNode(batch, itcache->first, itcache->second); + for (nodeCacheType::iterator itcache = dirtyNodes.begin(); itcache != dirtyNodes.end(); ++itcache) { + CClaimTrieNode* pNode = itcache->second; + uint32_t num_claims = pNode ? pNode->claims.size() : 0; + LogPrintf("%s: Writing %s to disk with %d claims\n", __func__, itcache->first, num_claims); + if (pNode) { + CClaimTrieNode copy(*pNode); + db.updateQueueRow(itcache->first, copy); + } else { + CClaimTrieNode emptyNode; + db.updateQueueRow(itcache->first, emptyNode); + } + } + dirtyNodes.clear(); - BatchWriteQueueRows(batch); - dirtyQueueRows.clear(); - BatchWriteQueueNameRows(batch); - dirtyQueueNameRows.clear(); - BatchWriteExpirationQueueRows(batch); - dirtyExpirationQueueRows.clear(); - BatchWriteSupportNodes(batch); - dirtySupportNodes.clear(); - BatchWriteSupportQueueRows(batch); - dirtySupportQueueRows.clear(); - BatchWriteSupportQueueNameRows(batch); - dirtySupportQueueNameRows.clear(); - BatchWriteSupportExpirationQueueRows(batch); - dirtySupportExpirationQueueRows.clear(); - batch.Write(HASH_BLOCK, hashBlock); - batch.Write(CURRENT_HEIGHT, nCurrentHeight); - return db.WriteBatch(batch); + db.writeQueues(); + db.Write(HASH_BLOCK, hashBlock); + db.Write(CURRENT_HEIGHT, nCurrentHeight); + return db.Sync(); } bool CClaimTrie::InsertFromDisk(const std::string& name, CClaimTrieNode* node) { - if (name.size() == 0) - { + if (name.empty()) { root = *node; return true; } CClaimTrieNode* current = &root; - for (std::string::const_iterator itname = name.begin(); itname + 1 != name.end(); ++itname) - { + for (std::string::const_iterator itname = name.begin(); itname + 1 != name.end(); ++itname) { nodeMapType::iterator itchild = current->children.find(*itname); - if (itchild == current->children.end()) - return false; + if (itchild == current->children.end()) return false; current = itchild->second; } - current->children[name[name.size()-1]] = node; + current->children[name[name.size() - 1]] = new CClaimTrieNode(*node); return true; } @@ -1096,82 +643,76 @@ bool CClaimTrie::ReadFromDisk(bool check) LogPrintf("%s: Couldn't read the best block's hash\n", __func__); if (!db.Read(CURRENT_HEIGHT, nCurrentHeight)) LogPrintf("%s: Couldn't read the current height\n", __func__); - setExpirationTime(Params().GetConsensus().GetExpirationTime(nCurrentHeight-1)); - boost::scoped_ptr pcursor(const_cast(&db)->NewIterator()); + setExpirationTime(Params().GetConsensus().GetExpirationTime(nCurrentHeight - 1)); - pcursor->SeekToFirst(); - while (pcursor->Valid()) - { - std::pair key; - if (pcursor->GetKey(key)) - { - if (key.first == TRIE_NODE) - { - CClaimTrieNode* node = new CClaimTrieNode(); - if (pcursor->GetValue(*node)) - { - if (!InsertFromDisk(key.second, node)) - { - return error("%s(): error restoring claim trie from disk", __func__); - } - } - else - { - return error("%s(): error reading claim trie from disk", __func__); - } - } - } - pcursor->Next(); + typedef std::map trieNodeMapType; + + trieNodeMapType nodes; + if (!db.seekByKey(nodes)) { + return error("%s(): error reading claim trie from disk", __func__); } - if (check) - { + for (trieNodeMapType::iterator it = nodes.begin(); it != nodes.end(); ++it) { + if (!InsertFromDisk(it->first, &(it->second))) { + return error("%s(): error restoring claim trie from disk", __func__); + } + } + + if (check) { LogPrintf("Checking Claim trie consistency..."); - if (checkConsistency()) - { + if (checkConsistency()) { LogPrintf("consistent\n"); return true; + } else { + LogPrintf("inconsistent!\n"); + return false; } - LogPrintf("inconsistent!\n"); - return false; } return true; } -bool CClaimTrieCache::recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent, std::string sPos) const +CClaimTrieCache::CClaimTrieCache(CClaimTrie* base, bool fRequireTakeoverHeights) + : base(base), fRequireTakeoverHeights(fRequireTakeoverHeights) { - if (sPos == "" && tnCurrent->empty()) - { - cacheHashes[""] = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); + assert(base); + hashBlock = base->hashBlock; + nCurrentHeight = base->nCurrentHeight; +} + +CClaimTrieCache::~CClaimTrieCache() +{ + clear(); +} + +bool CClaimTrieCache::recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent, const std::string& sPos) const +{ + if (sPos == "" && tnCurrent->empty()) { + cacheHashes[""] = one; return true; } std::vector vchToHash; - nodeCacheType::iterator cachedNode; + nodeCacheType::const_iterator cachedNode; - for (nodeMapType::iterator it = tnCurrent->children.begin(); it != tnCurrent->children.end(); ++it) - { + for (nodeMapType::iterator it = tnCurrent->children.begin(); it != tnCurrent->children.end(); ++it) { std::stringstream ss; ss << it->first; std::string sNextPos = sPos + ss.str(); - if (dirtyHashes.count(sNextPos) != 0) - { + if (dirtyHashes.count(sNextPos) != 0) { // the child might be in the cache, so look for it there cachedNode = cache.find(sNextPos); - if (cachedNode != cache.end()) + if (cachedNode != cache.end()) { recursiveComputeMerkleHash(cachedNode->second, sNextPos); - else + } else { recursiveComputeMerkleHash(it->second, sNextPos); + } } vchToHash.push_back(it->first); hashMapType::iterator ithash = cacheHashes.find(sNextPos); - if (ithash != cacheHashes.end()) - { + if (ithash != cacheHashes.end()) { vchToHash.insert(vchToHash.end(), ithash->second.begin(), ithash->second.end()); - } - else - { + } else { vchToHash.insert(vchToHash.end(), it->second->hash.begin(), it->second->hash.end()); } } @@ -1179,8 +720,7 @@ bool CClaimTrieCache::recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent, std: CClaimValue claim; bool hasClaim = tnCurrent->getBestClaim(claim); - if (hasClaim) - { + if (hasClaim) { int nHeightOfLastTakeover; assert(getLastTakeoverForName(sPos, nHeightOfLastTakeover)); uint256 valueHash = getValueHash(claim.outPoint, nHeightOfLastTakeover); @@ -1193,28 +733,29 @@ bool CClaimTrieCache::recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent, std: hasher.Finalize(&(vchHash[0])); cacheHashes[sPos] = uint256(vchHash); std::set::iterator itDirty = dirtyHashes.find(sPos); - if (itDirty != dirtyHashes.end()) + if (itDirty != dirtyHashes.end()) { dirtyHashes.erase(itDirty); + } return true; } uint256 CClaimTrieCache::getMerkleHash() const { - if (empty()) - { - uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); - return one; + if (empty()) return one; + if (dirty()) { + nodeCacheType::const_iterator cachedNode = cache.find(""); + if (cachedNode != cache.end()) { + recursiveComputeMerkleHash(cachedNode->second, ""); + } else { + recursiveComputeMerkleHash(&(base->root), ""); + } } - if (dirty()) - { - CClaimTrieNode* root = getRoot(); - recursiveComputeMerkleHash(root, ""); - } - hashMapType::iterator ithash = cacheHashes.find(""); - if (ithash != cacheHashes.end()) + hashMapType::const_iterator ithash = cacheHashes.find(""); + if (ithash != cacheHashes.end()) { return ithash->second; - else + } else { return base->root.hash; + } } bool CClaimTrieCache::empty() const @@ -1222,26 +763,27 @@ bool CClaimTrieCache::empty() const return base->empty() && cache.empty(); } -CClaimTrieNode* CClaimTrieCache::addNodeToCache(const std::string& position, CClaimTrieNode* original) const +CClaimTrieNode* CClaimTrieCache::addNodeToCache(const std::string& position, CClaimTrieNode* original) { // create a copy of the node in the cache, if new node, create empty node CClaimTrieNode* cacheCopy; - if(!original) + if (!original) { cacheCopy = new CClaimTrieNode(); - else + } else { cacheCopy = new CClaimTrieNode(*original); + } cache[position] = cacheCopy; // check to see if there is the original node in block_originals, // if not, add it to block_originals cache nodeCacheType::const_iterator itOriginals = block_originals.find(position); - if (block_originals.end() == itOriginals) - { + if (block_originals.end() == itOriginals) { CClaimTrieNode* originalCopy; - if(!original) + if (!original) { originalCopy = new CClaimTrieNode(); - else + } else { originalCopy = new CClaimTrieNode(*original); + } block_originals[position] = originalCopy; } return cacheCopy; @@ -1250,32 +792,32 @@ CClaimTrieNode* CClaimTrieCache::addNodeToCache(const std::string& position, CCl bool CClaimTrieCache::getOriginalInfoForName(const std::string& name, CClaimValue& claim) const { nodeCacheType::const_iterator itOriginalCache = block_originals.find(name); - if (itOriginalCache == block_originals.end()) - { + if (itOriginalCache == block_originals.end()) { return base->getInfoForName(name, claim); } return itOriginalCache->second->getBestClaim(claim); } -bool CClaimTrieCache::insertClaimIntoTrie(const std::string& name, CClaimValue claim, bool fCheckTakeover) const +bool CClaimTrieCache::insertClaimIntoTrie(const std::string& name, const CClaimValue& claim, bool fCheckTakeover) { assert(base); - CClaimTrieNode* currentNode = getRoot(); + CClaimTrieNode* currentNode = &(base->root); nodeCacheType::iterator cachedNode; - for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) - { + cachedNode = cache.find(""); + if (cachedNode != cache.end()) { + currentNode = cachedNode->second; + } + for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) { std::string sCurrentSubstring(name.begin(), itCur); std::string sNextSubstring(name.begin(), itCur + 1); cachedNode = cache.find(sNextSubstring); - if (cachedNode != cache.end()) - { + if (cachedNode != cache.end()) { currentNode = cachedNode->second; continue; } nodeMapType::iterator childNode = currentNode->children.find(*itCur); - if (childNode != currentNode->children.end()) - { + if (childNode != currentNode->children.end()) { currentNode = childNode->second; continue; } @@ -1290,12 +832,9 @@ bool CClaimTrieCache::insertClaimIntoTrie(const std::string& name, CClaimValue c // used to find the child in the cache. This is necessary in // order to calculate the merkle hash. cachedNode = cache.find(sCurrentSubstring); - if (cachedNode != cache.end()) - { + if (cachedNode != cache.end()) { assert(cachedNode->second == currentNode); - } - else - { + } else { currentNode = addNodeToCache(sCurrentSubstring, currentNode); } CClaimTrieNode* newNode = addNodeToCache(sNextSubstring, NULL); @@ -1304,65 +843,59 @@ bool CClaimTrieCache::insertClaimIntoTrie(const std::string& name, CClaimValue c } cachedNode = cache.find(name); - if (cachedNode != cache.end()) - { + if (cachedNode != cache.end()) { assert(cachedNode->second == currentNode); - } - else - { + } else { currentNode = addNodeToCache(name, currentNode); } bool fChanged = false; - if (currentNode->claims.empty()) - { + if (currentNode->claims.empty()) { fChanged = true; currentNode->insertClaim(claim); - } - else - { + } else { CClaimValue currentTop = currentNode->claims.front(); currentNode->insertClaim(claim); supportMapEntryType node; getSupportsForName(name, node); currentNode->reorderClaims(node); - if (currentTop != currentNode->claims.front()) + if (currentTop != currentNode->claims.front()) { fChanged = true; + } } - - if (fChanged) - { - for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) - { + if (fChanged) { + for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) { std::string sub(name.begin(), itCur); dirtyHashes.insert(sub); } dirtyHashes.insert(name); - if (fCheckTakeover) + if (fCheckTakeover) { namesToCheckForTakeover.insert(name); + } } return true; } -bool CClaimTrieCache::removeClaimFromTrie(const std::string& name, const COutPoint& outPoint, CClaimValue& claim, bool fCheckTakeover) const +bool CClaimTrieCache::removeClaimFromTrie(const std::string& name, const COutPoint& outPoint, CClaimValue& claim, bool fCheckTakeover) { assert(base); - CClaimTrieNode* currentNode = getRoot(); + CClaimTrieNode* currentNode = &(base->root); nodeCacheType::iterator cachedNode; + cachedNode = cache.find(""); + if (cachedNode != cache.end()) { + currentNode = cachedNode->second; + } assert(currentNode != NULL); // If there is no root in either the trie or the cache, how can there be any names to remove? - for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) - { + for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) { std::string sCurrentSubstring(name.begin(), itCur); std::string sNextSubstring(name.begin(), itCur + 1); cachedNode = cache.find(sNextSubstring); - if (cachedNode != cache.end()) - { + if (cachedNode != cache.end()) { currentNode = cachedNode->second; continue; } nodeMapType::iterator childNode = currentNode->children.find(*itCur); - if (childNode != currentNode->children.end()) - { + if (childNode != currentNode->children.end()) { currentNode = childNode->second; continue; } @@ -1371,84 +904,80 @@ bool CClaimTrieCache::removeClaimFromTrie(const std::string& name, const COutPoi } cachedNode = cache.find(name); - if (cachedNode != cache.end()) + if (cachedNode != cache.end()) { assert(cachedNode->second == currentNode); - else - { + } else { currentNode = addNodeToCache(name, currentNode); } bool fChanged = false; assert(currentNode != NULL); bool success = false; - if (currentNode->claims.empty()) - { + if (currentNode->claims.empty()) { LogPrintf("%s: Asked to remove claim from node without claims\n", __func__); return false; } CClaimValue currentTop = currentNode->claims.front(); success = currentNode->removeClaim(outPoint, claim); - if (!currentNode->claims.empty()) - { + if (!currentNode->claims.empty()) { supportMapEntryType node; getSupportsForName(name, node); currentNode->reorderClaims(node); - if (currentTop != currentNode->claims.front()) + if (currentTop != currentNode->claims.front()) { fChanged = true; - } - else + } + } else { fChanged = true; + } - if (!success) - { + if (!success) { LogPrintf("%s: Removing a claim was unsuccessful. name = %s, txhash = %s, nOut = %d", __func__, name.c_str(), outPoint.hash.GetHex(), outPoint.n); return false; } - if (fChanged) - { - for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) - { + if (fChanged) { + for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) { std::string sub(name.begin(), itCur); dirtyHashes.insert(sub); } dirtyHashes.insert(name); - if (fCheckTakeover) + if (fCheckTakeover) { namesToCheckForTakeover.insert(name); + } + } + CClaimTrieNode* rootNode = &(base->root); + cachedNode = cache.find(""); + if (cachedNode != cache.end()) { + rootNode = cachedNode->second; } - CClaimTrieNode* rootNode = getRoot(); return recursivePruneName(rootNode, 0, name); } -bool CClaimTrieCache::recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, std::string sName, bool* pfNullified) const +bool CClaimTrieCache::recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, const std::string& sName, bool* pfNullified) { // Recursively prune leaf node(s) without any claims in it and store // the modified nodes in the cache bool fNullified = false; std::string sCurrentSubstring = sName.substr(0, nPos); - if (nPos < sName.size()) - { + if (nPos < sName.size()) { std::string sNextSubstring = sName.substr(0, nPos + 1); unsigned char cNext = sName.at(nPos); CClaimTrieNode* tnNext = NULL; nodeCacheType::iterator cachedNode = cache.find(sNextSubstring); - if (cachedNode != cache.end()) + if (cachedNode != cache.end()) { tnNext = cachedNode->second; - else - { + } else { nodeMapType::iterator childNode = tnCurrent->children.find(cNext); - if (childNode != tnCurrent->children.end()) + if (childNode != tnCurrent->children.end()) { tnNext = childNode->second; + } } - if (tnNext == NULL) - return false; + if (tnNext == NULL) return false; bool fChildNullified = false; - if (!recursivePruneName(tnNext, nPos + 1, sName, &fChildNullified)) - return false; - if (fChildNullified) - { + if (!recursivePruneName(tnNext, nPos + 1, sName, &fChildNullified)) return false; + if (fChildNullified) { // If the child nullified itself, the child should already be // out of the cache, and the character must now be removed // from the current node's map of child nodes to ensure that @@ -1463,8 +992,7 @@ bool CClaimTrieCache::recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int // First, find out if this node is in the cache. cachedNode = cache.find(sCurrentSubstring); - if (cachedNode == cache.end()) - { + if (cachedNode == cache.end()) { // it isn't, so make a copy, stick it in the cache, // and make it the new current node tnCurrent = addNodeToCache(sCurrentSubstring, tnCurrent); @@ -1472,267 +1000,189 @@ bool CClaimTrieCache::recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int // erase the character from the current node, which is // now guaranteed to be in the cache nodeMapType::iterator childNode = tnCurrent->children.find(cNext); - if (childNode != tnCurrent->children.end()) + if (childNode != tnCurrent->children.end()) { tnCurrent->children.erase(childNode); - else + } else { return false; + } } } - if (sCurrentSubstring.size() != 0 && tnCurrent->empty()) - { + if (sCurrentSubstring.size() != 0 && tnCurrent->empty()) { // If the current node is in the cache, remove it from there nodeCacheType::iterator cachedNode = cache.find(sCurrentSubstring); - if (cachedNode != cache.end()) - { + if (cachedNode != cache.end()) { assert(tnCurrent == cachedNode->second); delete tnCurrent; cache.erase(cachedNode); } fNullified = true; } - if (pfNullified) + if (pfNullified) { *pfNullified = fNullified; + } return true; } -claimQueueType::iterator CClaimTrieCache::getQueueCacheRow(int nHeight, bool createIfNotExists) const -{ - claimQueueType::iterator itQueueRow = claimQueueCache.find(nHeight); - if (itQueueRow == claimQueueCache.end()) - { - // Have to make a new row it put in the cache, if createIfNotExists is true - claimQueueRowType queueRow; - // If the row exists in the base, copy its claims into the new row. - bool exists = base->getQueueRow(nHeight, queueRow); - if (!exists) - if (!createIfNotExists) - return itQueueRow; - // Stick the new row in the cache - std::pair ret; - ret = claimQueueCache.insert(std::pair(nHeight, queueRow)); - assert(ret.second); - itQueueRow = ret.first; - } - return itQueueRow; -} - -queueNameType::iterator CClaimTrieCache::getQueueCacheNameRow(const std::string& name, bool createIfNotExists) const -{ - queueNameType::iterator itQueueNameRow = claimQueueNameCache.find(name); - if (itQueueNameRow == claimQueueNameCache.end()) - { - // Have to make a new name row and put it in the cache, if createIfNotExists is true - queueNameRowType queueNameRow; - // If the row exists in the base, copy its claims into the new row. - bool exists = base->getQueueNameRow(name, queueNameRow); - if (!exists) - if (!createIfNotExists) - return itQueueNameRow; - // Stick the new row in the cache - std::pair ret; - ret = claimQueueNameCache.insert(std::pair(name, queueNameRow)); - assert(ret.second); - itQueueNameRow = ret.first; - } - return itQueueNameRow; -} - -bool CClaimTrieCache::addClaim(const std::string& name, const COutPoint& outPoint, uint160 claimId, CAmount nAmount, int nHeight) const +bool CClaimTrieCache::addClaim(const std::string& name, const COutPoint& outPoint, const uint160& claimId, const CAmount& nAmount, int nHeight) { LogPrintf("%s: name: %s, txhash: %s, nOut: %d, claimId: %s, nAmount: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, claimId.GetHex(), nAmount, nHeight, nCurrentHeight); assert(nHeight == nCurrentHeight); CClaimValue currentClaim; int delayForClaim; - if (getOriginalInfoForName(name, currentClaim) && currentClaim.claimId == claimId) - { + if (getOriginalInfoForName(name, currentClaim) && currentClaim.claimId == claimId) { LogPrintf("%s: This is an update to a best claim.\n", __func__); delayForClaim = 0; - } - else - { + } else { delayForClaim = getDelayForName(name); } CClaimValue newClaim(outPoint, claimId, nAmount, nHeight, nHeight + delayForClaim); return addClaimToQueues(name, newClaim); } -bool CClaimTrieCache::undoSpendClaim(const std::string& name, const COutPoint& outPoint, uint160 claimId, CAmount nAmount, int nHeight, int nValidAtHeight) const +bool CClaimTrieCache::undoSpendClaim(const std::string& name, const COutPoint& outPoint, const uint160& claimId, const CAmount& nAmount, int nHeight, int nValidAtHeight) { LogPrintf("%s: name: %s, txhash: %s, nOut: %d, claimId: %s, nAmount: %d, nHeight: %d, nValidAtHeight: %d, nCurrentHeight: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, claimId.GetHex(), nAmount, nHeight, nValidAtHeight, nCurrentHeight); CClaimValue claim(outPoint, claimId, nAmount, nHeight, nValidAtHeight); - if (nValidAtHeight < nCurrentHeight) - { + if (nValidAtHeight < nCurrentHeight) { nameOutPointType entry(name, claim.outPoint); addToExpirationQueue(claim.nHeight + base->nExpirationTime, entry); - CClaimIndexElement element = {name, claim}; - claimsToAdd.push_back(element); + base->addToClaimIndex(name, claim); return insertClaimIntoTrie(name, claim, false); - } - else - { + } else { return addClaimToQueues(name, claim); } } -bool CClaimTrieCache::addClaimToQueues(const std::string& name, CClaimValue& claim) const +template +typename std::map::iterator CClaimTrieCache::getQueueCacheRow(const K& key, std::map& map, bool createIfNotExists) +{ + typename std::map::iterator itQueueRow = map.find(key); + if (itQueueRow == map.end()) { + // Have to make a new row it put in the cache, if createIfNotExists is true + V queueRow; + // If the row exists in the base, copy its claims into the new row. + bool exists = base->db.getQueueRow(key, queueRow); + if (!exists && !createIfNotExists) return itQueueRow; + // Stick the new row in the cache + itQueueRow = map.insert(itQueueRow, std::make_pair(key, queueRow)); + } + return itQueueRow; +} + +bool CClaimTrieCache::addClaimToQueues(const std::string& name, CClaimValue& claim) { LogPrintf("%s: nValidAtHeight: %d\n", __func__, claim.nValidAtHeight); claimQueueEntryType entry(name, claim); - claimQueueType::iterator itQueueRow = getQueueCacheRow(claim.nValidAtHeight, true); - queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(name, true); + claimQueueType::iterator itQueueRow = getQueueCacheRow(claim.nValidAtHeight, claimQueueCache, true); + queueNameType::iterator itQueueNameRow = getQueueCacheRow(name, claimQueueNameCache, true); itQueueRow->second.push_back(entry); itQueueNameRow->second.push_back(outPointHeightType(claim.outPoint, claim.nValidAtHeight)); nameOutPointType expireEntry(name, claim.outPoint); addToExpirationQueue(claim.nHeight + base->nExpirationTime, expireEntry); - CClaimIndexElement element = {name, claim}; - claimsToAdd.push_back(element); + base->addToClaimIndex(name, claim); return true; } -bool CClaimTrieCache::removeClaimFromQueue(const std::string& name, const COutPoint& outPoint, CClaimValue& claim) const +bool CClaimTrieCache::removeClaimFromQueue(const std::string& name, const COutPoint& outPoint, CClaimValue& claim) { - queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(name, false); - if (itQueueNameRow == claimQueueNameCache.end()) - { - return false; - } + queueNameType::iterator itQueueNameRow = getQueueCacheRow(name, claimQueueNameCache, false); + if (itQueueNameRow == claimQueueNameCache.end()) return false; queueNameRowType::iterator itQueueName; - for (itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) - { - if (itQueueName->outPoint == outPoint) - { - break; - } + for (itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) { + if (itQueueName->outPoint == outPoint) break; } - if (itQueueName == itQueueNameRow->second.end()) - { - return false; - } - claimQueueType::iterator itQueueRow = getQueueCacheRow(itQueueName->nHeight, false); - if (itQueueRow != claimQueueCache.end()) - { + if (itQueueName == itQueueNameRow->second.end()) return false; + claimQueueType::iterator itQueueRow = getQueueCacheRow(itQueueName->nHeight, claimQueueCache, false); + if (itQueueRow != claimQueueCache.end()) { claimQueueRowType::iterator itQueue; - for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) - { - if (name == itQueue->first && itQueue->second.outPoint == outPoint) - { - break; + for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) { + if (name == itQueue->first && itQueue->second.outPoint == outPoint) { + std::swap(claim, itQueue->second); + itQueueNameRow->second.erase(itQueueName); + itQueueRow->second.erase(itQueue); + return true; } } - if (itQueue != itQueueRow->second.end()) - { - std::swap(claim, itQueue->second); - itQueueNameRow->second.erase(itQueueName); - itQueueRow->second.erase(itQueue); - return true; - } } LogPrintf("%s: An inconsistency was found in the claim queue. Please report this to the developers:\nFound in named queue but not in height queue: name: %s, txid: %s, nOut: %d, nValidAtHeight: %d, current height: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, itQueueName->nHeight, nCurrentHeight); return false; } -bool CClaimTrieCache::undoAddClaim(const std::string& name, const COutPoint& outPoint) const +bool CClaimTrieCache::undoAddClaim(const std::string& name, const COutPoint& outPoint, int nHeight) { int throwaway; - return removeClaim(name, outPoint, throwaway, false); + return removeClaim(name, outPoint, nHeight, throwaway, false); } -bool CClaimTrieCache::spendClaim(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const +bool CClaimTrieCache::spendClaim(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight) { - return removeClaim(name, outPoint, nValidAtHeight, true); + return removeClaim(name, outPoint, nHeight, nValidAtHeight, true); } -bool CClaimTrieCache::removeClaim(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight, bool fCheckTakeover) const +bool CClaimTrieCache::removeClaim(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight, bool fCheckTakeover) { - LogPrintf("%s: name: %s, txhash: %s, nOut: %s, nCurrentHeight: %s\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nCurrentHeight); + LogPrintf("%s: name: %s, txhash: %s, nOut: %s, nHeight: %s, nCurrentHeight: %s\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nHeight, nCurrentHeight); bool removed = false; CClaimValue claim; - if (removeClaimFromQueue(name, outPoint, claim)) - { + if (removeClaimFromQueue(name, outPoint, claim)) { removed = true; } - if (removed == false && removeClaimFromTrie(name, outPoint, claim, fCheckTakeover)) - { + if (removed == false && removeClaimFromTrie(name, outPoint, claim, fCheckTakeover)) { removed = true; } - if (removed == true) - { + if (removed == true) { nValidAtHeight = claim.nValidAtHeight; - int expirationHeight = claim.nHeight + base->nExpirationTime; + int expirationHeight = nHeight + base->nExpirationTime; removeFromExpirationQueue(name, outPoint, expirationHeight); - claimsToDelete.insert(claim); + base->removeFromClaimIndex(claim); } return removed; } -void CClaimTrieCache::addToExpirationQueue(int nExpirationHeight, nameOutPointType& entry) const +void CClaimTrieCache::addToExpirationQueue(int nExpirationHeight, nameOutPointType& entry) { - expirationQueueType::iterator itQueueRow = getExpirationQueueCacheRow(nExpirationHeight, true); + expirationQueueType::iterator itQueueRow = getQueueCacheRow(nExpirationHeight, expirationQueueCache, true); itQueueRow->second.push_back(entry); } -void CClaimTrieCache::removeFromExpirationQueue(const std::string& name, const COutPoint& outPoint, int expirationHeight) const +void CClaimTrieCache::removeFromExpirationQueue(const std::string& name, const COutPoint& outPoint, int expirationHeight) { - expirationQueueType::iterator itQueueRow = getExpirationQueueCacheRow(expirationHeight, false); + expirationQueueType::iterator itQueueRow = getQueueCacheRow(expirationHeight, expirationQueueCache, false); expirationQueueRowType::iterator itQueue; - if (itQueueRow != expirationQueueCache.end()) - { - for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) - { - if (name == itQueue->name && outPoint == itQueue->outPoint) + if (itQueueRow != expirationQueueCache.end()) { + for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) { + if (name == itQueue->name && outPoint == itQueue->outPoint) { + itQueueRow->second.erase(itQueue); break; - } - - if (itQueue != itQueueRow->second.end()) - { - itQueueRow->second.erase(itQueue); + } } } } -expirationQueueType::iterator CClaimTrieCache::getExpirationQueueCacheRow(int nHeight, bool createIfNotExists) const -{ - expirationQueueType::iterator itQueueRow = expirationQueueCache.find(nHeight); - if (itQueueRow == expirationQueueCache.end()) - { - // Have to make a new row it put in the cache, if createIfNotExists is true - expirationQueueRowType queueRow; - // If the row exists in the base, copy its claims into the new row. - bool exists = base->getExpirationQueueRow(nHeight, queueRow); - if (!exists) - if (!createIfNotExists) - return itQueueRow; - // Stick the new row in the cache - std::pair ret; - ret = expirationQueueCache.insert(std::pair(nHeight, queueRow)); - assert(ret.second); - itQueueRow = ret.first; - } - return itQueueRow; -} - -bool CClaimTrieCache::reorderTrieNode(const std::string& name, bool fCheckTakeover) const +bool CClaimTrieCache::reorderTrieNode(const std::string& name, bool fCheckTakeover) { assert(base); nodeCacheType::iterator cachedNode; cachedNode = cache.find(name); - if (cachedNode == cache.end()) - { - CClaimTrieNode* currentNode = getRoot(); - for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) - { + if (cachedNode == cache.end()) { + CClaimTrieNode* currentNode; + cachedNode = cache.find(""); + if (cachedNode == cache.end()) { + currentNode = &(base->root); + } else { + currentNode = cachedNode->second; + } + for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) { std::string sCurrentSubstring(name.begin(), itCur); std::string sNextSubstring(name.begin(), itCur + 1); cachedNode = cache.find(sNextSubstring); - if (cachedNode != cache.end()) - { + if (cachedNode != cache.end()) { currentNode = cachedNode->second; continue; } nodeMapType::iterator childNode = currentNode->children.find(*itCur); - if (childNode != currentNode->children.end()) - { + if (childNode != currentNode->children.end()) { currentNode = childNode->second; continue; } @@ -1746,59 +1196,52 @@ bool CClaimTrieCache::reorderTrieNode(const std::string& name, bool fCheckTakeov cachedNode = ret.first; } bool fChanged = false; - if (cachedNode->second->claims.empty()) - { + if (cachedNode->second->claims.empty()) { // Nothing in there to reorder return true; - } - else - { + } else { CClaimValue currentTop = cachedNode->second->claims.front(); supportMapEntryType node; getSupportsForName(name, node); cachedNode->second->reorderClaims(node); - if (cachedNode->second->claims.front() != currentTop) + if (cachedNode->second->claims.front() != currentTop) { fChanged = true; + } } - if (fChanged) - { - for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) - { + if (fChanged) { + for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) { std::string sub(name.begin(), itCur); dirtyHashes.insert(sub); } dirtyHashes.insert(name); - if (fCheckTakeover) + if (fCheckTakeover) { namesToCheckForTakeover.insert(name); + } } return true; } bool CClaimTrieCache::getSupportsForName(const std::string& name, supportMapEntryType& node) const { - supportMapType::iterator cachedNode; + supportMapType::const_iterator cachedNode; cachedNode = supportCache.find(name); - if (cachedNode != supportCache.end()) - { + if (cachedNode != supportCache.end()) { node = cachedNode->second; return true; - } - else - { - return base->getSupportNode(name, node); + } else { + return base->db.getQueueRow(name, node); } } -bool CClaimTrieCache::insertSupportIntoMap(const std::string& name, CSupportValue support, bool fCheckTakeover) const +bool CClaimTrieCache::insertSupportIntoMap(const std::string& name, const CSupportValue& support, bool fCheckTakeover) { supportMapType::iterator cachedNode; // If this node is already in the cache, use that cachedNode = supportCache.find(name); // If not, copy the one from base if it exists, and use that - if (cachedNode == supportCache.end()) - { + if (cachedNode == supportCache.end()) { supportMapEntryType node; - base->getSupportNode(name, node); + base->db.getQueueRow(name, node); std::pair ret; ret = supportCache.insert(std::pair(name, node)); assert(ret.second); @@ -1806,18 +1249,16 @@ bool CClaimTrieCache::insertSupportIntoMap(const std::string& name, CSupportValu } cachedNode->second.push_back(support); // See if this changed the biggest bid - return reorderTrieNode(name, fCheckTakeover); + return reorderTrieNode(name, fCheckTakeover); } -bool CClaimTrieCache::removeSupportFromMap(const std::string& name, const COutPoint& outPoint, CSupportValue& support, bool fCheckTakeover) const +bool CClaimTrieCache::removeSupportFromMap(const std::string& name, const COutPoint& outPoint, CSupportValue& support, bool fCheckTakeover) { supportMapType::iterator cachedNode; cachedNode = supportCache.find(name); - if (cachedNode == supportCache.end()) - { + if (cachedNode == supportCache.end()) { supportMapEntryType node; - if (!base->getSupportNode(name, node)) - { + if (!base->db.getQueueRow(name, node)) { // clearly, this support does not exist return false; } @@ -1827,70 +1268,23 @@ bool CClaimTrieCache::removeSupportFromMap(const std::string& name, const COutPo cachedNode = ret.first; } supportMapEntryType::iterator itSupport; - for (itSupport = cachedNode->second.begin(); itSupport != cachedNode->second.end(); ++itSupport) - { - if (itSupport->outPoint == outPoint) - { - break; + for (itSupport = cachedNode->second.begin(); itSupport != cachedNode->second.end(); ++itSupport) { + if (itSupport->outPoint == outPoint) { + std::swap(support, *itSupport); + cachedNode->second.erase(itSupport); + return reorderTrieNode(name, fCheckTakeover); } } - if (itSupport != cachedNode->second.end()) - { - std::swap(support, *itSupport); - cachedNode->second.erase(itSupport); - return reorderTrieNode(name, fCheckTakeover); - } - else - { - LogPrintf("CClaimTrieCache::%s() : asked to remove a support that doesn't exist\n", __func__); - return false; - } + LogPrintf("CClaimTrieCache::%s() : asked to remove a support that doesn't exist\n", __func__); + return false; } -supportQueueType::iterator CClaimTrieCache::getSupportQueueCacheRow(int nHeight, bool createIfNotExists) const -{ - supportQueueType::iterator itQueueRow = supportQueueCache.find(nHeight); - if (itQueueRow == supportQueueCache.end()) - { - supportQueueRowType queueRow; - bool exists = base->getSupportQueueRow(nHeight, queueRow); - if (!exists) - if (!createIfNotExists) - return itQueueRow; - // Stick the new row in the cache - std::pair ret; - ret = supportQueueCache.insert(std::pair(nHeight, queueRow)); - assert(ret.second); - itQueueRow = ret.first; - } - return itQueueRow; -} - -queueNameType::iterator CClaimTrieCache::getSupportQueueCacheNameRow(const std::string& name, bool createIfNotExists) const -{ - queueNameType::iterator itQueueNameRow = supportQueueNameCache.find(name); - if (itQueueNameRow == supportQueueNameCache.end()) - { - queueNameRowType queueNameRow; - bool exists = base->getSupportQueueNameRow(name, queueNameRow); - if (!exists) - if (!createIfNotExists) - return itQueueNameRow; - // Stick the new row in the name cache - std::pair ret; - ret = supportQueueNameCache.insert(std::pair(name, queueNameRow)); - assert(ret.second); - itQueueNameRow = ret.first; - } - return itQueueNameRow; -} - -bool CClaimTrieCache::addSupportToQueues(const std::string& name, CSupportValue& support) const +bool CClaimTrieCache::addSupportToQueues(const std::string& name, CSupportValue& support) { LogPrintf("%s: nValidAtHeight: %d\n", __func__, support.nValidAtHeight); supportQueueEntryType entry(name, support); - supportQueueType::iterator itQueueRow = getSupportQueueCacheRow(support.nValidAtHeight, true); - queueNameType::iterator itQueueNameRow = getSupportQueueCacheNameRow(name, true); + supportQueueType::iterator itQueueRow = getQueueCacheRow(support.nValidAtHeight, supportQueueCache, true); + supportQueueNameType::iterator itQueueNameRow = getQueueCacheRow(name, supportQueueNameCache, true); itQueueRow->second.push_back(entry); itQueueNameRow->second.push_back(outPointHeightType(support.outPoint, support.nValidAtHeight)); nameOutPointType expireEntry(name, support.outPoint); @@ -1898,94 +1292,71 @@ bool CClaimTrieCache::addSupportToQueues(const std::string& name, CSupportValue& return true; } -bool CClaimTrieCache::removeSupportFromQueue(const std::string& name, const COutPoint& outPoint, CSupportValue& support) const +bool CClaimTrieCache::removeSupportFromQueue(const std::string& name, const COutPoint& outPoint, CSupportValue& support) { - queueNameType::iterator itQueueNameRow = getSupportQueueCacheNameRow(name, false); - if (itQueueNameRow == supportQueueNameCache.end()) - { - return false; + supportQueueNameType::iterator itQueueNameRow = getQueueCacheRow(name, supportQueueNameCache, false); + if (itQueueNameRow == supportQueueNameCache.end()) return false; + supportQueueNameRowType::iterator itQueueName; + for (itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) { + if (itQueueName->outPoint == outPoint) break; } - queueNameRowType::iterator itQueueName; - for (itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) - { - if (itQueueName->outPoint == outPoint) - { - break; - } - } - if (itQueueName == itQueueNameRow->second.end()) - { - return false; - } - supportQueueType::iterator itQueueRow = getSupportQueueCacheRow(itQueueName->nHeight, false); - if (itQueueRow != supportQueueCache.end()) - { + if (itQueueName == itQueueNameRow->second.end()) return false; + supportQueueType::iterator itQueueRow = getQueueCacheRow(itQueueName->nHeight, supportQueueCache, false); + if (itQueueRow != supportQueueCache.end()) { supportQueueRowType::iterator itQueue; - for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) - { - CSupportValue& support = itQueue->second; - if (name == itQueue->first && support.outPoint == outPoint) - { - break; + for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) { + if (name == itQueue->first && itQueue->second.outPoint == outPoint) { + std::swap(support, itQueue->second); + itQueueNameRow->second.erase(itQueueName); + itQueueRow->second.erase(itQueue); + return true; } } - if (itQueue != itQueueRow->second.end()) - { - std::swap(support, itQueue->second); - itQueueNameRow->second.erase(itQueueName); - itQueueRow->second.erase(itQueue); - return true; - } } LogPrintf("%s: An inconsistency was found in the claim queue. Please report this to the developers:\nFound in named support queue but not in height support queue: name: %s, txid: %s, nOut: %d, nValidAtHeight: %d, current height: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, itQueueName->nHeight, nCurrentHeight); return false; } -bool CClaimTrieCache::addSupport(const std::string& name, const COutPoint& outPoint, CAmount nAmount, uint160 supportedClaimId, int nHeight) const +bool CClaimTrieCache::addSupport(const std::string& name, const COutPoint& outPoint, const CAmount& nAmount, const uint160& supportedClaimId, int nHeight) { LogPrintf("%s: name: %s, txhash: %s, nOut: %d, nAmount: %d, supportedClaimId: %s, nHeight: %d, nCurrentHeight: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nAmount, supportedClaimId.GetHex(), nHeight, nCurrentHeight); assert(nHeight == nCurrentHeight); CClaimValue claim; int delayForSupport; - if (getOriginalInfoForName(name, claim) && claim.claimId == supportedClaimId) - { + if (getOriginalInfoForName(name, claim) && claim.claimId == supportedClaimId) { LogPrintf("%s: This is a support to a best claim.\n", __func__); delayForSupport = 0; - } - else - { + } else { delayForSupport = getDelayForName(name); } CSupportValue support(outPoint, supportedClaimId, nAmount, nHeight, nHeight + delayForSupport); return addSupportToQueues(name, support); } -bool CClaimTrieCache::undoSpendSupport(const std::string& name, const COutPoint& outPoint, uint160 supportedClaimId, CAmount nAmount, int nHeight, int nValidAtHeight) const +bool CClaimTrieCache::undoSpendSupport(const std::string& name, const COutPoint& outPoint, const uint160& supportedClaimId, const CAmount& nAmount, int nHeight, int nValidAtHeight) { LogPrintf("%s: name: %s, txhash: %s, nOut: %d, nAmount: %d, supportedClaimId: %s, nHeight: %d, nCurrentHeight: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nAmount, supportedClaimId.GetHex(), nHeight, nCurrentHeight); CSupportValue support(outPoint, supportedClaimId, nAmount, nHeight, nValidAtHeight); - if (nValidAtHeight < nCurrentHeight) - { + if (nValidAtHeight < nCurrentHeight) { nameOutPointType entry(name, support.outPoint); addSupportToExpirationQueue(support.nHeight + base->nExpirationTime, entry); return insertSupportIntoMap(name, support, false); - } - else - { + } else { return addSupportToQueues(name, support); } } -bool CClaimTrieCache::removeSupport(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight, bool fCheckTakeover) const +bool CClaimTrieCache::removeSupport(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight, bool fCheckTakeover) { bool removed = false; CSupportValue support; - if (removeSupportFromQueue(name, outPoint, support)) + if (removeSupportFromQueue(name, outPoint, support)) { removed = true; - if (removed == false && removeSupportFromMap(name, outPoint, support, fCheckTakeover)) + } + if (removed == false && removeSupportFromMap(name, outPoint, support, fCheckTakeover)) { removed = true; - if (removed) - { + } + if (removed) { int expirationHeight = nHeight + base->nExpirationTime; removeSupportFromExpirationQueue(name, outPoint, expirationHeight); nValidAtHeight = support.nValidAtHeight; @@ -1993,100 +1364,65 @@ bool CClaimTrieCache::removeSupport(const std::string& name, const COutPoint& ou return removed; } -void CClaimTrieCache::addSupportToExpirationQueue(int nExpirationHeight, nameOutPointType& entry) const +void CClaimTrieCache::addSupportToExpirationQueue(int nExpirationHeight, nameOutPointType& entry) { - expirationQueueType::iterator itQueueRow = getSupportExpirationQueueCacheRow(nExpirationHeight, true); + supportExpirationQueueType::iterator itQueueRow = getQueueCacheRow(nExpirationHeight, supportExpirationQueueCache, true); itQueueRow->second.push_back(entry); } -void CClaimTrieCache::removeSupportFromExpirationQueue(const std::string& name, const COutPoint& outPoint, int expirationHeight) const +void CClaimTrieCache::removeSupportFromExpirationQueue(const std::string& name, const COutPoint& outPoint, int expirationHeight) { - expirationQueueType::iterator itQueueRow = getSupportExpirationQueueCacheRow(expirationHeight, false); - expirationQueueRowType::iterator itQueue; - if (itQueueRow != supportExpirationQueueCache.end()) - { - for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) - { - if (name == itQueue->name && outPoint == itQueue->outPoint) + supportExpirationQueueType::iterator itQueueRow = getQueueCacheRow(expirationHeight, supportExpirationQueueCache, false); + supportExpirationQueueRowType::iterator itQueue; + if (itQueueRow != supportExpirationQueueCache.end()) { + for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) { + if (name == itQueue->name && outPoint == itQueue->outPoint) { + itQueueRow->second.erase(itQueue); break; + } } } - if (itQueue != itQueueRow->second.end()) - { - itQueueRow->second.erase(itQueue); - } } -expirationQueueType::iterator CClaimTrieCache::getSupportExpirationQueueCacheRow(int nHeight, bool createIfNotExists) const -{ - expirationQueueType::iterator itQueueRow = supportExpirationQueueCache.find(nHeight); - if (itQueueRow == supportExpirationQueueCache.end()) - { - // Have to make a new row it put in the cache, if createIfNotExists is true - expirationQueueRowType queueRow; - // If the row exists in the base, copy its claims into the new row. - bool exists = base->getSupportExpirationQueueRow(nHeight, queueRow); - if (!exists) - if (!createIfNotExists) - return itQueueRow; - // Stick the new row in the cache - std::pair ret; - ret = supportExpirationQueueCache.insert(std::pair(nHeight, queueRow)); - assert(ret.second); - itQueueRow = ret.first; - } - return itQueueRow; -} - -bool CClaimTrieCache::undoAddSupport(const std::string& name, const COutPoint& outPoint, int nHeight) const +bool CClaimTrieCache::undoAddSupport(const std::string& name, const COutPoint& outPoint, int nHeight) { LogPrintf("%s: name: %s, txhash: %s, nOut: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nHeight, nCurrentHeight); int throwaway; return removeSupport(name, outPoint, nHeight, throwaway, false); } -bool CClaimTrieCache::spendSupport(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight) const +bool CClaimTrieCache::spendSupport(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight) { LogPrintf("%s: name: %s, txhash: %s, nOut: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nHeight, nCurrentHeight); return removeSupport(name, outPoint, nHeight, nValidAtHeight, true); } -bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowType& expireUndo, insertUndoType& insertSupportUndo, supportQueueRowType& expireSupportUndo, std::vector >& takeoverHeightUndo) const +bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowType& expireUndo, insertUndoType& insertSupportUndo, supportQueueRowType& expireSupportUndo, std::vector >& takeoverHeightUndo) { LogPrintf("%s: nCurrentHeight (before increment): %d\n", __func__, nCurrentHeight); - claimQueueType::iterator itQueueRow = getQueueCacheRow(nCurrentHeight, false); - if (itQueueRow != claimQueueCache.end()) - { - for (claimQueueRowType::iterator itEntry = itQueueRow->second.begin(); itEntry != itQueueRow->second.end(); ++itEntry) - { + claimQueueType::iterator itQueueRow = getQueueCacheRow(nCurrentHeight, claimQueueCache, false); + if (itQueueRow != claimQueueCache.end()) { + for (claimQueueRowType::iterator itEntry = itQueueRow->second.begin(); itEntry != itQueueRow->second.end(); ++itEntry) { bool found = false; - queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(itEntry->first, false); - if (itQueueNameRow != claimQueueNameCache.end()) - { - for (queueNameRowType::iterator itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) - { - if (itQueueName->outPoint == itEntry->second.outPoint && itQueueName->nHeight == nCurrentHeight) - { + queueNameType::iterator itQueueNameRow = getQueueCacheRow(itEntry->first, claimQueueNameCache, false); + if (itQueueNameRow != claimQueueNameCache.end()) { + for (queueNameRowType::iterator itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) { + if (itQueueName->outPoint == itEntry->second.outPoint && itQueueName->nHeight == nCurrentHeight) { found = true; itQueueNameRow->second.erase(itQueueName); break; } } } - if (!found) - { + if (!found) { LogPrintf("%s: An inconsistency was found in the claim queue. Please report this to the developers:\nFound in height queue but not in named queue: name: %s, txid: %s, nOut: %d, nValidAtHeight: %d, current height: %d\n", __func__, itEntry->first, itEntry->second.outPoint.hash.GetHex(), itEntry->second.outPoint.n, itEntry->second.nValidAtHeight, nCurrentHeight); - if (itQueueNameRow != claimQueueNameCache.end()) - { + if (itQueueNameRow != claimQueueNameCache.end()) { LogPrintf("Claims found for that name:\n"); - for (queueNameRowType::iterator itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) - { + for (queueNameRowType::iterator itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) { LogPrintf("\ttxid: %s, nOut: %d, nValidAtHeight: %d\n", itQueueName->outPoint.hash.GetHex(), itQueueName->outPoint.n, itQueueName->nHeight); } - } - else - { + } else { LogPrintf("No claims found for that name\n"); } } @@ -2096,51 +1432,39 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy } itQueueRow->second.clear(); } - expirationQueueType::iterator itExpirationRow = getExpirationQueueCacheRow(nCurrentHeight, false); - if (itExpirationRow != expirationQueueCache.end()) - { - for (expirationQueueRowType::iterator itEntry = itExpirationRow->second.begin(); itEntry != itExpirationRow->second.end(); ++itEntry) - { + expirationQueueType::iterator itExpirationRow = getQueueCacheRow(nCurrentHeight, expirationQueueCache, false); + if (itExpirationRow != expirationQueueCache.end()) { + for (expirationQueueRowType::iterator itEntry = itExpirationRow->second.begin(); itEntry != itExpirationRow->second.end(); ++itEntry) { CClaimValue claim; assert(removeClaimFromTrie(itEntry->name, itEntry->outPoint, claim, true)); - claimsToDelete.insert(claim); + base->removeFromClaimIndex(claim); expireUndo.push_back(std::make_pair(itEntry->name, claim)); LogPrintf("Expiring claim %s: %s, nHeight: %d, nValidAtHeight: %d\n", claim.claimId.GetHex(), itEntry->name, claim.nHeight, claim.nValidAtHeight); } itExpirationRow->second.clear(); } - supportQueueType::iterator itSupportRow = getSupportQueueCacheRow(nCurrentHeight, false); - if (itSupportRow != supportQueueCache.end()) - { - for (supportQueueRowType::iterator itSupport = itSupportRow->second.begin(); itSupport != itSupportRow->second.end(); ++itSupport) - { + supportQueueType::iterator itSupportRow = getQueueCacheRow(nCurrentHeight, supportQueueCache, false); + if (itSupportRow != supportQueueCache.end()) { + for (supportQueueRowType::iterator itSupport = itSupportRow->second.begin(); itSupport != itSupportRow->second.end(); ++itSupport) { bool found = false; - queueNameType::iterator itSupportNameRow = getSupportQueueCacheNameRow(itSupport->first, false); - if (itSupportNameRow != supportQueueNameCache.end()) - { - for (queueNameRowType::iterator itSupportName = itSupportNameRow->second.begin(); itSupportName != itSupportNameRow->second.end(); ++itSupportName) - { - if (itSupportName->outPoint == itSupport->second.outPoint && itSupportName->nHeight == itSupport->second.nValidAtHeight) - { + supportQueueNameType::iterator itSupportNameRow = getQueueCacheRow(itSupport->first, supportQueueNameCache, false); + if (itSupportNameRow != supportQueueNameCache.end()) { + for (supportQueueNameRowType::iterator itSupportName = itSupportNameRow->second.begin(); itSupportName != itSupportNameRow->second.end(); ++itSupportName) { + if (itSupportName->outPoint == itSupport->second.outPoint && itSupportName->nHeight == itSupport->second.nValidAtHeight) { found = true; itSupportNameRow->second.erase(itSupportName); break; } } } - if (!found) - { + if (!found) { LogPrintf("%s: An inconsistency was found in the support queue. Please report this to the developers:\nFound in height queue but not in named queue: %s, txid: %s, nOut: %d, nValidAtHeight: %d, current height: %d\n", __func__, itSupport->first, itSupport->second.outPoint.hash.GetHex(), itSupport->second.outPoint.n, itSupport->second.nValidAtHeight, nCurrentHeight); - if (itSupportNameRow != supportQueueNameCache.end()) - { + if (itSupportNameRow != supportQueueNameCache.end()) { LogPrintf("Supports found for that name:\n"); - for (queueNameRowType::iterator itSupportName = itSupportNameRow->second.begin(); itSupportName != itSupportNameRow->second.end(); ++itSupportName) - { + for (supportQueueNameRowType::iterator itSupportName = itSupportNameRow->second.begin(); itSupportName != itSupportNameRow->second.end(); ++itSupportName) { LogPrintf("\ttxid: %s, nOut: %d, nValidAtHeight: %d\n", itSupportName->outPoint.hash.GetHex(), itSupportName->outPoint.n, itSupportName->nHeight); } - } - else - { + } else { LogPrintf("No support found for that name\n"); } } @@ -2149,11 +1473,9 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy } itSupportRow->second.clear(); } - expirationQueueType::iterator itSupportExpirationRow = getSupportExpirationQueueCacheRow(nCurrentHeight, false); - if (itSupportExpirationRow != supportExpirationQueueCache.end()) - { - for (expirationQueueRowType::iterator itEntry = itSupportExpirationRow->second.begin(); itEntry != itSupportExpirationRow->second.end(); ++itEntry) - { + supportExpirationQueueType::iterator itSupportExpirationRow = getQueueCacheRow(nCurrentHeight, supportExpirationQueueCache, false); + if (itSupportExpirationRow != supportExpirationQueueCache.end()) { + for (supportExpirationQueueRowType::iterator itEntry = itSupportExpirationRow->second.begin(); itEntry != itSupportExpirationRow->second.end(); ++itEntry) { CSupportValue support; assert(removeSupportFromMap(itEntry->name, itEntry->outPoint, support, true)); expireSupportUndo.push_back(std::make_pair(itEntry->name, support)); @@ -2168,8 +1490,7 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy // insertSupportUndo vectors, with the nValidAtHeight they had prior to // this block. // Run through all names that have been taken over - for (std::set::iterator itNamesToCheck = namesToCheckForTakeover.begin(); itNamesToCheck != namesToCheckForTakeover.end(); ++itNamesToCheck) - { + for (std::set::iterator itNamesToCheck = namesToCheckForTakeover.begin(); itNamesToCheck != namesToCheckForTakeover.end(); ++itNamesToCheck) { // Check if a takeover has occurred nodeCacheType::iterator itCachedNode = cache.find(*itNamesToCheck); // many possibilities @@ -2186,56 +1507,40 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy CClaimValue claimInTrie; bool haveClaimInCache; bool haveClaimInTrie; - if (itCachedNode == cache.end()) - { + if (itCachedNode == cache.end()) { haveClaimInCache = false; - } - else - { + } else { haveClaimInCache = itCachedNode->second->getBestClaim(claimInCache); } haveClaimInTrie = getOriginalInfoForName(*itNamesToCheck, claimInTrie); bool takeoverHappened = false; - if (!haveClaimInTrie) - { + if (!haveClaimInTrie) { takeoverHappened = true; - } - else if (!haveClaimInCache) - { + } else if (!haveClaimInCache) { takeoverHappened = true; - } - else if (claimInCache != claimInTrie) - { - if (claimInCache.claimId != claimInTrie.claimId) - { + } else if (claimInCache != claimInTrie) { + if (claimInCache.claimId != claimInTrie.claimId) { takeoverHappened = true; } } - if (takeoverHappened) - { - // Get all pending claims for that name and activate them all in the case that our winner is defunct. - queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(*itNamesToCheck, false); - if (itQueueNameRow != claimQueueNameCache.end()) - { - for (queueNameRowType::iterator itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) - { + if (takeoverHappened) { + // Get all claims in the queue for that name + queueNameType::iterator itQueueNameRow = getQueueCacheRow(*itNamesToCheck, claimQueueNameCache, false); + if (itQueueNameRow != claimQueueNameCache.end()) { + for (queueNameRowType::iterator itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) { bool found = false; // Pull those claims out of the height-based queue - claimQueueType::iterator itQueueRow = getQueueCacheRow(itQueueName->nHeight, false); + claimQueueType::iterator itQueueRow = getQueueCacheRow(itQueueName->nHeight, claimQueueCache, false); claimQueueRowType::iterator itQueue; - if (itQueueRow != claimQueueCache.end()) - { - for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) - { - if (*itNamesToCheck == itQueue->first && itQueue->second.outPoint == itQueueName->outPoint && itQueue->second.nValidAtHeight == itQueueName->nHeight) - { + if (itQueueRow != claimQueueCache.end()) { + for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) { + if (*itNamesToCheck == itQueue->first && itQueue->second.outPoint == itQueueName->outPoint && itQueue->second.nValidAtHeight == itQueueName->nHeight) { found = true; break; } } } - if (found) - { + if (found) { // Insert them into the queue undo with their previous nValidAtHeight insertUndo.push_back(nameOutPointHeightType(itQueue->first, itQueue->second.outPoint, itQueue->second.nValidAtHeight)); // Insert them into the name trie with the new nValidAtHeight @@ -2243,9 +1548,7 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy insertClaimIntoTrie(itQueue->first, itQueue->second, false); // Delete them from the height-based queue itQueueRow->second.erase(itQueue); - } - else - { + } else { LogPrintf("%s(): An inconsistency was found in the claim queue. Please report this to the developers:\nClaim found in name queue but not in height based queue:\nname: %s, txid: %s, nOut: %d, nValidAtHeight in name based queue: %d, current height: %d\n", __func__, *itNamesToCheck, itQueueName->outPoint.hash.GetHex(), itQueueName->outPoint.n, itQueueName->nHeight, nCurrentHeight); } assert(found); @@ -2255,25 +1558,17 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy } // // Then, get all supports in the queue for that name - queueNameType::iterator itSupportQueueNameRow = getSupportQueueCacheNameRow(*itNamesToCheck, false); - if (itSupportQueueNameRow != supportQueueNameCache.end()) - { - for (queueNameRowType::iterator itSupportQueueName = itSupportQueueNameRow->second.begin(); itSupportQueueName != itSupportQueueNameRow->second.end(); ++itSupportQueueName) - { + supportQueueNameType::iterator itSupportQueueNameRow = getQueueCacheRow(*itNamesToCheck, supportQueueNameCache, false); + if (itSupportQueueNameRow != supportQueueNameCache.end()) { + for (supportQueueNameRowType::iterator itSupportQueueName = itSupportQueueNameRow->second.begin(); itSupportQueueName != itSupportQueueNameRow->second.end(); ++itSupportQueueName) { // Pull those supports out of the height-based queue - supportQueueType::iterator itSupportQueueRow = getSupportQueueCacheRow(itSupportQueueName->nHeight, false); - if (itSupportQueueRow != supportQueueCache.end()) - { + supportQueueType::iterator itSupportQueueRow = getQueueCacheRow(itSupportQueueName->nHeight, supportQueueCache, false); + if (itSupportQueueRow != supportQueueCache.end()) { supportQueueRowType::iterator itSupportQueue; - for (itSupportQueue = itSupportQueueRow->second.begin(); itSupportQueue != itSupportQueueRow->second.end(); ++itSupportQueue) - { - if (*itNamesToCheck == itSupportQueue->first && itSupportQueue->second.outPoint == itSupportQueueName->outPoint && itSupportQueue->second.nValidAtHeight == itSupportQueueName->nHeight) - { - break; - } + for (itSupportQueue = itSupportQueueRow->second.begin(); itSupportQueue != itSupportQueueRow->second.end(); ++itSupportQueue) { + if (*itNamesToCheck == itSupportQueue->first && itSupportQueue->second.outPoint == itSupportQueueName->outPoint && itSupportQueue->second.nValidAtHeight == itSupportQueueName->nHeight) break; } - if (itSupportQueue != itSupportQueueRow->second.end()) - { + if (itSupportQueue != itSupportQueueRow->second.end()) { // Insert them into the support queue undo with the previous nValidAtHeight insertSupportUndo.push_back(nameOutPointHeightType(itSupportQueue->first, itSupportQueue->second.outPoint, itSupportQueue->second.nValidAtHeight)); // Insert them into the support map with the new nValidAtHeight @@ -2281,14 +1576,10 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy insertSupportIntoMap(itSupportQueue->first, itSupportQueue->second, false); // Delete them from the height-based queue itSupportQueueRow->second.erase(itSupportQueue); - } - else - { + } else { // here be problems TODO: show error, assert false } - } - else - { + } else { // here be problems } } @@ -2297,26 +1588,22 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy } // save the old last height so that it can be restored if the block is undone - if (haveClaimInTrie) - { + if (haveClaimInTrie) { int nHeightOfLastTakeover; assert(getLastTakeoverForName(*itNamesToCheck, nHeightOfLastTakeover)); takeoverHeightUndo.push_back(std::make_pair(*itNamesToCheck, nHeightOfLastTakeover)); } itCachedNode = cache.find(*itNamesToCheck); - if (itCachedNode != cache.end()) - { + if (itCachedNode != cache.end()) { cacheTakeoverHeights[*itNamesToCheck] = nCurrentHeight; } } } - for (nodeCacheType::const_iterator itOriginals = block_originals.begin(); itOriginals != block_originals.end(); ++itOriginals) - { + for (nodeCacheType::const_iterator itOriginals = block_originals.begin(); itOriginals != block_originals.end(); ++itOriginals) { delete itOriginals->second; } block_originals.clear(); - for (nodeCacheType::const_iterator itCache = cache.begin(); itCache != cache.end(); ++itCache) - { + for (nodeCacheType::const_iterator itCache = cache.begin(); itCache != cache.end(); ++itCache) { block_originals[itCache->first] = new CClaimTrieNode(*(itCache->second)); } namesToCheckForTakeover.clear(); @@ -2324,77 +1611,60 @@ bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowTy return true; } -bool CClaimTrieCache::decrementBlock(insertUndoType& insertUndo, claimQueueRowType& expireUndo, insertUndoType& insertSupportUndo, supportQueueRowType& expireSupportUndo, std::vector >& takeoverHeightUndo) const +bool CClaimTrieCache::decrementBlock(insertUndoType& insertUndo, claimQueueRowType& expireUndo, insertUndoType& insertSupportUndo, supportQueueRowType& expireSupportUndo, std::vector >& takeoverHeightUndo) { LogPrintf("%s: nCurrentHeight (before decrement): %d\n", __func__, nCurrentHeight); nCurrentHeight--; - if (expireSupportUndo.begin() != expireSupportUndo.end()) - { - expirationQueueType::iterator itSupportExpireRow = getSupportExpirationQueueCacheRow(nCurrentHeight, true); - for (supportQueueRowType::iterator itSupportExpireUndo = expireSupportUndo.begin(); itSupportExpireUndo != expireSupportUndo.end(); ++itSupportExpireUndo) - { + if (expireSupportUndo.begin() != expireSupportUndo.end()) { + supportExpirationQueueType::iterator itSupportExpireRow = getQueueCacheRow(nCurrentHeight, supportExpirationQueueCache, true); + for (supportQueueRowType::iterator itSupportExpireUndo = expireSupportUndo.begin(); itSupportExpireUndo != expireSupportUndo.end(); ++itSupportExpireUndo) { insertSupportIntoMap(itSupportExpireUndo->first, itSupportExpireUndo->second, false); itSupportExpireRow->second.push_back(nameOutPointType(itSupportExpireUndo->first, itSupportExpireUndo->second.outPoint)); } } - for (insertUndoType::iterator itSupportUndo = insertSupportUndo.begin(); itSupportUndo != insertSupportUndo.end(); ++itSupportUndo) - { - supportQueueType::iterator itSupportRow = getSupportQueueCacheRow(itSupportUndo->nHeight, true); + for (insertUndoType::iterator itSupportUndo = insertSupportUndo.begin(); itSupportUndo != insertSupportUndo.end(); ++itSupportUndo) { + supportQueueType::iterator itSupportRow = getQueueCacheRow(itSupportUndo->nHeight, supportQueueCache, true); CSupportValue support; assert(removeSupportFromMap(itSupportUndo->name, itSupportUndo->outPoint, support, false)); - // support.nValidHeight may have been changed if this was inserted before activation height - // due to a triggered takeover, change it back to original nValidAtHeight - support.nValidAtHeight = itSupportUndo->nHeight; - queueNameType::iterator itSupportNameRow = getSupportQueueCacheNameRow(itSupportUndo->name, true); + supportQueueNameType::iterator itSupportNameRow = getQueueCacheRow(itSupportUndo->name, supportQueueNameCache, true); itSupportRow->second.push_back(std::make_pair(itSupportUndo->name, support)); itSupportNameRow->second.push_back(outPointHeightType(support.outPoint, support.nValidAtHeight)); } - if (expireUndo.begin() != expireUndo.end()) - { - expirationQueueType::iterator itExpireRow = getExpirationQueueCacheRow(nCurrentHeight, true); - for (claimQueueRowType::iterator itExpireUndo = expireUndo.begin(); itExpireUndo != expireUndo.end(); ++itExpireUndo) - { + if (expireUndo.begin() != expireUndo.end()) { + expirationQueueType::iterator itExpireRow = getQueueCacheRow(nCurrentHeight, expirationQueueCache, true); + for (claimQueueRowType::iterator itExpireUndo = expireUndo.begin(); itExpireUndo != expireUndo.end(); ++itExpireUndo) { insertClaimIntoTrie(itExpireUndo->first, itExpireUndo->second, false); - CClaimIndexElement element = {itExpireUndo->first, itExpireUndo->second}; - claimsToAdd.push_back(element); + base->addToClaimIndex(itExpireUndo->first, itExpireUndo->second); itExpireRow->second.push_back(nameOutPointType(itExpireUndo->first, itExpireUndo->second.outPoint)); } } - for (insertUndoType::iterator itInsertUndo = insertUndo.begin(); itInsertUndo != insertUndo.end(); ++itInsertUndo) - { - claimQueueType::iterator itQueueRow = getQueueCacheRow(itInsertUndo->nHeight, true); - + for (insertUndoType::iterator itInsertUndo = insertUndo.begin(); itInsertUndo != insertUndo.end(); ++itInsertUndo) { + claimQueueType::iterator itQueueRow = getQueueCacheRow(itInsertUndo->nHeight, claimQueueCache, true); CClaimValue claim; assert(removeClaimFromTrie(itInsertUndo->name, itInsertUndo->outPoint, claim, false)); - // claim.nValidHeight may have been changed if this was inserted before activation height - // due to a triggered takeover, change it back to original nValidAtHeight - claim.nValidAtHeight = itInsertUndo->nHeight; - queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(itInsertUndo->name, true); + queueNameType::iterator itQueueNameRow = getQueueCacheRow(itInsertUndo->name, claimQueueNameCache, true); itQueueRow->second.push_back(std::make_pair(itInsertUndo->name, claim)); - itQueueNameRow->second.push_back(outPointHeightType(itInsertUndo->outPoint, claim.nValidAtHeight)); + itQueueNameRow->second.push_back(outPointHeightType(itInsertUndo->outPoint, itInsertUndo->nHeight)); } - for (std::vector >::iterator itTakeoverHeightUndo = takeoverHeightUndo.begin(); itTakeoverHeightUndo != takeoverHeightUndo.end(); ++itTakeoverHeightUndo) - { + for (std::vector >::iterator itTakeoverHeightUndo = takeoverHeightUndo.begin(); itTakeoverHeightUndo != takeoverHeightUndo.end(); ++itTakeoverHeightUndo) { cacheTakeoverHeights[itTakeoverHeightUndo->first] = itTakeoverHeightUndo->second; } return true; } -bool CClaimTrieCache::finalizeDecrement() const +bool CClaimTrieCache::finalizeDecrement() { - for (nodeCacheType::iterator itOriginals = block_originals.begin(); itOriginals != block_originals.end(); ++itOriginals) - { + for (nodeCacheType::iterator itOriginals = block_originals.begin(); itOriginals != block_originals.end(); ++itOriginals) { delete itOriginals->second; } block_originals.clear(); - for (nodeCacheType::const_iterator itCache = cache.begin(); itCache != cache.end(); ++itCache) - { + for (nodeCacheType::const_iterator itCache = cache.begin(); itCache != cache.end(); ++itCache) { block_originals[itCache->first] = new CClaimTrieNode(*(itCache->second)); } return true; @@ -2402,14 +1672,12 @@ bool CClaimTrieCache::finalizeDecrement() const bool CClaimTrieCache::getLastTakeoverForName(const std::string& name, int& nLastTakeoverForName) const { - if (!fRequireTakeoverHeights) - { + if (!fRequireTakeoverHeights) { nLastTakeoverForName = 0; return true; } - std::map::iterator itHeights = cacheTakeoverHeights.find(name); - if (itHeights == cacheTakeoverHeights.end()) - { + std::map::const_iterator itHeights = cacheTakeoverHeights.find(name); + if (itHeights == cacheTakeoverHeights.end()) { return base->getLastTakeoverForName(name, nLastTakeoverForName); } nLastTakeoverForName = itHeights->second; @@ -2417,15 +1685,6 @@ bool CClaimTrieCache::getLastTakeoverForName(const std::string& name, int& nLast } int CClaimTrieCache::getNumBlocksOfContinuousOwnership(const std::string& name) const -{ - const CClaimTrieNode* node = getNodeForName(name); - if (!node || node->claims.empty()) return 0; - int nLastTakeoverHeight; - assert(getLastTakeoverForName(name, nLastTakeoverHeight)); - return nCurrentHeight - nLastTakeoverHeight; -} - -const CClaimTrieNode* CClaimTrieCache::getNodeForName(const std::string& name) const { const CClaimTrieNode* node = NULL; nodeCacheType::const_iterator itCache = cache.find(name); @@ -2435,24 +1694,23 @@ const CClaimTrieNode* CClaimTrieCache::getNodeForName(const std::string& name) c if (!node) { node = base->getNodeForName(name); } - return node; + if (!node || node->claims.empty()) { + return 0; + } + int nLastTakeoverHeight; + assert(getLastTakeoverForName(name, nLastTakeoverHeight)); + return nCurrentHeight - nLastTakeoverHeight; } int CClaimTrieCache::getDelayForName(const std::string& name) const { - if (!fRequireTakeoverHeights) - { - return 0; - } + if (!fRequireTakeoverHeights) return 0; int nBlocksOfContinuousOwnership = getNumBlocksOfContinuousOwnership(name); return std::min(nBlocksOfContinuousOwnership / base->nProportionalDelayFactor, 4032); } -uint256 CClaimTrieCache::getBestBlock() +uint256 CClaimTrieCache::getBestBlock() const { - if (hashBlock.IsNull()) - if (base != NULL) - hashBlock = base->hashBlock; return hashBlock; } @@ -2461,15 +1719,13 @@ void CClaimTrieCache::setBestBlock(const uint256& hashBlockIn) hashBlock = hashBlockIn; } -bool CClaimTrieCache::clear() const +bool CClaimTrieCache::clear() { - for (nodeCacheType::iterator itcache = cache.begin(); itcache != cache.end(); ++itcache) - { + for (nodeCacheType::iterator itcache = cache.begin(); itcache != cache.end(); ++itcache) { delete itcache->second; } cache.clear(); - for (nodeCacheType::iterator itOriginals = block_originals.begin(); itOriginals != block_originals.end(); ++itOriginals) - { + for (nodeCacheType::iterator itOriginals = block_originals.begin(); itOriginals != block_originals.end(); ++itOriginals) { delete itOriginals->second; } block_originals.clear(); @@ -2487,217 +1743,104 @@ bool CClaimTrieCache::clear() const return true; } +template +void CClaimTrieCache::update(std::map& map) +{ + for (typename std::map::iterator itQueue = map.begin(); itQueue != map.end(); ++itQueue) { + base->db.updateQueueRow(itQueue->first, itQueue->second); + } +} + bool CClaimTrieCache::flush() { - if (dirty()) - getMerkleHash(); + if (dirty()) getMerkleHash(); + for (nodeCacheType::iterator itcache = cache.begin(); itcache != cache.end(); ++itcache) { + if (!base->updateName(itcache->first, itcache->second)) { + LogPrintf("%s: Failed to update name for:%s\n", __func__, itcache->first); + return false; + } + } + for (hashMapType::iterator ithash = cacheHashes.begin(); ithash != cacheHashes.end(); ++ithash) { + if (!base->updateHash(ithash->first, ithash->second)) { + LogPrintf("%s: Failed to update hash for:%s\n", __func__, ithash->first); + return false; + } + } + for (std::map::iterator itheight = cacheTakeoverHeights.begin(); itheight != cacheTakeoverHeights.end(); ++itheight) { + if (!base->updateTakeoverHeight(itheight->first, itheight->second)) { + LogPrintf("%s: Failed to update takeover height for:%s\n", __func__, itheight->first); + return false; + } + } + update(claimQueueCache); + update(claimQueueNameCache); + update(expirationQueueCache); + update(supportCache); + update(supportQueueCache); + update(supportQueueNameCache); + update(supportExpirationQueueCache); + base->hashBlock = getBestBlock(); + base->nCurrentHeight = nCurrentHeight; + return clear(); +} - if (!claimsToDelete.empty()) { - for (claimIndexClaimListType::iterator it = claimsToDelete.begin(); it != claimsToDelete.end(); ++it) - base->removeFromClaimIndex(*it); - claimsToDelete.clear(); - } - if (!claimsToAdd.empty()) { - for (claimIndexElementListType::iterator it = claimsToAdd.begin(); it != claimsToAdd.end(); ++it) - base->addToClaimIndex(it->name, it->claim); - claimsToAdd.clear(); - } - - bool success = base->update(cache, cacheHashes, cacheTakeoverHeights, getBestBlock(), claimQueueCache, claimQueueNameCache, expirationQueueCache, nCurrentHeight, supportCache, supportQueueCache, supportQueueNameCache, supportExpirationQueueCache); - if (success) - { - success = clear(); - } - return success; +bool CClaimTrieCache::dirty() const +{ + return !dirtyHashes.empty(); } uint256 CClaimTrieCache::getLeafHashForProof(const std::string& currentPosition, unsigned char nodeChar, const CClaimTrieNode* currentNode) const { std::stringstream leafPosition; leafPosition << currentPosition << nodeChar; - hashMapType::iterator cachedHash = cacheHashes.find(leafPosition.str()); - if (cachedHash != cacheHashes.end()) - { + hashMapType::const_iterator cachedHash = cacheHashes.find(leafPosition.str()); + if (cachedHash != cacheHashes.end()) { return cachedHash->second; - } - else - { + } else { return currentNode->hash; } } -void CClaimTrieCache::recursiveIterateTrie(std::string& name, const CClaimTrieNode* current, CNodeCallback& callback) const +CClaimTrieProof CClaimTrieCache::getProofForName(const std::string& name) const { - callback.visit(name, current); - - nodeCacheType::const_iterator cachedNode; - for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) { - name.push_back(it->first); - cachedNode = cache.find(name); - if (cachedNode != cache.end()) - recursiveIterateTrie(name, cachedNode->second, callback); - else - recursiveIterateTrie(name, it->second, callback); - name.erase(name.end() - 1); - } -} - -bool CClaimTrieCache::iterateTrie(CNodeCallback& callback) const -{ - try { - std::string name; - recursiveIterateTrie(name, getRoot(), callback); - assert(name.empty()); - } catch (const CNodeCallback::CRecursionInterruptionException& ex) { - return ex.success; - } - return true; -} - -claimsForNameType CClaimTrieCache::getClaimsForName(const std::string& name) const -{ - int nLastTakeoverHeight = 0; - std::vector claims; - if (const CClaimTrieNode* node = getNodeForName(name)) { - claims = node->claims; - getLastTakeoverForName(name, nLastTakeoverHeight); - } - supportMapEntryType supports; - getSupportsForName(name, supports); - queueNameType::const_iterator itQueueNameCache = getQueueCacheNameRow(name, false); - if (itQueueNameCache != claimQueueNameCache.end()) { - const queueNameRowType& namedClaimRow = itQueueNameCache->second; - for (queueNameRowType::const_iterator itClaimsForName = namedClaimRow.begin(); itClaimsForName != namedClaimRow.end(); ++itClaimsForName) { - claimQueueType::const_iterator itQueueCache = getQueueCacheRow(itClaimsForName->nHeight, false); - if (itQueueCache != claimQueueCache.end()) { - const claimQueueRowType& claimRow = itQueueCache->second; - for (claimQueueRowType::const_iterator itClaimRow = claimRow.begin(); itClaimRow != claimRow.end(); ++itClaimRow) { - if (itClaimRow->first == name && itClaimRow->second.outPoint == itClaimsForName->outPoint) { - claims.push_back(itClaimRow->second); - break; - } - } - } - } - } - queueNameType::const_iterator itSupportQueueNameCache = getSupportQueueCacheNameRow(name, false); - if (itSupportQueueNameCache != supportQueueNameCache.end()) { - const queueNameRowType& namedSupportRow = itSupportQueueNameCache->second; - for (queueNameRowType::const_iterator itSupportsForName = namedSupportRow.begin(); itSupportsForName != namedSupportRow.end(); ++itSupportsForName) { - supportQueueType::const_iterator itSupportQueueCache = getSupportQueueCacheRow(itSupportsForName->nHeight, false); - if (itSupportQueueCache != supportQueueCache.end()) { - const supportQueueRowType& supportRow = itSupportQueueCache->second; - for (supportQueueRowType::const_iterator itSupportRow = supportRow.begin(); itSupportRow != supportRow.end(); ++itSupportRow) { - if (itSupportRow->first == name && itSupportRow->second.outPoint == itSupportsForName->outPoint) { - supports.push_back(itSupportRow->second); - break; - } - } - } - } - } - return claimsForNameType(claims, supports, nLastTakeoverHeight); -} - -CAmount CClaimTrieCache::getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector* supports) const -{ - return getEffectiveAmountForClaim(getClaimsForName(name), claimId, supports); -} - -CAmount CClaimTrieCache::getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector* supports) const -{ - CAmount effectiveAmount = 0; - for (std::vector::const_iterator it = claims.claims.begin(); it != claims.claims.end(); ++it) { - if (it->claimId == claimId && it->nValidAtHeight < nCurrentHeight) { - effectiveAmount += it->nAmount; - for (std::vector::const_iterator it = claims.supports.begin(); it != claims.supports.end(); ++it) { - if (it->supportedClaimId == claimId && it->nValidAtHeight < nCurrentHeight) { - effectiveAmount += it->nAmount; - if (supports) supports->push_back(*it); - } - } - break; - } - } - return effectiveAmount; -} - -bool CClaimTrieCache::getInfoForName(const std::string& name, CClaimValue& claim) const -{ - if (dirty()) - getMerkleHash(); - - CClaimTrieNode* current = getRoot(); - nodeCacheType::const_iterator cachedNode; - - for (std::string::const_iterator itName = name.begin(); current; ++itName) { - std::string currentPosition(name.begin(), itName); - cachedNode = cache.find(currentPosition); - if (cachedNode != cache.end()) - current = cachedNode->second; - - if (itName == name.end()) - return current->getBestClaim(claim); - - nodeMapType::const_iterator itChildren = current->children.find(*itName); - if (itChildren != current->children.end()) { - current = itChildren->second; - } - } - return false; -} - -bool CClaimTrieCache::getProofForName(const std::string& name, CClaimTrieProof& proof) const -{ - if (dirty()) - getMerkleHash(); - + if (dirty()) getMerkleHash(); std::vector nodes; - CClaimTrieNode* current = getRoot(); + CClaimTrieNode* current = &(base->root); nodeCacheType::const_iterator cachedNode; bool fNameHasValue = false; COutPoint outPoint; int nHeightOfLastTakeover = 0; - for (std::string::const_iterator itName = name.begin(); current; ++itName) - { + for (std::string::const_iterator itName = name.begin(); current; ++itName) { std::string currentPosition(name.begin(), itName); cachedNode = cache.find(currentPosition); - if (cachedNode != cache.end()) + if (cachedNode != cache.end()) { current = cachedNode->second; + } CClaimValue claim; bool fNodeHasValue = current->getBestClaim(claim); uint256 valueHash; - if (fNodeHasValue) - { + if (fNodeHasValue) { int nHeightOfLastTakeover; - if (!getLastTakeoverForName(currentPosition, nHeightOfLastTakeover)) - return false; + assert(getLastTakeoverForName(currentPosition, nHeightOfLastTakeover)); valueHash = getValueHash(claim.outPoint, nHeightOfLastTakeover); } std::vector > children; CClaimTrieNode* nextCurrent = NULL; - for (nodeMapType::const_iterator itChildren = current->children.begin(); itChildren != current->children.end(); ++itChildren) - { - if (itName == name.end() || itChildren->first != *itName) // Leaf node - { + for (nodeMapType::const_iterator itChildren = current->children.begin(); itChildren != current->children.end(); ++itChildren) { + if (itName == name.end() || itChildren->first != *itName) { // Leaf node uint256 childHash = getLeafHashForProof(currentPosition, itChildren->first, itChildren->second); children.push_back(std::make_pair(itChildren->first, childHash)); - } - else // Full node - { + } else { // Full node nextCurrent = itChildren->second; uint256 childHash; children.push_back(std::make_pair(itChildren->first, childHash)); } } - if (currentPosition == name) - { + if (currentPosition == name) { fNameHasValue = fNodeHasValue; - if (fNameHasValue) - { + if (fNameHasValue) { outPoint = claim.outPoint; - if (!getLastTakeoverForName(name, nHeightOfLastTakeover)) - return false; + assert(getLastTakeoverForName(name, nHeightOfLastTakeover)); } valueHash.SetNull(); } @@ -2705,15 +1848,12 @@ bool CClaimTrieCache::getProofForName(const std::string& name, CClaimTrieProof& nodes.push_back(node); current = nextCurrent; } - proof = CClaimTrieProof(nodes, fNameHasValue, outPoint, nHeightOfLastTakeover); - return true; + return CClaimTrieProof(nodes, fNameHasValue, outPoint, nHeightOfLastTakeover); } - -void CClaimTrieCache::removeAndAddToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const +void CClaimTrieCache::removeAndAddToExpirationQueue(expirationQueueRowType& row, int height, bool increment) { - for (expirationQueueRowType::iterator e = row.begin(); e != row.end(); ++e) - { + for (expirationQueueRowType::iterator e = row.begin(); e != row.end(); ++e) { // remove and insert with new expiration time removeFromExpirationQueue(e->name, e->outPoint, height); int extend_expiration = Params().GetConsensus().nExtendedClaimExpirationTime - Params().GetConsensus().nOriginalClaimExpirationTime; @@ -2721,13 +1861,11 @@ void CClaimTrieCache::removeAndAddToExpirationQueue(expirationQueueRowType &row, nameOutPointType entry(e->name, e->outPoint); addToExpirationQueue(new_expiration_height, entry); } - } -void CClaimTrieCache::removeAndAddSupportToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const +void CClaimTrieCache::removeAndAddSupportToExpirationQueue(supportExpirationQueueRowType& row, int height, bool increment) { - for (expirationQueueRowType::iterator e = row.begin(); e != row.end(); ++e) - { + for (supportExpirationQueueRowType::iterator e = row.begin(); e != row.end(); ++e) { // remove and insert with new expiration time removeSupportFromExpirationQueue(e->name, e->outPoint, height); int extend_expiration = Params().GetConsensus().nExtendedClaimExpirationTime - Params().GetConsensus().nOriginalClaimExpirationTime; @@ -2735,10 +1873,9 @@ void CClaimTrieCache::removeAndAddSupportToExpirationQueue(expirationQueueRowTyp nameOutPointType entry(e->name, e->outPoint); addSupportToExpirationQueue(new_expiration_height, entry); } - } -bool CClaimTrieCache::forkForExpirationChange(bool increment) const +bool CClaimTrieCache::forkForExpirationChange(bool increment) { /* If increment is True, we have forked to extend the expiration time, thus items in the expiration queue @@ -2748,66 +1885,27 @@ bool CClaimTrieCache::forkForExpirationChange(bool increment) const will have their expiration extension removed. */ - // look through dirty expiration queues - std::set dirtyHeights; - for (expirationQueueType::const_iterator i = base->dirtyExpirationQueueRows.begin(); i != base->dirtyExpirationQueueRows.end(); ++i) - { + expirationQueueType dirtyExpirationQueueRows; + if (!base->db.getQueueMap(dirtyExpirationQueueRows)) { + return error("%s(): error reading expiration queue rows from disk", __func__); + } + + supportExpirationQueueType dirtySupportExpirationQueueRows; + if (!base->db.getQueueMap(dirtySupportExpirationQueueRows)) { + return error("%s(): error reading support expiration queue rows from disk", __func__); + } + + for (expirationQueueType::const_iterator i = dirtyExpirationQueueRows.begin(); i != dirtyExpirationQueueRows.end(); ++i) { int height = i->first; - dirtyHeights.insert(height); expirationQueueRowType row = i->second; removeAndAddToExpirationQueue(row, height, increment); } - std::set dirtySupportHeights; - for (expirationQueueType::const_iterator i = base->dirtySupportExpirationQueueRows.begin(); i != base->dirtySupportExpirationQueueRows.end(); ++i) - { + for (supportExpirationQueueType::const_iterator i = dirtySupportExpirationQueueRows.begin(); i != dirtySupportExpirationQueueRows.end(); ++i) { int height = i->first; - dirtySupportHeights.insert(height); - expirationQueueRowType row = i->second; + supportExpirationQueueRowType row = i->second; removeAndAddSupportToExpirationQueue(row, height, increment); } - - //look through db for expiration queues, if we haven't already found it in dirty expiration queue - boost::scoped_ptr pcursor(const_cast(&base->db)->NewIterator()); - pcursor->SeekToFirst(); - while (pcursor->Valid()) - { - std::pair key; - if (pcursor->GetKey(key)) - { - int height = key.second; - // if we've looked through this in dirtyExprirationQueueRows, don't use it - // because its stale - if ((key.first == EXP_QUEUE_ROW) & (dirtyHeights.count(height) == 0)) - { - expirationQueueRowType row; - if (pcursor->GetValue(row)) - { - removeAndAddToExpirationQueue(row, height, increment); - } - else - { - return error("%s(): error reading expiration queue rows from disk", __func__); - } - } - else if ((key.first == SUPPORT_EXP_QUEUE_ROW) & (dirtySupportHeights.count(height) == 0)) - { - expirationQueueRowType row; - if (pcursor->GetValue(row)) - { - removeAndAddSupportToExpirationQueue(row, height, increment); - } - else - { - return error("%s(): error reading support expiration queue rows from disk", __func__); - } - } - - } - pcursor->Next(); - } - return true; } - diff --git a/src/claimtrie.h b/src/claimtrie.h index d192cf6f6..a7ac02748 100644 --- a/src/claimtrie.h +++ b/src/claimtrie.h @@ -2,55 +2,35 @@ #define BITCOIN_CLAIMTRIE_H #include "amount.h" +#include "chainparams.h" +#include "claimtriedb.h" +#include "primitives/transaction.h" #include "serialize.h" #include "uint256.h" #include "util.h" -#include "dbwrapper.h" -#include "chainparams.h" -#include "primitives/transaction.h" #include #include -#include -// leveldb keys -#define HASH_BLOCK 'h' -#define CURRENT_HEIGHT 't' -#define TRIE_NODE 'n' -#define CLAIM_BY_ID 'i' -#define CLAIM_QUEUE_ROW 'r' -#define CLAIM_QUEUE_NAME_ROW 'm' -#define EXP_QUEUE_ROW 'e' -#define SUPPORT 's' -#define SUPPORT_QUEUE_ROW 'u' -#define SUPPORT_QUEUE_NAME_ROW 'p' -#define SUPPORT_EXP_QUEUE_ROW 'x' - -uint256 getValueHash(COutPoint outPoint, int nHeightOfLastTakeover); +uint256 getValueHash(const COutPoint& outPoint, int nHeightOfLastTakeover); class CClaimValue { public: - COutPoint outPoint; - uint160 claimId; - CAmount nAmount; - CAmount nEffectiveAmount; - int nHeight; - int nValidAtHeight; + CClaimValue() + { + } - CClaimValue() {}; - - CClaimValue(COutPoint outPoint, uint160 claimId, CAmount nAmount, int nHeight, - int nValidAtHeight) - : outPoint(outPoint), claimId(claimId) - , nAmount(nAmount), nEffectiveAmount(nAmount) - , nHeight(nHeight), nValidAtHeight(nValidAtHeight) - {} + CClaimValue(const COutPoint& outPoint, const uint160& claimId, const CAmount& nAmount, const int nHeight, const int nValidAtHeight) + : outPoint(outPoint), claimId(claimId), nAmount(nAmount), nEffectiveAmount(nAmount), nHeight(nHeight), nValidAtHeight(nValidAtHeight) + { + } ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + { READWRITE(outPoint); READWRITE(claimId); READWRITE(nAmount); @@ -60,16 +40,15 @@ public: bool operator<(const CClaimValue& other) const { - if (nEffectiveAmount < other.nEffectiveAmount) + if (nEffectiveAmount < other.nEffectiveAmount) { return true; - else if (nEffectiveAmount == other.nEffectiveAmount) - { - if (nHeight > other.nHeight) + } else if (nEffectiveAmount == other.nEffectiveAmount) { + if (nHeight > other.nHeight) { return true; - else if (nHeight == other.nHeight) - { - if (outPoint != other.outPoint && !(outPoint < other.outPoint)) + } else if (nHeight == other.nHeight) { + if (outPoint != other.outPoint && !(outPoint < other.outPoint)) { return true; + } } } return false; @@ -84,29 +63,36 @@ public: { return !(*this == other); } + + COutPoint outPoint; + uint160 claimId; + CAmount nAmount; + CAmount nEffectiveAmount; + int nHeight; + int nValidAtHeight; }; class CSupportValue { public: - COutPoint outPoint; - uint160 supportedClaimId; - CAmount nAmount; - int nHeight; - int nValidAtHeight; + CSupportValue() + { + } - CSupportValue() {}; - CSupportValue(COutPoint outPoint, uint160 supportedClaimId, - CAmount nAmount, int nHeight, int nValidAtHeight) - : outPoint(outPoint), supportedClaimId(supportedClaimId) - , nAmount(nAmount), nHeight(nHeight) - , nValidAtHeight(nValidAtHeight) - {} + CSupportValue(const COutPoint& outPoint, + const uint160& supportedClaimId, + const CAmount& nAmount, + const int nHeight, + const int nValidAtHeight) + : outPoint(outPoint), supportedClaimId(supportedClaimId), nAmount(nAmount), nHeight(nHeight), nValidAtHeight(nValidAtHeight) + { + } ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + { READWRITE(outPoint); READWRITE(supportedClaimId); READWRITE(nAmount); @@ -123,6 +109,12 @@ public: { return !(*this == other); } + + COutPoint outPoint; + uint160 supportedClaimId; + CAmount nAmount; + int nHeight; + int nValidAtHeight; }; class CClaimTrieNode; @@ -132,27 +124,36 @@ typedef std::vector supportMapEntryType; typedef std::map nodeMapType; +typedef std::pair namedNodeType; + class CClaimTrieNode { public: - CClaimTrieNode() : nHeightOfLastTakeover(0) {} - CClaimTrieNode(uint256 hash) : hash(hash), nHeightOfLastTakeover(0) {} - uint256 hash; - nodeMapType children; - int nHeightOfLastTakeover; - std::vector claims; + CClaimTrieNode() : nHeightOfLastTakeover(0) + { + } + + CClaimTrieNode(const uint256& hash) : hash(hash), nHeightOfLastTakeover(0) + { + } + + bool insertClaim(const CClaimValue& claim); - bool insertClaim(CClaimValue claim); bool removeClaim(const COutPoint& outPoint, CClaimValue& claim); + bool getBestClaim(CClaimValue& claim) const; - bool empty() const {return children.empty() && claims.empty();} + + bool empty() const; + bool haveClaim(const COutPoint& outPoint) const; + void reorderClaims(supportMapEntryType& supports); ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + { READWRITE(hash); READWRITE(claims); READWRITE(nHeightOfLastTakeover); @@ -167,27 +168,37 @@ public: { return !(*this == other); } + + uint256 hash; + nodeMapType children; + int nHeightOfLastTakeover; + std::vector claims; }; -struct nodenamecompare +class nodeNameCompare { - bool operator() (const std::string& i, const std::string& j) const +public: + bool operator()(const std::string& i, const std::string& j) const { - if (i.size() == j.size()) + if (i.size() == j.size()) { return i < j; + } return i.size() < j.size(); } }; -struct outPointHeightType +class outPointHeightType { - COutPoint outPoint; - int nHeight; +public: + outPointHeightType() + { + } - outPointHeightType() {} - - outPointHeightType(COutPoint outPoint, int nHeight) - : outPoint(outPoint), nHeight(nHeight) {} + outPointHeightType(const COutPoint& outPoint, + const int nHeight) + : outPoint(outPoint), nHeight(nHeight) + { + } ADD_SERIALIZE_METHODS; @@ -198,18 +209,22 @@ struct outPointHeightType READWRITE(nHeight); } -}; - -struct nameOutPointHeightType -{ - std::string name; COutPoint outPoint; int nHeight; +}; - nameOutPointHeightType() {} +class nameOutPointHeightType +{ +public: + nameOutPointHeightType() + { + } + + nameOutPointHeightType(const std::string& name, const COutPoint& outPoint, const int nHeight) + : name(name), outPoint(outPoint), nHeight(nHeight) + { + } - nameOutPointHeightType(std::string name, COutPoint outPoint, int nHeight) - : name(name), outPoint(outPoint), nHeight(nHeight) {} ADD_SERIALIZE_METHODS; template @@ -219,17 +234,23 @@ struct nameOutPointHeightType READWRITE(outPoint); READWRITE(nHeight); } -}; -struct nameOutPointType -{ std::string name; COutPoint outPoint; + int nHeight; +}; - nameOutPointType() {} +class nameOutPointType +{ +public: + nameOutPointType() + { + } - nameOutPointType(std::string name, COutPoint outPoint) - : name(name), outPoint(outPoint) {} + nameOutPointType(const std::string& name, const COutPoint& outPoint) + : name(name), outPoint(outPoint) + { + } ADD_SERIALIZE_METHODS; @@ -239,58 +260,129 @@ struct nameOutPointType READWRITE(name); READWRITE(outPoint); } + + std::string name; + COutPoint outPoint; }; class CClaimIndexElement { - public: +public: ADD_SERIALIZE_METHODS; template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) + { READWRITE(name); READWRITE(claim); } + bool empty() const + { + return name.empty() && claim.claimId.IsNull(); + } + std::string name; CClaimValue claim; }; -typedef std::pair claimQueueEntryType; +// Helpers to separate queue types from each other +class claimQueueEntryHelper; +class supportQueueEntryHelper; -typedef std::pair supportQueueEntryType; +class queueNameRowHelper; +class supportQueueNameRowHelper; + +class expirationQueueRowHelper; +class supportExpirationQueueRowHelper; + +template +class CGeneric : public Base +{ +public: + CGeneric() : Base() + { + } + + CGeneric(const Base& base) : Base(base) + { + } + + CGeneric(const CGeneric& CGeneric) : Base(CGeneric) + { + } +}; + +// Make std::swap to work with custom types +namespace std { +template +inline void swap(CGeneric& CGeneric, Base& base) +{ + Base base1 = CGeneric; + CGeneric = base; + base = base1; +} + +template +inline void swap(Base& base, CGeneric& CGeneric) +{ + swap(CGeneric, base); +} +} // namespace std + +// Each of these CGeneric types will be stored in the database +typedef CGeneric claimQueueValueType; +typedef CGeneric supportQueueValueType; + +typedef CGeneric queueNameRowValueType; +typedef CGeneric supportQueueNameRowValueType; + +typedef CGeneric expirationQueueRowValueType; +typedef CGeneric supportExpirationQueueRowValueType; + +typedef std::pair claimQueueEntryType; + +typedef std::pair supportQueueEntryType; typedef std::map supportMapType; -typedef std::vector queueNameRowType; +typedef std::vector queueNameRowType; typedef std::map queueNameType; +typedef std::vector supportQueueNameRowType; +typedef std::map supportQueueNameType; + typedef std::vector insertUndoType; -typedef std::vector expirationQueueRowType; +typedef std::vector expirationQueueRowType; typedef std::map expirationQueueType; +typedef std::vector supportExpirationQueueRowType; +typedef std::map supportExpirationQueueType; + typedef std::vector claimQueueRowType; typedef std::map claimQueueType; typedef std::vector supportQueueRowType; typedef std::map supportQueueType; -typedef std::map nodeCacheType; +typedef std::map nodeCacheType; typedef std::map hashMapType; -typedef std::set claimIndexClaimListType; -typedef std::vector claimIndexElementListType; - -struct claimsForNameType +class claimsForNameType { +public: + claimsForNameType(const std::vector& claims, + const std::vector& supports, + const int nLastTakeoverHeight) + : claims(claims), supports(supports), nLastTakeoverHeight(nLastTakeoverHeight) + { + } + std::vector claims; std::vector supports; int nLastTakeoverHeight; - - claimsForNameType(std::vector claims, std::vector supports, int nLastTakeoverHeight) - : claims(claims), supports(supports), nLastTakeoverHeight(nLastTakeoverHeight) {} }; class CClaimTrieCache; @@ -298,87 +390,85 @@ class CClaimTrieCache; class CClaimTrie { public: - CClaimTrie(bool fMemory = false, bool fWipe = false, int nProportionalDelayFactor = 32) - : db(GetDataDir() / "claimtrie", 100, fMemory, fWipe, false) - , nCurrentHeight(0), nExpirationTime(Params().GetConsensus().nOriginalClaimExpirationTime) - , nProportionalDelayFactor(nProportionalDelayFactor) - , root(uint256S("0000000000000000000000000000000000000000000000000000000000000001")) - {} + CClaimTrie(bool fMemory = false, bool fWipe = false, int nProportionalDelayFactor = 32); + + ~CClaimTrie(); uint256 getMerkleHash(); bool empty() const; + void clear(); bool checkConsistency() const; bool WriteToDisk(); + bool ReadFromDisk(bool check = false); + std::vector flattenTrie() const; + bool getInfoForName(const std::string& name, CClaimValue& claim) const; + bool getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const; claimsForNameType getClaimsForName(const std::string& name) const; - CAmount getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector* supports = NULL) const; - CAmount getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector* supports = NULL) const; + CAmount getEffectiveAmountForClaim(const std::string& name, const uint160& claimId) const; + + CAmount getEffectiveAmountForClaimWithSupports(const std::string& name, + const uint160& claimId, + std::vector& supports) const; bool queueEmpty() const; + bool supportEmpty() const; + bool supportQueueEmpty() const; + bool expirationQueueEmpty() const; + bool supportExpirationQueueEmpty() const; void setExpirationTime(int t); void addToClaimIndex(const std::string& name, const CClaimValue& claim); + void removeFromClaimIndex(const CClaimValue& claim); - bool getClaimById(const uint160 claimId, std::string& name, CClaimValue& claim) const; - bool getQueueRow(int nHeight, claimQueueRowType& row) const; - bool getQueueNameRow(const std::string& name, queueNameRowType& row) const; - bool getExpirationQueueRow(int nHeight, expirationQueueRowType& row) const; - bool getSupportNode(std::string name, supportMapEntryType& node) const; - bool getSupportQueueRow(int nHeight, supportQueueRowType& row) const; - bool getSupportQueueNameRow(const std::string& name, queueNameRowType& row) const; - bool getSupportExpirationQueueRow(int nHeight, expirationQueueRowType& row) const; - + bool getClaimById(const uint160& claimId, std::string& name, CClaimValue& claim) const; bool haveClaim(const std::string& name, const COutPoint& outPoint) const; - bool haveClaimInQueue(const std::string& name, const COutPoint& outPoint, - int& nValidAtHeight) const; + + bool haveClaimInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const; bool haveSupport(const std::string& name, const COutPoint& outPoint) const; - bool haveSupportInQueue(const std::string& name, const COutPoint& outPoint, - int& nValidAtHeight) const; + + bool haveSupportInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const; unsigned int getTotalNamesInTrie() const; + unsigned int getTotalClaimsInTrie() const; + CAmount getTotalValueOfClaimsInTrie(bool fControllingOnly) const; friend class CClaimTrieCache; - CDBWrapper db; int nCurrentHeight; int nExpirationTime; int nProportionalDelayFactor; + private: void clear(CClaimTrieNode* current); const CClaimTrieNode* getNodeForName(const std::string& name) const; - bool update(nodeCacheType& cache, hashMapType& hashes, - std::map& takeoverHeights, - const uint256& hashBlock, claimQueueType& queueCache, - queueNameType& queueNameCache, - expirationQueueType& expirationQueueCache, int nNewHeight, - supportMapType& supportCache, - supportQueueType& supportQueueCache, - queueNameType& supportQueueNameCache, - expirationQueueType& supportExpirationQueueCache); bool updateName(const std::string& name, CClaimTrieNode* updatedNode); - bool updateHash(const std::string& name, uint256& hash); + + bool updateHash(const std::string& name, const uint256& hash); + bool updateTakeoverHeight(const std::string& name, int nTakeoverHeight); + bool recursiveNullify(CClaimTrieNode* node, std::string& name); bool recursiveCheckConsistency(const CClaimTrieNode* node) const; @@ -386,57 +476,37 @@ private: bool InsertFromDisk(const std::string& name, CClaimTrieNode* node); unsigned int getTotalNamesRecursive(const CClaimTrieNode* current) const; + unsigned int getTotalClaimsRecursive(const CClaimTrieNode* current) const; - CAmount getTotalValueOfClaimsRecursive(const CClaimTrieNode* current, - bool fControllingOnly) const; + + CAmount getTotalValueOfClaimsRecursive(const CClaimTrieNode* current, bool fControllingOnly) const; + + bool recursiveFlattenTrie(const std::string& name, + const CClaimTrieNode* current, + std::vector& nodes) const; void markNodeDirty(const std::string& name, CClaimTrieNode* node); - void updateQueueRow(int nHeight, claimQueueRowType& row); - void updateQueueNameRow(const std::string& name, - queueNameRowType& row); - void updateExpirationRow(int nHeight, expirationQueueRowType& row); - void updateSupportMap(const std::string& name, supportMapEntryType& node); - void updateSupportQueue(int nHeight, supportQueueRowType& row); - void updateSupportNameQueue(const std::string& name, - queueNameRowType& row); - void updateSupportExpirationQueue(int nHeight, expirationQueueRowType& row); - - void BatchWriteNode(CDBBatch& batch, const std::string& name, - const CClaimTrieNode* pNode) const; - void BatchEraseNode(CDBBatch& batch, const std::string& nome) const; - void BatchWriteClaimIndex(CDBBatch& batch) const; - void BatchWriteQueueRows(CDBBatch& batch); - void BatchWriteQueueNameRows(CDBBatch& batch); - void BatchWriteExpirationQueueRows(CDBBatch& batch); - void BatchWriteSupportNodes(CDBBatch& batch); - void BatchWriteSupportQueueRows(CDBBatch& batch); - void BatchWriteSupportQueueNameRows(CDBBatch& batch); - void BatchWriteSupportExpirationQueueRows(CDBBatch& batch); - template bool keyTypeEmpty(char key, K& dummy) const; + CClaimTrieDb db; CClaimTrieNode root; uint256 hashBlock; - - claimQueueType dirtyQueueRows; - queueNameType dirtyQueueNameRows; - expirationQueueType dirtyExpirationQueueRows; - - supportQueueType dirtySupportQueueRows; - queueNameType dirtySupportQueueNameRows; - expirationQueueType dirtySupportExpirationQueueRows; - nodeCacheType dirtyNodes; - supportMapType dirtySupportNodes; }; class CClaimTrieProofNode { public: - CClaimTrieProofNode() {}; - CClaimTrieProofNode(std::vector > children, - bool hasValue, uint256 valHash) + CClaimTrieProofNode() + { + } + + CClaimTrieProofNode(const std::vector >& children, + const bool hasValue, + const uint256& valHash) : children(children), hasValue(hasValue), valHash(valHash) - {}; + { + } + std::vector > children; bool hasValue; uint256 valHash; @@ -445,214 +515,199 @@ public: class CClaimTrieProof { public: - CClaimTrieProof() {}; - CClaimTrieProof(std::vector nodes, bool hasValue, COutPoint outPoint, int nHeightOfLastTakeover) : nodes(nodes), hasValue(hasValue), outPoint(outPoint), nHeightOfLastTakeover(nHeightOfLastTakeover) {} + CClaimTrieProof() + { + } + + CClaimTrieProof(const std::vector& nodes, + const bool hasValue, + const COutPoint& outPoint, + const int nHeightOfLastTakeover) + : nodes(nodes), hasValue(hasValue), outPoint(outPoint), nHeightOfLastTakeover(nHeightOfLastTakeover) + { + } + std::vector nodes; bool hasValue; COutPoint outPoint; int nHeightOfLastTakeover; }; -struct CNodeCallback { - struct CRecursionInterruptionException : public std::exception { - const bool success; - explicit CRecursionInterruptionException(bool success) : success(success) {} - }; - - virtual ~CNodeCallback() - { - } - - /** - * Callback to be called on every trie node - * @param[in] name full name of the node - * @param[in] node pointer to node itself - * - * To breakout early throw an exception. - * Throwing CRecursionInterruptionException will allow you to set the return value of iterateTrie. - */ - virtual void visit(const std::string& name, const CClaimTrieNode* node) = 0; -}; - class CClaimTrieCache { public: - CClaimTrieCache(CClaimTrie* base, bool fRequireTakeoverHeights = true) - : base(base), - fRequireTakeoverHeights(fRequireTakeoverHeights) - { - assert(base); - nCurrentHeight = base->nCurrentHeight; - } + CClaimTrieCache(CClaimTrie* base, bool fRequireTakeoverHeights = true); uint256 getMerkleHash() const; bool empty() const; + bool flush(); - bool dirty() const { return !dirtyHashes.empty(); } - CClaimTrieNode* getRoot() const - { - nodeCacheType::iterator iter = cache.find(""); - return iter == cache.end() ? &(base->root) : iter->second; - } + bool dirty() const; - bool addClaim(const std::string& name, const COutPoint& outPoint, - uint160 claimId, CAmount nAmount, int nHeight) const; - bool undoAddClaim(const std::string& name, const COutPoint& outPoint) const; - bool spendClaim(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const; - bool undoSpendClaim(const std::string& name, const COutPoint& outPoint, - uint160 claimId, CAmount nAmount, int nHeight, - int nValidAtHeight) const; + bool addClaim(const std::string& name, + const COutPoint& outPoint, + const uint160& claimId, + const CAmount& nAmount, + int nHeight); - bool addSupport(const std::string& name, const COutPoint& outPoint, - CAmount nAmount, uint160 supportedClaimId, - int nHeight) const; - bool undoAddSupport(const std::string& name, const COutPoint& outPoint, - int nHeight) const; - bool spendSupport(const std::string& name, const COutPoint& outPoint, - int nHeight, int& nValidAtHeight) const; - bool undoSpendSupport(const std::string& name, const COutPoint& outPoint, - uint160 supportedClaimId, CAmount nAmount, - int nHeight, int nValidAtHeight) const; + bool undoAddClaim(const std::string& name, const COutPoint& outPoint, int nHeight); + + bool spendClaim(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight); + + bool undoSpendClaim(const std::string& name, + const COutPoint& outPoint, + const uint160& claimId, + const CAmount& nAmount, + int nHeight, + int nValidAtHeight); + + bool addSupport(const std::string& name, + const COutPoint& outPoint, + const CAmount& nAmount, + const uint160& supportedClaimId, + int nHeight); + + bool undoAddSupport(const std::string& name, const COutPoint& outPoint, int nHeight); + + bool spendSupport(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight); + + bool undoSpendSupport(const std::string& name, + const COutPoint& outPoint, + const uint160& supportedClaimId, + const CAmount& nAmount, + int nHeight, + int nValidAtHeight); + + uint256 getBestBlock() const; - uint256 getBestBlock(); void setBestBlock(const uint256& hashBlock); bool incrementBlock(insertUndoType& insertUndo, - claimQueueRowType& expireUndo, - insertUndoType& insertSupportUndo, - supportQueueRowType& expireSupportUndo, - std::vector >& takeoverHeightUndo) const; + claimQueueRowType& expireUndo, + insertUndoType& insertSupportUndo, + supportQueueRowType& expireSupportUndo, + std::vector >& takeoverHeightUndo); + bool decrementBlock(insertUndoType& insertUndo, - claimQueueRowType& expireUndo, - insertUndoType& insertSupportUndo, - supportQueueRowType& expireSupportUndo, - std::vector >& takeoverHeightUndo) const; + claimQueueRowType& expireUndo, + insertUndoType& insertSupportUndo, + supportQueueRowType& expireSupportUndo, + std::vector >& takeoverHeightUndo); - ~CClaimTrieCache() { clear(); } + ~CClaimTrieCache(); - bool insertClaimIntoTrie(const std::string& name, CClaimValue claim, - bool fCheckTakeover = false) const; - bool removeClaimFromTrie(const std::string& name, const COutPoint& outPoint, - CClaimValue& claim, - bool fCheckTakeover = false) const; + bool insertClaimIntoTrie(const std::string& name, + const CClaimValue& claim, + bool fCheckTakeover = false); - bool getProofForName(const std::string& name, CClaimTrieProof& proof) const; - bool getInfoForName(const std::string& name, CClaimValue& claim) const; + bool removeClaimFromTrie(const std::string& name, + const COutPoint& outPoint, + CClaimValue& claim, + bool fCheckTakeover = false); - bool finalizeDecrement() const; + CClaimTrieProof getProofForName(const std::string& name) const; - void removeAndAddSupportToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const; - void removeAndAddToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const; + bool finalizeDecrement(); - bool forkForExpirationChange(bool increment) const; + void removeAndAddSupportToExpirationQueue(supportExpirationQueueRowType& row, int height, bool increment); - bool iterateTrie(CNodeCallback& callback) const; + void removeAndAddToExpirationQueue(expirationQueueRowType& row, int height, bool increment); - claimsForNameType getClaimsForName(const std::string& name) const; - - CAmount getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector* supports = NULL) const; - CAmount getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector* supports = NULL) const; + bool forkForExpirationChange(bool increment); protected: - CClaimTrie* base; - - bool fRequireTakeoverHeights; - - mutable nodeCacheType cache; - mutable nodeCacheType block_originals; - mutable std::set dirtyHashes; - mutable hashMapType cacheHashes; - mutable claimQueueType claimQueueCache; - mutable queueNameType claimQueueNameCache; - mutable expirationQueueType expirationQueueCache; - mutable supportMapType supportCache; - mutable supportQueueType supportQueueCache; - mutable queueNameType supportQueueNameCache; - mutable expirationQueueType supportExpirationQueueCache; - mutable std::set namesToCheckForTakeover; - mutable std::map cacheTakeoverHeights; - mutable int nCurrentHeight; // Height of the block that is being worked on, which is - // one greater than the height of the chain's tip - mutable claimIndexElementListType claimsToAdd; - mutable claimIndexClaimListType claimsToDelete; - - uint256 hashBlock; - uint256 computeHash() const; - bool reorderTrieNode(const std::string& name, bool fCheckTakeover) const; - bool recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent, - std::string sPos) const; - bool recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, - std::string sName, - bool* pfNullified = NULL) const; + bool reorderTrieNode(const std::string& name, bool fCheckTakeover); - bool clear() const; + bool recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent, const std::string& sPos) const; - bool removeClaim(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight, bool fCheckTakeover) const; - bool addClaimToQueues(const std::string& name, CClaimValue& claim) const; - bool removeClaimFromQueue(const std::string& name, const COutPoint& outPoint, - CClaimValue& claim) const; - void addToExpirationQueue(int nExpirationHeight, nameOutPointType& entry) const; - void removeFromExpirationQueue(const std::string& name, const COutPoint& outPoint, - int nHeight) const; + bool recursivePruneName(CClaimTrieNode* tnCurrent, + unsigned int nPos, + const std::string& sName, + bool* pfNullified = NULL); - claimQueueType::iterator getQueueCacheRow(int nHeight, - bool createIfNotExists) const; - queueNameType::iterator getQueueCacheNameRow(const std::string& name, - bool createIfNotExists) const; - expirationQueueType::iterator getExpirationQueueCacheRow(int nHeight, - bool createIfNotExists) const; + bool clear(); - bool removeSupport(const std::string& name, const COutPoint& outPoint, - int nHeight, int& nValidAtHeight, - bool fCheckTakeover) const; - bool removeSupportFromMap(const std::string& name, const COutPoint& outPoint, - CSupportValue& support, - bool fCheckTakeover) const; + bool removeClaim(const std::string& name, + const COutPoint& outPoint, + int nHeight, + int& nValidAtHeight, + bool fCheckTakeover); - bool insertSupportIntoMap(const std::string& name, - CSupportValue support, - bool fCheckTakeover) const; + bool addClaimToQueues(const std::string& name, CClaimValue& claim); - supportQueueType::iterator getSupportQueueCacheRow(int nHeight, - bool createIfNotExists) const; - queueNameType::iterator getSupportQueueCacheNameRow(const std::string& name, - bool createIfNotExists) const; - expirationQueueType::iterator getSupportExpirationQueueCacheRow(int nHeight, - bool createIfNotExists) const; + bool removeClaimFromQueue(const std::string& name, const COutPoint& outPoint, CClaimValue& claim); - bool addSupportToQueues(const std::string& name, CSupportValue& support) const; - bool removeSupportFromQueue(const std::string& name, const COutPoint& outPoint, - CSupportValue& support) const; + void addToExpirationQueue(int nExpirationHeight, nameOutPointType& entry); - void addSupportToExpirationQueue(int nExpirationHeight, - nameOutPointType& entry) const; - void removeSupportFromExpirationQueue(const std::string& name, - const COutPoint& outPoint, - int nHeight) const; + void removeFromExpirationQueue(const std::string& name, const COutPoint& outPoint, int nHeight); - bool getSupportsForName(const std::string& name, - supportMapEntryType& node) const; + bool removeSupport(const std::string& name, + const COutPoint& outPoint, + int nHeight, + int& nValidAtHeight, + bool fCheckTakeover); + + bool removeSupportFromMap(const std::string& name, + const COutPoint& outPoint, + CSupportValue& support, + bool fCheckTakeover); + + bool insertSupportIntoMap(const std::string& name, const CSupportValue& support, bool fCheckTakeover); + + bool addSupportToQueues(const std::string& name, CSupportValue& support); + + bool removeSupportFromQueue(const std::string& name, const COutPoint& outPoint, CSupportValue& support); + + void addSupportToExpirationQueue(int nExpirationHeight, nameOutPointType& entry); + + void removeSupportFromExpirationQueue(const std::string& name, const COutPoint& outPoint, int nHeight); + + bool getSupportsForName(const std::string& name, supportMapEntryType& node) const; bool getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const; int getDelayForName(const std::string& name) const; - uint256 getLeafHashForProof(const std::string& currentPosition, unsigned char nodeChar, - const CClaimTrieNode* currentNode) const; + uint256 getLeafHashForProof(const std::string& currentPosition, + unsigned char nodeChar, + const CClaimTrieNode* currentNode) const; - CClaimTrieNode* addNodeToCache(const std::string& position, CClaimTrieNode* original) const; + CClaimTrieNode* addNodeToCache(const std::string& position, CClaimTrieNode* original); bool getOriginalInfoForName(const std::string& name, CClaimValue& claim) const; int getNumBlocksOfContinuousOwnership(const std::string& name) const; - void recursiveIterateTrie(std::string& name, const CClaimTrieNode* current, CNodeCallback& callback) const; + template + void update(std::map& map); - const CClaimTrieNode* getNodeForName(const std::string& name) const; + template + typename std::map::iterator getQueueCacheRow(const K& key, std::map& map, bool createIfNotExists); + + CClaimTrie* base; + bool fRequireTakeoverHeights; + nodeCacheType cache; + nodeCacheType block_originals; + claimQueueType claimQueueCache; + queueNameType claimQueueNameCache; + expirationQueueType expirationQueueCache; + supportMapType supportCache; + supportQueueType supportQueueCache; + supportQueueNameType supportQueueNameCache; + supportExpirationQueueType supportExpirationQueueCache; + std::set namesToCheckForTakeover; + std::map cacheTakeoverHeights; + int nCurrentHeight; // Height of the block that is being worked on, which is + // one greater than the height of the chain's tip + + // used in merkle hash computing + mutable hashMapType cacheHashes; + mutable std::set dirtyHashes; + uint256 hashBlock; }; #endif // BITCOIN_CLAIMTRIE_H diff --git a/src/claimtriedb.cpp b/src/claimtriedb.cpp new file mode 100644 index 000000000..bc74a5862 --- /dev/null +++ b/src/claimtriedb.cpp @@ -0,0 +1,227 @@ + +#include "claimtriedb.h" +#include "claimtrie.h" + +#include +#include +#include + +/** + * Function to provide unique char of types pair + */ +template +unsigned char hashType(); + +#define TEMPLATE_HASH_TYPE(type1, type2, ret) \ + template <> \ + unsigned char hashType() \ + { \ + return ret; \ + } + +TEMPLATE_HASH_TYPE(std::string, CClaimTrieNode, 'n') +TEMPLATE_HASH_TYPE(uint160, CClaimIndexElement, 'i') +TEMPLATE_HASH_TYPE(int, claimQueueRowType, 'r') +TEMPLATE_HASH_TYPE(std::string, queueNameRowType, 'm') +TEMPLATE_HASH_TYPE(int, expirationQueueRowType, 'e') +TEMPLATE_HASH_TYPE(std::string, supportMapEntryType, 's') +TEMPLATE_HASH_TYPE(int, supportQueueRowType, 'u') +TEMPLATE_HASH_TYPE(std::string, supportQueueNameRowType, 'p') +TEMPLATE_HASH_TYPE(int, supportExpirationQueueRowType, 'x') + +/* + * Concrete implementation of buffer + */ +template +class CActualBuffer : public CAbstractBuffer +{ +public: + CActualBuffer() : data() + { + } + + typedef std::list > dataType; + + typename dataType::iterator find(const K& key) + { + typename dataType::iterator itData = data.begin(); + while (itData != data.end()) { + if (key == itData->first) break; + ++itData; + } + return itData; + } + + typename dataType::iterator end() + { + return data.end(); + } + + typename dataType::iterator push_back(const std::pair& element) + { + return data.insert(data.end(), element); + } + + void write(const unsigned char key, CClaimTrieDb* db) + { + for (typename dataType::iterator it = data.begin(); it != data.end(); ++it) { + if (it->second.empty()) { + db->Erase(std::make_pair(key, it->first)); + } else { + db->Write(std::make_pair(key, it->first), it->second); + } + } + data.clear(); + } + + dataType data; +}; + +CClaimTrieDb::CClaimTrieDb(bool fMemory, bool fWipe) + : CDBWrapper(GetDataDir() / "claimtrie", 100, fMemory, fWipe, false) +{ +} + +CClaimTrieDb::~CClaimTrieDb() +{ + for (std::map::iterator itQueue = queues.begin(); itQueue != queues.end(); ++itQueue) { + delete itQueue->second; + } +} + +void CClaimTrieDb::writeQueues() +{ + for (std::map::iterator itQueue = queues.begin(); itQueue != queues.end(); ++itQueue) { + itQueue->second->write(itQueue->first, this); + } +} + +template +bool CClaimTrieDb::getQueueRow(const K& key, V& row) const +{ + const unsigned char hash = hashType(); + std::map::const_iterator itQueue = queues.find(hash); + if (itQueue != queues.end()) { + CActualBuffer* map = static_cast*>(itQueue->second); + typename CActualBuffer::dataType::const_iterator itData = map->find(key); + if (itData != map->end()) { + row = itData->second; + return true; + } + } + return Read(std::make_pair(hash, key), row); +} + +template +void CClaimTrieDb::updateQueueRow(const K& key, V& row) +{ + const unsigned char hash = hashType(); + std::map::iterator itQueue = queues.find(hash); + if (itQueue == queues.end()) { + itQueue = queues.insert(itQueue, std::pair(hash, new CActualBuffer)); + } + CActualBuffer* map = static_cast*>(itQueue->second); + typename CActualBuffer::dataType::iterator itData = map->find(key); + if (itData == map->end()) { + itData = map->push_back(std::make_pair(key, V())); + } + std::swap(itData->second, row); +} + +template +bool CClaimTrieDb::keyTypeEmpty() const +{ + const unsigned char hash = hashType(); + std::map::const_iterator itQueue = queues.find(hash); + if (itQueue != queues.end()) { + const typename CActualBuffer::dataType& data = (static_cast*>(itQueue->second))->data; + for (typename CActualBuffer::dataType::const_iterator itData = data.begin(); itData != data.end(); ++itData) { + if (!itData->second.empty()) return false; + } + } + + boost::scoped_ptr pcursor(const_cast(this)->NewIterator()); + + for (pcursor->SeekToFirst(); pcursor->Valid(); pcursor->Next()) { + std::pair key; + if (pcursor->GetKey(key)) { + if (hash == key.first) return false; + } else { + break; + } + } + return true; +} + +template +bool CClaimTrieDb::seekByKey(std::map& map) const +{ + const unsigned char hash = hashType(); + boost::scoped_ptr pcursor(const_cast(this)->NewIterator()); + + for (pcursor->SeekToFirst(); pcursor->Valid(); pcursor->Next()) { + std::pair key; + if (pcursor->GetKey(key)) { + if (hash == key.first) { + V value; + if (!pcursor->GetValue(value)) return false; + map.insert(std::make_pair(key.second, value)); + } + } + } + return true; +} + +template +bool CClaimTrieDb::getQueueMap(std::map& map) const +{ + const unsigned char hash = hashType(); + std::map::const_iterator itQueue = queues.find(hash); + if (itQueue != queues.end()) { + const typename CActualBuffer::dataType& data = (static_cast*>(itQueue->second))->data; + std::copy(data.begin(), data.end(), std::inserter(map, map.end())); + } + + boost::scoped_ptr pcursor(const_cast(this)->NewIterator()); + + for (pcursor->SeekToFirst(); pcursor->Valid(); pcursor->Next()) { + std::pair key; + if (pcursor->GetKey(key)) { + if (hash == key.first) { + typename std::map::iterator itMap = map.find(key.second); + if (itMap != map.end()) continue; + V value; + if (!pcursor->GetValue(value)) return false; + map.insert(itMap, std::make_pair(key.second, value)); + } + } + } + return true; +} + +/* + * Explicit template instantiation for every pair of types + */ +#define TEMPLATE_INSTANTIATE2(type1, type2) \ + template bool CClaimTrieDb::getQueueMap<>(std::map & map) const; \ + template bool CClaimTrieDb::getQueueRow<>(const type1& key, type2& row) const; \ + template void CClaimTrieDb::updateQueueRow<>(const type1& key, type2& row); \ + template bool CClaimTrieDb::keyTypeEmpty() const; \ + template bool CClaimTrieDb::seekByKey<>(std::map & map) const + +#define TEMPLATE_INSTANTIATE3(type1, type2, type3) \ + template bool CClaimTrieDb::getQueueMap<>(std::map & map) const; \ + template bool CClaimTrieDb::getQueueRow<>(const type1& key, type2& row) const; \ + template void CClaimTrieDb::updateQueueRow<>(const type1& key, type2& row); \ + template bool CClaimTrieDb::keyTypeEmpty() const; \ + template bool CClaimTrieDb::seekByKey<>(std::map & map) const + +TEMPLATE_INSTANTIATE3(std::string, CClaimTrieNode, nodeNameCompare); +TEMPLATE_INSTANTIATE2(uint160, CClaimIndexElement); +TEMPLATE_INSTANTIATE2(int, claimQueueRowType); +TEMPLATE_INSTANTIATE2(std::string, queueNameRowType); +TEMPLATE_INSTANTIATE2(int, expirationQueueRowType); +TEMPLATE_INSTANTIATE2(std::string, supportMapEntryType); +TEMPLATE_INSTANTIATE2(int, supportQueueRowType); +TEMPLATE_INSTANTIATE2(std::string, supportQueueNameRowType); +TEMPLATE_INSTANTIATE2(int, supportExpirationQueueRowType); diff --git a/src/claimtriedb.h b/src/claimtriedb.h new file mode 100644 index 000000000..17b8c6d74 --- /dev/null +++ b/src/claimtriedb.h @@ -0,0 +1,94 @@ +#ifndef BITCOIN_CLAIMTRIE_DB_H +#define BITCOIN_CLAIMTRIE_DB_H + +#include "dbwrapper.h" + +#include + +#include + + +class CClaimTrieDb; + +/** + * Interface between buffer and database + */ +class CAbstractBuffer +{ +public: + virtual ~CAbstractBuffer() + { + } + + virtual void write(const unsigned char key, CClaimTrieDb* db) = 0; +}; + +/** + * This class implements key value storage. It is used by the CClaimTrie + * class to store queues of claim information. It allows for the storage + * of values of datatype V that can be retrieved using key datatype K. + * Changes to the key value storage is buffered until they are written to + * disk using writeQueues() + */ +class CClaimTrieDb : public CDBWrapper +{ +public: + CClaimTrieDb(bool fMemory = false, bool fWipe = false); + + ~CClaimTrieDb(); + + /** + * Write to disk the buffered changes to the key value storage + */ + void writeQueues(); + + /** + * Gets a map representation of K type / V type stored by their hash + * on disk with buffered changes applied. + * @param[out] map key / value pairs to read + */ + template + bool getQueueMap(std::map& map) const; + + /** + * Gets a value of type V found by key of type K stored by their hash + * on disk with with buffered changes applied. + * @param[in] key key to look for + * @param[out] row value which is found + */ + template + bool getQueueRow(const K& key, V& row) const; + + /** + * Update value of type V by key of type K in the buffer through + * their hash + * @param[in] key key to look for + * @param[in/out] row update value and gets its last value + */ + template + void updateQueueRow(const K& key, V& row); + + /** + * Check that there are no data stored under key datatype K and value + * datatype V. Checks both the buffer and disk + */ + template + bool keyTypeEmpty() const; + + /** + * Get a map representation of K type / V type stored by their hash. + * Look only in the disk, and not the buffer. + * Returns false if database read fails. + * @param[out] map key / value pairs readed only from disk + */ + template + bool seekByKey(std::map& map) const; + +private: + /** + * Represents buffer of changes before being stored to disk + */ + std::map queues; +}; + +#endif // BITCOIN_CLAIMTRIE_DB_H diff --git a/src/clientversion.h b/src/clientversion.h index dbcf9c627..e8e8417ca 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -16,8 +16,8 @@ //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 12 -#define CLIENT_VERSION_REVISION 3 -#define CLIENT_VERSION_BUILD 1 +#define CLIENT_VERSION_REVISION 2 +#define CLIENT_VERSION_BUILD 0 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/main.cpp b/src/main.cpp index 38f738834..a894999b6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -963,12 +963,13 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state) if (!MoneyRange(nValueOut)) return state.DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge"); - // check claimtrie transactions + // check claimtrie transactions if (ClaimScriptSize(txout.scriptPubKey) > MAX_CLAIM_SCRIPT_SIZE) return state.DoS(100, false, REJECT_INVALID, "bad-txns-claimscriptsize-toolarge"); - if (ClaimNameSize(txout.scriptPubKey) > MAX_CLAIM_NAME_SIZE) + if (ClaimNameSize(txout.scriptPubKey) > MAX_CLAIM_NAME_SIZE) return state.DoS(100, false, REJECT_INVALID, "bad-txns-claimscriptname-toolarge"); + } // Check for duplicate inputs @@ -1033,12 +1034,8 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C // Rather not work on nonstandard transactions (unless -testnet/-regtest) string reason; - if (fRequireStandard && !IsStandardTx(tx, reason)) { - if (reason == "dust") - return state.DoS(0, false, REJECT_DUST, reason); - else - return state.DoS(0, false, REJECT_NONSTANDARD, reason); - } + if (fRequireStandard && !IsStandardTx(tx, reason)) + return state.DoS(0, false, REJECT_NONSTANDARD, reason); // Don't relay version 2 transactions until CSV is active, and we can be // sure that such transactions will be mined (unless we're on @@ -2193,7 +2190,8 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI } std::string name(vvchParams[0].begin(), vvchParams[0].end()); LogPrintf("%s: (txid: %s, nOut: %d) Trying to remove %s from the claim trie due to its block being disconnected\n", __func__, hash.ToString(), i, name.c_str()); - if (!trieCache.undoAddClaim(name, COutPoint(hash, i))) { + if (!trieCache.undoAddClaim(name, COutPoint(hash, i), pindex->nHeight)) + { LogPrintf("%s: Could not find the claim in the trie or the cache\n", __func__); } } @@ -2501,7 +2499,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin flags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY; nLockTimeFlags |= LOCKTIME_VERIFY_SEQUENCE; } - + // v 13 LBRYcrd hard fork to extend expiration time if (pindex->nHeight == Params().GetConsensus().nExtendedClaimExpirationForkHeight) { @@ -2586,7 +2584,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin typedef std::vector > spentClaimsType; spentClaimsType spentClaims; - + for (unsigned int i = 0; i < tx.vin.size(); ++i) { const CTxIn& txin = tx.vin[i]; @@ -2623,7 +2621,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin std::string name(vvchParams[0].begin(), vvchParams[0].end()); int nValidAtHeight; LogPrintf("%s: Removing %s from the claim trie. Tx: %s, nOut: %d\n", __func__, name, txin.prevout.hash.GetHex(), txin.prevout.n); - if (trieCache.spendClaim(name, COutPoint(txin.prevout.hash, txin.prevout.n), nValidAtHeight)) { + if (trieCache.spendClaim(name, COutPoint(txin.prevout.hash, txin.prevout.n), coins->nHeight, nValidAtHeight)) + { mClaimUndoHeights[i] = nValidAtHeight; std::pair entry(name, claimId); spentClaims.push_back(entry); @@ -2646,7 +2645,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } } } - + for (unsigned int i = 0; i < tx.vout.size(); ++i) { const CTxOut& txout = tx.vout[i]; @@ -4215,8 +4214,8 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); // check level 1: verify block validity if (nCheckLevel >= 1 && !CheckBlock(block, state)) - return error("%s: *** found bad block at %d, hash=%s (%s)\n", __func__, - pindex->nHeight, pindex->GetBlockHash().ToString(), FormatStateMessage(state)); + return error("%s: *** found bad block at %d, hash=%s (%s)\n", __func__, + pindex->nHeight, pindex->GetBlockHash().ToString(), FormatStateMessage(state)); // check level 2: verify undo validity if (nCheckLevel >= 2 && pindex) { CBlockUndo undo; @@ -4264,6 +4263,42 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, return true; } +bool GetProofForName(const CBlockIndex* pindexProof, const std::string& name, CClaimTrieProof& proof) +{ + AssertLockHeld(cs_main); + if (!chainActive.Contains(pindexProof)) + { + return false; + } + CCoinsViewCache coins(pcoinsTip); + CClaimTrieCache trieCache(pclaimTrie); + CBlockIndex* pindexState = chainActive.Tip(); + CValidationState state; + for (CBlockIndex *pindex = chainActive.Tip(); pindex && pindex->pprev && pindexState != pindexProof; pindex=pindex->pprev) + { + boost::this_thread::interruption_point(); + CBlock block; + if (!ReadBlockFromDisk(block, pindex, Params().GetConsensus())) + { + return false; + } + if (pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) + { + bool fClean = true; + if (!DisconnectBlock(block, state, pindex, coins, trieCache, &fClean)) + { + return false; + } + pindexState = pindex->pprev; + } + if (ShutdownRequested()) + return false; + } + assert(pindexState == pindexProof); + proof = trieCache.getProofForName(name); + return true; +} + void UnloadBlockIndex() { LOCK(cs_main); @@ -4306,7 +4341,7 @@ bool LoadBlockIndex() return true; } -bool InitBlockIndex(const CChainParams& chainparams) +bool InitBlockIndex(const CChainParams& chainparams) { LOCK(cs_main); diff --git a/src/main.h b/src/main.h index 00bfcb5dd..4dfc5b2ca 100644 --- a/src/main.h +++ b/src/main.h @@ -225,6 +225,8 @@ FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false); FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false); /** Translation to a filesystem path */ boost::filesystem::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix); +/** Get a cryptographic proof that a name maps to a value **/ +bool GetProofForName(const CBlockIndex* pindexProof, const std::string& name, CClaimTrieProof& proof); /** Import blocks from an external file */ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp = NULL); /** Initialize a new block tree database + block data on disk */ diff --git a/src/miner.cpp b/src/miner.cpp index bfa5613e1..8136d8e80 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -294,7 +294,8 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s } std::string name(vvchParams[0].begin(), vvchParams[0].end()); int throwaway; - if (trieCache.spendClaim(name, COutPoint(txin.prevout.hash, txin.prevout.n), throwaway)) { + if (trieCache.spendClaim(name, COutPoint(txin.prevout.hash, txin.prevout.n), nTxinHeight, throwaway)) + { std::pair entry(name, claimId); spentClaims.push_back(entry); } @@ -315,11 +316,11 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s } } } - + for (unsigned int i = 0; i < tx.vout.size(); ++i) { const CTxOut& txout = tx.vout[i]; - + std::vector > vvchParams; int op; if (DecodeClaimScript(txout.scriptPubKey, op, vvchParams)) @@ -567,7 +568,7 @@ void static BitcoinMiner(const CChainParams& chainparams) while (true) { unsigned int nHashesDone = 0; - + // Check if something found while (true) { @@ -598,7 +599,7 @@ void static BitcoinMiner(const CChainParams& chainparams) } if (found) break; - + // Meter hashes/sec static int64_t nHashCounter; if (nHPSTimerStart == 0) diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp index ff96ccaa2..20e1f79ff 100644 --- a/src/qt/paymentrequestplus.cpp +++ b/src/qt/paymentrequestplus.cpp @@ -159,19 +159,14 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c std::string data_to_verify; // Everything but the signature rcopy.SerializeToString(&data_to_verify); - EVP_MD_CTX* ctx = EVP_MD_CTX_new(); - if (!ctx) - throw SSLVerifyError("Unable to allocate OpenSSL context."); - - EVP_PKEY* pubkey = X509_get_pubkey(signing_cert); - EVP_MD_CTX_init(ctx); - if (!EVP_VerifyInit_ex(ctx, digestAlgorithm, NULL) || - !EVP_VerifyUpdate(ctx, data_to_verify.data(), data_to_verify.size()) || - !EVP_VerifyFinal(ctx, (const unsigned char*)paymentRequest.signature().data(), (unsigned int)paymentRequest.signature().size(), pubkey)) { - EVP_MD_CTX_free(ctx); + EVP_MD_CTX ctx; + EVP_PKEY *pubkey = X509_get_pubkey(signing_cert); + EVP_MD_CTX_init(&ctx); + if (!EVP_VerifyInit_ex(&ctx, digestAlgorithm, NULL) || + !EVP_VerifyUpdate(&ctx, data_to_verify.data(), data_to_verify.size()) || + !EVP_VerifyFinal(&ctx, (const unsigned char*)paymentRequest.signature().data(), (unsigned int)paymentRequest.signature().size(), pubkey)) { throw SSLVerifyError("Bad signature, invalid payment request."); } - EVP_MD_CTX_free(ctx); // OpenSSL API for getting human printable strings from certs is baroque. int textlen = X509_NAME_get_text_by_NID(certname, NID_commonName, NULL, 0); diff --git a/src/rpc/claimtrie.cpp b/src/rpc/claimtrie.cpp index dc66cefa2..252de232b 100644 --- a/src/rpc/claimtrie.cpp +++ b/src/rpc/claimtrie.cpp @@ -1,17 +1,13 @@ -#include "boost/scope_exit.hpp" -#include "consensus/validation.h" -#include "init.h" #include "main.h" #include "nameclaim.h" #include "rpc/server.h" -#include "txmempool.h" #include "univalue.h" +#include "txmempool.h" -#include +// Maximum block decrement that is allowed from rpc calls +const int MAX_RPC_BLOCK_DECREMENTS = 50; -#include - -uint160 ParseClaimtrieId(const UniValue& v, const std::string& strName) +uint160 ParseClaimtrieId(const UniValue& v, std::string strName) { std::string strHex; if (v.isStr()) @@ -26,129 +22,72 @@ uint160 ParseClaimtrieId(const UniValue& v, const std::string& strName) return result; } -static CBlockIndex* BlockHashIndex(const uint256& blockHash) -{ - AssertLockHeld(cs_main); - - if (mapBlockIndex.count(blockHash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlockIndex* pblockIndex = mapBlockIndex[blockHash]; - if (!chainActive.Contains(pblockIndex)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not in main chain"); - - return pblockIndex; -} - -#define MAX_RPC_BLOCK_DECREMENTS 500 - -void RollBackTo(const CBlockIndex* targetIndex, CCoinsViewCache& coinsCache, CClaimTrieCache& trieCache) -{ - AssertLockHeld(cs_main); - - const CBlockIndex* activeIndex = chainActive.Tip(); - - if (activeIndex->nHeight > (targetIndex->nHeight + MAX_RPC_BLOCK_DECREMENTS)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Block is too deep"); - - const size_t currentMemoryUsage = pcoinsTip->DynamicMemoryUsage(); - - for (; activeIndex && activeIndex != targetIndex; activeIndex = activeIndex->pprev) { - boost::this_thread::interruption_point(); - - CBlock block; - if (!ReadBlockFromDisk(block, activeIndex, Params().GetConsensus())) - throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("Failed to read %s", activeIndex->ToString())); - - if (coinsCache.DynamicMemoryUsage() + currentMemoryUsage > nCoinCacheUsage) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Out of memory, you may want to increase dbcache size"); - - if (ShutdownRequested()) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Shutdown requested"); - - CValidationState state; - if (!DisconnectBlock(block, state, activeIndex, coinsCache, trieCache)) - throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("Failed to disconnect %s", block.ToString())); - } -} UniValue getclaimsintrie(const UniValue& params, bool fHelp) { - if (fHelp || params.size() > 1) + if (fHelp || params.size() > 0) throw std::runtime_error( "getclaimsintrie\n" "Return all claims in the name trie.\n" "Arguments:\n" - "1. \"blockhash\" (string, optional) get claims in the trie\n" - " at the block specified\n" - " by this block hash.\n" - " If none is given,\n" - " the latest active\n" - " block will be used.\n" + "None\n" "Result: \n" "[\n" " {\n" - " \"name\" (string) the name claimed\n" - " \"claims\": [ (array of object) the claims for this name\n" + " \"name\" (string) the name claimed\n" + " \"claims\": [ (array of object) the claims for this name\n" " {\n" - " \"claimId\" (string) the claimId of the claim\n" - " \"txid\" (string) the txid of the claim\n" - " \"n\" (numeric) the vout value of the claim\n" - " \"amount\" (numeric) txout amount\n" - " \"height\" (numeric) the height of the block in which this transaction is located\n" - " \"value\" (string) the value of this claim\n" + " \"claimId\" (string) the claimId of the claim\n" + " \"txid\" (string) the txid of the claim\n" + " \"n\" (numeric) the vout value of the claim\n" + " \"amount\" (numeric) txout amount\n" + " \"height\" (numeric) the height of the block in which this transaction is located\n" + " \"value\" (string) the value of this claim\n" " }\n" " ]\n" " }\n" - "]\n"); - + "]\n" + ); + LOCK(cs_main); + UniValue ret(UniValue::VARR); - CCoinsViewCache coinsCache(pcoinsTip); - CClaimTrieCache trieCache(pclaimTrie); + CCoinsViewCache view(pcoinsTip); + std::vector nodes = pclaimTrie->flattenTrie(); - if (!params.empty()) { - CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(params[0], "blockhash (optional parameter 1)")); - RollBackTo(blockIndex, coinsCache, trieCache); - } - - class CClaimsCallback : public CNodeCallback + for (std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it) { - public: - CClaimsCallback(UniValue& ret, const CCoinsViewCache& coinsCache) : nodes(ret), coinsCache(coinsCache) + if (!it->second.claims.empty()) { - } - - void visit(const std::string& name, const CClaimTrieNode* node) - { - if (ShutdownRequested()) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Shutdown requested"); - - boost::this_thread::interruption_point(); - - if (node->claims.empty()) - return; - + UniValue node(UniValue::VOBJ); + node.push_back(Pair("name", it->first)); UniValue claims(UniValue::VARR); - for (std::vector::const_iterator itClaims = node->claims.begin(); itClaims != node->claims.end(); ++itClaims) { + for (std::vector::iterator itClaims = it->second.claims.begin(); itClaims != it->second.claims.end(); ++itClaims) + { UniValue claim(UniValue::VOBJ); claim.push_back(Pair("claimId", itClaims->claimId.GetHex())); claim.push_back(Pair("txid", itClaims->outPoint.hash.GetHex())); claim.push_back(Pair("n", (int)itClaims->outPoint.n)); - claim.push_back(Pair("amount", ::ValueFromAmount(itClaims->nAmount))); + claim.push_back(Pair("amount", ValueFromAmount(itClaims->nAmount))); claim.push_back(Pair("height", itClaims->nHeight)); - const CCoins* coin = coinsCache.AccessCoins(itClaims->outPoint.hash); - if (!coin) { + const CCoins* coin = view.AccessCoins(itClaims->outPoint.hash); + if (!coin) + { LogPrintf("%s: %s does not exist in the coins view, despite being associated with a name\n", - __func__, itClaims->outPoint.hash.GetHex()); + __func__, itClaims->outPoint.hash.GetHex()); claim.push_back(Pair("error", "No value found for claim")); - } else if (!coin->IsAvailable(itClaims->outPoint.n)) { + } + else if (!coin->IsAvailable(itClaims->outPoint.n)) + { LogPrintf("%s: the specified txout of %s appears to have been spent\n", __func__, itClaims->outPoint.hash.GetHex()); claim.push_back(Pair("error", "Txout spent")); - } else { + } + else + { int op; std::vector > vvchParams; - if (!DecodeClaimScript(coin->vout[itClaims->outPoint.n].scriptPubKey, op, vvchParams)) { + if (!DecodeClaimScript(coin->vout[itClaims->outPoint.n].scriptPubKey, op, vvchParams)) + { LogPrintf("%s: the specified txout of %s does not have an claim command\n", __func__, itClaims->outPoint.hash.GetHex()); } std::string sValue(vvchParams[1].begin(), vvchParams[1].end()); @@ -156,112 +95,70 @@ UniValue getclaimsintrie(const UniValue& params, bool fHelp) } claims.push_back(claim); } - - UniValue nodeObj(UniValue::VOBJ); - nodeObj.push_back(Pair("name", name)); - nodeObj.push_back(Pair("claims", claims)); - nodes.push_back(nodeObj); + node.push_back(Pair("claims", claims)); + ret.push_back(node); } - - private: - UniValue& nodes; - const CCoinsViewCache& coinsCache; - }; - - UniValue ret(UniValue::VARR); - CClaimsCallback claimsCallback(ret, coinsCache); - trieCache.iterateTrie(claimsCallback); + } return ret; } UniValue getclaimtrie(const UniValue& params, bool fHelp) { - if (fHelp || params.size() > 1) + if (fHelp || params.size() > 0) throw std::runtime_error( "getclaimtrie\n" - "DEPRECATED. Return the entire name trie.\n" + "Return the entire name trie.\n" "Arguments:\n" - "1. \"blockhash\" (string, optional) get claim in the trie\n" - " at the block specified\n" - " by this block hash.\n" - " If none is given,\n" - " the latest active\n" - " block will be used.\n" + "None\n" "Result: \n" - "[\n" - " {\n" + "{\n" " \"name\" (string) the name of the node\n" " \"hash\" (string) the hash of the node\n" " \"txid\" (string) (if value exists) the hash of the transaction which has successfully claimed this name\n" " \"n\" (numeric) (if value exists) vout value\n" " \"value\" (numeric) (if value exists) txout value\n" " \"height\" (numeric) (if value exists) the height of the block in which this transaction is located\n" - " }\n" - "]\n"); + "}\n" + ); LOCK(cs_main); - - CCoinsViewCache coinsCache(pcoinsTip); - CClaimTrieCache trieCache(pclaimTrie); - - if (!params.empty()) { - CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(params[0], "blockhash (optional parameter 1)")); - RollBackTo(blockIndex, coinsCache, trieCache); - } - - class CClaimCallback : public CNodeCallback - { - public: - CClaimCallback(UniValue& ret) : nodes(ret) - { - } - - void visit(const std::string& name, const CClaimTrieNode* node) - { - if (ShutdownRequested()) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Shutdown requested"); - - boost::this_thread::interruption_point(); - - UniValue nodeObj(UniValue::VOBJ); - nodeObj.push_back(Pair("name", name)); - nodeObj.push_back(Pair("hash", node->hash.GetHex())); - CClaimValue claim; - if (node->getBestClaim(claim)) { - nodeObj.push_back(Pair("txid", claim.outPoint.hash.GetHex())); - nodeObj.push_back(Pair("n", (int)claim.outPoint.n)); - nodeObj.push_back(Pair("value", ::ValueFromAmount(claim.nAmount))); - nodeObj.push_back(Pair("height", claim.nHeight)); - } - nodes.push_back(nodeObj); - } - - private: - UniValue& nodes; - }; - UniValue ret(UniValue::VARR); - CClaimCallback claimCallback(ret); - trieCache.iterateTrie(claimCallback); + + std::vector nodes = pclaimTrie->flattenTrie(); + for (std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it) + { + UniValue node(UniValue::VOBJ); + node.push_back(Pair("name", it->first)); + node.push_back(Pair("hash", it->second.hash.GetHex())); + CClaimValue claim; + if (it->second.getBestClaim(claim)) + { + node.push_back(Pair("txid", claim.outPoint.hash.GetHex())); + node.push_back(Pair("n", (int)claim.outPoint.n)); + node.push_back(Pair("value", ValueFromAmount(claim.nAmount))); + node.push_back(Pair("height", claim.nHeight)); + } + ret.push_back(node); + } return ret; } -bool getValueForClaim(const CCoinsViewCache& coinsCache, const COutPoint& out, std::string& sValue) +bool getValueForClaim(const COutPoint& out, std::string& sValue) { - const CCoins* coin = coinsCache.AccessCoins(out.hash); + CCoinsViewCache view(pcoinsTip); + const CCoins* coin = view.AccessCoins(out.hash); if (!coin) { LogPrintf("%s: %s does not exist in the coins view, despite being associated with a name\n", __func__, out.hash.GetHex()); return true; } - if(!coin->IsAvailable(out.n)) { LogPrintf("%s: the specified txout of %s appears to have been spent\n", __func__, out.hash.GetHex()); return true; } - + int op; std::vector > vvchParams; if (!DecodeClaimScript(coin->vout[out.n].scriptPubKey, op, vvchParams)) @@ -283,115 +180,118 @@ bool getValueForClaim(const CCoinsViewCache& coinsCache, const COutPoint& out, s UniValue getvalueforname(const UniValue& params, bool fHelp) { - if (fHelp || params.size() > 2) + if (fHelp || params.size() != 1) throw std::runtime_error( "getvalueforname \"name\"\n" "Return the value associated with a name, if one exists\n" "Arguments:\n" - "1. \"name\" (string) the name to look up\n" - "2. \"blockhash\" (string, optional) get the value\n" - " associated with the name\n" - " at the block specified\n" - " by this block hash.\n" - " If none is given,\n" - " the latest active\n" - " block will be used.\n" + "1. \"name\" (string) the name to look up\n" "Result: \n" - "\"value\" (string) the value of the name, if it exists\n" - "\"claimId\" (string) the claimId for this name claim\n" - "\"txid\" (string) the hash of the transaction which successfully claimed the name\n" - "\"n\" (numeric) vout value\n" - "\"amount\" (numeric) txout amount\n" - "\"effective amount\" (numeric) txout amount plus amount from all supports associated with the claim\n" - "\"height\" (numeric) the height of the block in which this transaction is located\n"); - + "\"value\" (string) the value of the name, if it exists\n" + "\"claimId\" (string) the claimId for this name claim\n" + "\"txid\" (string) the hash of the transaction which successfully claimed the name\n" + "\"n\" (numeric) vout value\n" + "\"amount\" (numeric) txout amount\n" + "\"effective amount\" (numeric) txout amount plus amount from all supports associated with the claim\n" + "\"height\" (numeric) the height of the block in which this transaction is located\n" + ); LOCK(cs_main); - - CCoinsViewCache coinsCache(pcoinsTip); - CClaimTrieCache trieCache(pclaimTrie); - - if (params.size() > 1) { - CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(params[1], "blockhash (optional parameter 2)")); - RollBackTo(blockIndex, coinsCache, trieCache); - } - + std::string name = params[0].get_str(); CClaimValue claim; UniValue ret(UniValue::VOBJ); - std::string name = params[0].get_str(); - if (!trieCache.getInfoForName(name, claim)) - return ret; // they may have asked for a name that doesn't exist (which is not an error) - - std::string sValue; - if (!getValueForClaim(coinsCache, claim.outPoint, sValue)) + if (!pclaimTrie->getInfoForName(name, claim)) + return ret; + std::string sValue; + if (!getValueForClaim(claim.outPoint, sValue)) return ret; - - CAmount nEffectiveAmount = trieCache.getEffectiveAmountForClaim(name, claim.claimId); - ret.push_back(Pair("value", sValue)); ret.push_back(Pair("claimId", claim.claimId.GetHex())); ret.push_back(Pair("txid", claim.outPoint.hash.GetHex())); ret.push_back(Pair("n", (int)claim.outPoint.n)); ret.push_back(Pair("amount", claim.nAmount)); - ret.push_back(Pair("effective amount", nEffectiveAmount)); + ret.push_back(Pair("effective amount", pclaimTrie->getEffectiveAmountForClaim(name, claim.claimId))); ret.push_back(Pair("height", claim.nHeight)); return ret; } typedef std::pair > claimAndSupportsType; typedef std::map claimSupportMapType; +typedef std::map > supportsWithoutClaimsMapType; -UniValue supportToJSON(const CSupportValue& support) +UniValue claimsAndSupportsToJSON(claimSupportMapType::const_iterator itClaimsAndSupports, int nCurrentHeight) { UniValue ret(UniValue::VOBJ); - ret.push_back(Pair("txid", support.outPoint.hash.GetHex())); - ret.push_back(Pair("n", (int)support.outPoint.n)); - ret.push_back(Pair("nHeight", support.nHeight)); - ret.push_back(Pair("nValidAtHeight", support.nValidAtHeight)); - ret.push_back(Pair("nAmount", support.nAmount)); - return ret; -} - -UniValue claimAndSupportsToJSON(const CCoinsViewCache& coinsCache, CAmount nEffectiveAmount, claimSupportMapType::const_iterator itClaimsAndSupports) -{ - UniValue ret(UniValue::VOBJ); - const CClaimValue& claim = itClaimsAndSupports->second.first; - const std::vector& supports = itClaimsAndSupports->second.second; + const CClaimValue claim = itClaimsAndSupports->second.first; + const std::vector supports = itClaimsAndSupports->second.second; + CAmount nEffectiveAmount = 0; UniValue supportObjs(UniValue::VARR); - for (std::vector::const_iterator itSupports = supports.begin(); itSupports != supports.end(); ++itSupports) { - supportObjs.push_back(supportToJSON(*itSupports)); + for (std::vector::const_iterator itSupports = supports.begin(); itSupports != supports.end(); ++itSupports) + { + UniValue supportObj(UniValue::VOBJ); + supportObj.push_back(Pair("txid", itSupports->outPoint.hash.GetHex())); + supportObj.push_back(Pair("n", (int)itSupports->outPoint.n)); + supportObj.push_back(Pair("nHeight", itSupports->nHeight)); + supportObj.push_back(Pair("nValidAtHeight", itSupports->nValidAtHeight)); + if (itSupports->nValidAtHeight < nCurrentHeight) + { + nEffectiveAmount += itSupports->nAmount; + } + supportObj.push_back(Pair("nAmount", itSupports->nAmount)); + supportObjs.push_back(supportObj); } ret.push_back(Pair("claimId", itClaimsAndSupports->first.GetHex())); ret.push_back(Pair("txid", claim.outPoint.hash.GetHex())); ret.push_back(Pair("n", (int)claim.outPoint.n)); ret.push_back(Pair("nHeight", claim.nHeight)); ret.push_back(Pair("nValidAtHeight", claim.nValidAtHeight)); + if (claim.nValidAtHeight < nCurrentHeight) + { + nEffectiveAmount += claim.nAmount; + } ret.push_back(Pair("nAmount", claim.nAmount)); std::string sValue; - if (getValueForClaim(coinsCache, claim.outPoint, sValue)) + if (getValueForClaim(claim.outPoint, sValue)) + { ret.push_back(Pair("value", sValue)); + } ret.push_back(Pair("nEffectiveAmount", nEffectiveAmount)); ret.push_back(Pair("supports", supportObjs)); + + return ret; +} + +UniValue supportsWithoutClaimsToJSON(supportsWithoutClaimsMapType::const_iterator itSupportsWithoutClaims, int nCurrentHeight) +{ + const std::vector supports = itSupportsWithoutClaims->second; + UniValue ret(UniValue::VOBJ); + UniValue supportObjs(UniValue::VARR); + ret.push_back(Pair("claimId (no matching claim)", itSupportsWithoutClaims->first.GetHex())); + for (std::vector::const_iterator itSupports = supports.begin(); itSupports != supports.end(); ++itSupports) + { + UniValue supportObj(UniValue::VOBJ); + supportObj.push_back(Pair("txid", itSupports->outPoint.hash.GetHex())); + supportObj.push_back(Pair("n", (int)itSupports->outPoint.n)); + supportObj.push_back(Pair("nHeight", itSupports->nHeight)); + supportObj.push_back(Pair("nValidAtHeight", itSupports->nValidAtHeight)); + supportObj.push_back(Pair("nAmount", itSupports->nAmount)); + supportObjs.push_back(supportObj); + } + ret.push_back(Pair("supports", supportObjs)); return ret; } UniValue getclaimsforname(const UniValue& params, bool fHelp) { - if (fHelp || params.size() > 2) + if (fHelp || params.size() != 1) throw std::runtime_error( "getclaimsforname\n" "Return all claims and supports for a name\n" "Arguments: \n" - "1. \"name\" (string) the name for which to get claims and supports\n" - "2. \"blockhash\" (string, optional) get claims for name\n" - " at the block specified\n" - " by this block hash.\n" - " If none is given,\n" - " the latest active\n" - " block will be used.\n" + "1. \"name\" (string) the name for which to get claims and supports\n" "Result:\n" "{\n" - " \"nLastTakeoverHeight\" (numeric) the last height at which ownership of the name changed\n" - " \"claims\": [ (array of object) claims for this name\n" + " \"nLastTakeoverheight\" (numeric) the last height at which ownership of the name changed\n" + " \"claims\": [ (array of object) claims for this name\n" " {\n" " \"claimId\" (string) the claimId of this claim\n" " \"txid\" (string) the txid of this claim\n" @@ -399,7 +299,6 @@ UniValue getclaimsforname(const UniValue& params, bool fHelp) " \"nHeight\" (numeric) the height at which the claim was included in the blockchain\n" " \"nValidAtHeight\" (numeric) the height at which the claim became/becomes valid\n" " \"nAmount\" (numeric) the amount of the claim\n" - " \"value\" (string) the value of the name, if it exists\n" " \"nEffectiveAmount\" (numeric) the total effective amount of the claim, taking into effect whether the claim or support has reached its nValidAtHeight\n" " \"supports\" : [ (array of object) supports for this claim\n" " \"txid\" (string) the txid of the support\n" @@ -410,7 +309,7 @@ UniValue getclaimsforname(const UniValue& params, bool fHelp) " ]\n" " }\n" " ],\n" - " \"supports without claims\": [ (array of object) supports that did not match a claim for this name\n" + " \"unmatched supports\": [ (array of object) supports that did not match a claim for this name\n" " {\n" " \"txid\" (string) the txid of the support\n" " \"n\" (numeric) the index of the support in the transaction's list of outputs\n" @@ -419,49 +318,49 @@ UniValue getclaimsforname(const UniValue& params, bool fHelp) " \"nAmount\" (numeric) the amount of the support\n" " }\n" " ]\n" - "}\n"); + "}\n" + ); LOCK(cs_main); - - CCoinsViewCache coinsCache(pcoinsTip); - CClaimTrieCache trieCache(pclaimTrie); - - if (params.size() > 1) { - CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(params[1], "blockhash (optional parameter 2)")); - RollBackTo(blockIndex, coinsCache, trieCache); - } - std::string name = params[0].get_str(); - claimsForNameType claimsForName = trieCache.getClaimsForName(name); + claimsForNameType claimsForName = pclaimTrie->getClaimsForName(name); + int nCurrentHeight = chainActive.Height(); - UniValue claimObjs(UniValue::VARR); claimSupportMapType claimSupportMap; - UniValue unmatchedSupports(UniValue::VARR); - - for (std::vector::const_iterator itClaims = claimsForName.claims.begin(); itClaims != claimsForName.claims.end(); ++itClaims) { + supportsWithoutClaimsMapType supportsWithoutClaims; + for (std::vector::const_iterator itClaims = claimsForName.claims.begin(); itClaims != claimsForName.claims.end(); ++itClaims) + { claimAndSupportsType claimAndSupports = std::make_pair(*itClaims, std::vector()); claimSupportMap.insert(std::pair(itClaims->claimId, claimAndSupports)); } - - for (std::vector::const_iterator itSupports = claimsForName.supports.begin(); itSupports != claimsForName.supports.end(); ++itSupports) { + for (std::vector::const_iterator itSupports = claimsForName.supports.begin(); itSupports != claimsForName.supports.end(); ++itSupports) + { claimSupportMapType::iterator itClaimAndSupports = claimSupportMap.find(itSupports->supportedClaimId); - if (itClaimAndSupports == claimSupportMap.end()) { - unmatchedSupports.push_back(supportToJSON(*itSupports)); - } else { + if (itClaimAndSupports == claimSupportMap.end()) + { + std::pair ret = supportsWithoutClaims.insert(std::pair >(itSupports->supportedClaimId, std::vector())); + ret.first->second.push_back(*itSupports); + } + else + { itClaimAndSupports->second.second.push_back(*itSupports); } } - UniValue ret(UniValue::VOBJ); + UniValue claimObjs(UniValue::VARR); ret.push_back(Pair("nLastTakeoverHeight", claimsForName.nLastTakeoverHeight)); - - for (claimSupportMapType::const_iterator itClaimsAndSupports = claimSupportMap.begin(); itClaimsAndSupports != claimSupportMap.end(); ++itClaimsAndSupports) { - CAmount nEffectiveAmount = trieCache.getEffectiveAmountForClaim(claimsForName, itClaimsAndSupports->first); - UniValue claimObj = claimAndSupportsToJSON(coinsCache, nEffectiveAmount, itClaimsAndSupports); - claimObjs.push_back(claimObj); + for (claimSupportMapType::const_iterator itClaimsAndSupports = claimSupportMap.begin(); itClaimsAndSupports != claimSupportMap.end(); ++itClaimsAndSupports) + { + UniValue claimAndSupportsObj = claimsAndSupportsToJSON(itClaimsAndSupports, nCurrentHeight); + claimObjs.push_back(claimAndSupportsObj); } - ret.push_back(Pair("claims", claimObjs)); + UniValue unmatchedSupports(UniValue::VARR); + for (supportsWithoutClaimsMapType::const_iterator itSupportsWithoutClaims = supportsWithoutClaims.begin(); itSupportsWithoutClaims != supportsWithoutClaims.end(); ++itSupportsWithoutClaims) + { + UniValue supportsObj = supportsWithoutClaimsToJSON(itSupportsWithoutClaims, nCurrentHeight); + unmatchedSupports.push_back(supportsObj); + } ret.push_back(Pair("supports without claims", unmatchedSupports)); return ret; } @@ -504,11 +403,11 @@ UniValue getclaimbyid(const UniValue& params, bool fHelp) if (claimValue.claimId == claimId) { std::vector supports; - CAmount effectiveAmount = pclaimTrie->getEffectiveAmountForClaim(name, claimValue.claimId, &supports); + CAmount effectiveAmount = pclaimTrie->getEffectiveAmountForClaimWithSupports( + name, claimValue.claimId, supports); std::string sValue; - CCoinsViewCache coins(pcoinsTip); - getValueForClaim(coins, claimValue.outPoint, sValue); + getValueForClaim(claimValue.outPoint, sValue); claim.push_back(Pair("name", name)); claim.push_back(Pair("value", sValue)); claim.push_back(Pair("claimId", claimValue.claimId.GetHex())); @@ -549,7 +448,7 @@ UniValue gettotalclaimednames(const UniValue& params, bool fHelp) if (!pclaimTrie) { return -1; - } + } unsigned int num_names = pclaimTrie->getTotalNamesInTrie(); return int(num_names); } @@ -632,7 +531,7 @@ UniValue getclaimsfortx(const UniValue& params, bool fHelp) int op; std::vector > vvchParams; - + CCoinsViewCache view(pcoinsTip); const CCoins* coin = view.AccessCoins(hash); std::vector txouts; @@ -831,7 +730,7 @@ UniValue getnameproof(const UniValue& params, bool fHelp) " this will not\n" " exist whether\n" " the node has a\n" - " value or not\n" + " value or not\n" " ]\n" " \"txhash\" : \"hash\" (string, if exists) the txid of the\n" " claim which controls\n" @@ -849,18 +748,29 @@ UniValue getnameproof(const UniValue& params, bool fHelp) "}\n"); LOCK(cs_main); - - CCoinsViewCache coinsCache(pcoinsTip); - CClaimTrieCache trieCache(pclaimTrie); - - if (params.size() == 2) { - CBlockIndex* pblockIndex = BlockHashIndex(ParseHashV(params[1], "blockhash (optional parameter 2)")); - RollBackTo(pblockIndex, coinsCache, trieCache); + std::string strName = params[0].get_str(); + uint256 blockHash; + if (params.size() == 2) + { + blockHash = ParseHashV(params[1], "blockhash (optional parameter 2)"); + } + else + { + blockHash = chainActive.Tip()->GetBlockHash(); } + if (mapBlockIndex.count(blockHash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + + CBlockIndex* pblockIndex = mapBlockIndex[blockHash]; + if (!chainActive.Contains(pblockIndex)) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not in main chain"); + + if (chainActive.Tip()->nHeight > (pblockIndex->nHeight + MAX_RPC_BLOCK_DECREMENTS)) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Block too deep to generate proof"); + CClaimTrieProof proof; - std::string name = params[0].get_str(); - if (!trieCache.getProofForName(name, proof)) + if (!GetProofForName(pblockIndex, strName, proof)) throw JSONRPCError(RPC_INTERNAL_ERROR, "Failed to generate proof"); return proofToJSON(proof); diff --git a/src/test/claimtriebranching_tests.cpp b/src/test/claimtriebranching_tests.cpp index bc5bb8e3f..a25801cb2 100644 --- a/src/test/claimtriebranching_tests.cpp +++ b/src/test/claimtriebranching_tests.cpp @@ -12,7 +12,6 @@ #include "nameclaim.h" #include "policy/policy.h" #include "primitives/transaction.h" -#include "rpc/server.h" #include "streams.h" #include "test/test_bitcoin.h" #include "txmempool.h" @@ -26,15 +25,14 @@ BOOST_FIXTURE_TEST_SUITE(claimtriebranching_tests, RegTestingSetup) //is a claim in queue boost::test_tools::predicate_result -is_claim_in_queue(std::string name, const CTransaction &tx) +is_claim_in_queue(std::string name, const CTransaction& tx) { COutPoint outPoint(tx.GetHash(), 0); int validAtHeight; bool have_claim = pclaimTrie->haveClaimInQueue(name, outPoint, validAtHeight); - if (have_claim){ + if (have_claim) { return true; - } - else{ + } else { boost::test_tools::predicate_result res(false); res.message() << "Is not a claim in queue."; return res; @@ -43,16 +41,15 @@ is_claim_in_queue(std::string name, const CTransaction &tx) // check if tx is best claim based on outpoint boost::test_tools::predicate_result -is_best_claim(std::string name, const CTransaction &tx) +is_best_claim(std::string name, const CTransaction& tx) { CClaimValue val; COutPoint outPoint(tx.GetHash(), 0); bool have_claim = pclaimTrie->haveClaim(name, outPoint); bool have_info = pclaimTrie->getInfoForName(name, val); - if (have_claim && have_info && val.outPoint == outPoint){ + if (have_claim && have_info && val.outPoint == outPoint) { return true; - } - else{ + } else { boost::test_tools::predicate_result res(false); res.message() << "Is not best claim"; return res; @@ -64,29 +61,23 @@ best_claim_effective_amount_equals(std::string name, CAmount amount) { CClaimValue val; bool have_info = pclaimTrie->getInfoForName(name, val); - if (!have_info) - { + if (!have_info) { boost::test_tools::predicate_result res(false); - res.message()<<"No claim found"; + res.message() << "No claim found"; return res; - } - else - { + } else { CAmount effective_amount = pclaimTrie->getEffectiveAmountForClaim(name, val.claimId); - if (effective_amount != amount) - { + if (effective_amount != amount) { boost::test_tools::predicate_result res(false); - res.message()<WriteToDisk(); pclaimTrie->clear(); - pclaimTrie->ReadFromDisk(true); + BOOST_CHECK(pclaimTrie->ReadFromDisk(true)); } }; @@ -345,62 +326,62 @@ BOOST_AUTO_TEST_CASE(claim_test) { // no competing bids ClaimTrieChainFixture fixture; - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx1)); + BOOST_CHECK(is_best_claim("test", tx1)); fixture.DecrementBlocks(1); - BOOST_CHECK(!is_best_claim("test",tx1)); + BOOST_CHECK(!is_best_claim("test", tx1)); // there is a competing bid inserted same height - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); - CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); + CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx3)); + BOOST_CHECK(is_best_claim("test", tx3)); BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); fixture.DecrementBlocks(1); - BOOST_CHECK(!is_best_claim("test",tx2)); - BOOST_CHECK(!is_best_claim("test",tx3)); + BOOST_CHECK(!is_best_claim("test", tx2)); + BOOST_CHECK(!is_best_claim("test", tx3)); BOOST_CHECK_EQUAL(0U, pclaimTrie->getClaimsForName("test").claims.size()); // make two claims , one older - CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); + CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx4)); - CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(),"test","two",1); + BOOST_CHECK(is_best_claim("test", tx4)); + CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "two", 1); fixture.IncrementBlocks(1); - BOOST_CHECK(is_claim_in_queue("test",tx5)); + BOOST_CHECK(is_claim_in_queue("test", tx5)); BOOST_CHECK(is_best_claim("test", tx4)); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx4)); + BOOST_CHECK(is_best_claim("test", tx4)); BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); fixture.DecrementBlocks(1); BOOST_CHECK(is_best_claim("test", tx4)); - BOOST_CHECK(is_claim_in_queue("test",tx5)); + BOOST_CHECK(is_claim_in_queue("test", tx5)); fixture.DecrementBlocks(1); BOOST_CHECK(is_best_claim("test", tx4)); fixture.DecrementBlocks(1); // check claim takeover, note that CClaimTrie.nProportionalDelayFactor is set to 1 // instead of 32 in test_bitcoin.cpp - CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); + CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); fixture.IncrementBlocks(10); - BOOST_CHECK(is_best_claim("test",tx6)); - CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(),"test","two",2); + BOOST_CHECK(is_best_claim("test", tx6)); + CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "two", 2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_claim_in_queue("test",tx7)); + BOOST_CHECK(is_claim_in_queue("test", tx7)); BOOST_CHECK(is_best_claim("test", tx6)); fixture.IncrementBlocks(10); - BOOST_CHECK(is_best_claim("test",tx7)); + BOOST_CHECK(is_best_claim("test", tx7)); BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); fixture.DecrementBlocks(10); - BOOST_CHECK(is_claim_in_queue("test",tx7)); + BOOST_CHECK(is_claim_in_queue("test", tx7)); BOOST_CHECK(is_best_claim("test", tx6)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx6)); + BOOST_CHECK(is_best_claim("test", tx6)); fixture.DecrementBlocks(10); } @@ -415,8 +396,8 @@ BOOST_AUTO_TEST_CASE(spend_claim_test) ClaimTrieChainFixture fixture; // spending winning claim will make losing active claim winner - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); fixture.IncrementBlocks(1); BOOST_CHECK(is_best_claim("test", tx1)); fixture.Spend(tx1); @@ -429,34 +410,34 @@ BOOST_AUTO_TEST_CASE(spend_claim_test) // spending winning claim will make inactive claim winner - CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(10); - BOOST_CHECK(is_best_claim("test",tx3)); - CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + BOOST_CHECK(is_best_claim("test", tx3)); + CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx3)); + BOOST_CHECK(is_best_claim("test", tx3)); fixture.Spend(tx3); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx4)); + BOOST_CHECK(is_best_claim("test", tx4)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx3)); + BOOST_CHECK(is_best_claim("test", tx3)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx3)); + BOOST_CHECK(is_best_claim("test", tx3)); fixture.DecrementBlocks(10); //spending winning claim will empty out claim trie - CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx5)); + BOOST_CHECK(is_best_claim("test", tx5)); fixture.Spend(tx5); fixture.IncrementBlocks(1); - BOOST_CHECK(!is_best_claim("test",tx5)); + BOOST_CHECK(!is_best_claim("test", tx5)); BOOST_CHECK(pclaimTrie->empty()); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx5)); + BOOST_CHECK(is_best_claim("test", tx5)); fixture.DecrementBlocks(1); } @@ -471,35 +452,35 @@ BOOST_AUTO_TEST_CASE(support_test) { ClaimTrieChainFixture fixture; // check claim with more support wins - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); - CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx1,"test",1); - CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(),tx2,"test",10); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 1); + CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(), tx2, "test", 10); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx2)); - BOOST_CHECK(best_claim_effective_amount_equals("test",11)); + BOOST_CHECK(is_best_claim("test", tx2)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 11)); fixture.DecrementBlocks(1); // check support delay - CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); - CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(),"test","two",2); + CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); + CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "two", 2); fixture.IncrementBlocks(10); - BOOST_CHECK(is_best_claim("test",tx4)); - BOOST_CHECK(best_claim_effective_amount_equals("test",2)); + BOOST_CHECK(is_best_claim("test", tx4)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 2)); CMutableTransaction s4 = fixture.MakeSupport(fixture.GetCoinbase(), tx3, "test", 10); //10 delay fixture.IncrementBlocks(10); - BOOST_CHECK(is_best_claim("test",tx4)); - BOOST_CHECK(best_claim_effective_amount_equals("test",2)); + BOOST_CHECK(is_best_claim("test", tx4)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 2)); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx3)); - BOOST_CHECK(best_claim_effective_amount_equals("test",11)); + BOOST_CHECK(is_best_claim("test", tx3)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 11)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx4)); - BOOST_CHECK(best_claim_effective_amount_equals("test",2)); + BOOST_CHECK(is_best_claim("test", tx4)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 2)); fixture.DecrementBlocks(10); BOOST_CHECK(is_best_claim("test", tx4)); - BOOST_CHECK(best_claim_effective_amount_equals("test",2)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 2)); fixture.DecrementBlocks(10); } @@ -514,35 +495,34 @@ BOOST_AUTO_TEST_CASE(support_test) BOOST_AUTO_TEST_CASE(support_on_abandon_test) { ClaimTrieChainFixture fixture; - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(1); //supporting and abandoing on the same block will cause it to crash - CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx1,"test",1); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 1); fixture.Spend(tx1); fixture.IncrementBlocks(1); - BOOST_CHECK(!is_best_claim("test",tx1)); + BOOST_CHECK(!is_best_claim("test", tx1)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx1)); - + BOOST_CHECK(is_best_claim("test", tx1)); } BOOST_AUTO_TEST_CASE(support_on_abandon_2_test) { ClaimTrieChainFixture fixture; - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); - CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx1,"test",1); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 1); fixture.IncrementBlocks(1); //abandoning a support and abandoing claim on the same block will cause it to crash fixture.Spend(tx1); fixture.Spend(s1); fixture.IncrementBlocks(1); - BOOST_CHECK(!is_best_claim("test",tx1)); + BOOST_CHECK(!is_best_claim("test", tx1)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx1)); + BOOST_CHECK(is_best_claim("test", tx1)); } BOOST_AUTO_TEST_CASE(update_on_support_test) @@ -551,15 +531,15 @@ BOOST_AUTO_TEST_CASE(update_on_support_test) // updates happening on the same block as a support // (it should not) ClaimTrieChainFixture fixture; - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",3); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 3); fixture.IncrementBlocks(1); - CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx1,"test",1); - CMutableTransaction u1 = fixture.MakeUpdate(tx1,"test","two",ClaimIdHash(tx1.GetHash(),0),1); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 1); + CMutableTransaction u1 = fixture.MakeUpdate(tx1, "test", "two", ClaimIdHash(tx1.GetHash(), 0), 1); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",u1)); - BOOST_CHECK(best_claim_effective_amount_equals("test",2)); + BOOST_CHECK(is_best_claim("test", u1)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 2)); fixture.DecrementBlocks(1); BOOST_CHECK(is_best_claim("test", tx1)); @@ -573,29 +553,28 @@ BOOST_AUTO_TEST_CASE(update_on_support_test) */ BOOST_AUTO_TEST_CASE(support_spend_test) { - ClaimTrieChainFixture fixture; - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); - CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx1,"test",2); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 2); fixture.IncrementBlocks(1); BOOST_CHECK(is_best_claim("test", tx1)); CMutableTransaction sp1 = fixture.Spend(s1); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx2)); + BOOST_CHECK(is_best_claim("test", tx2)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx1)); + BOOST_CHECK(is_best_claim("test", tx1)); fixture.DecrementBlocks(1); // spend a support on txin[i] where i is not 0 - CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"x","one",3); - CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(),"test","two",2); - CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(),"test","three",1); - CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(),tx5,"test",2); + CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "x", "one", 3); + CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "two", 2); + CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "three", 1); + CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(), tx5, "test", 2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx5)); + BOOST_CHECK(is_best_claim("test", tx5)); BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); // build the spend where s2 is sppent on txin[1] and tx3 is spent on txin[0] @@ -621,7 +600,7 @@ BOOST_AUTO_TEST_CASE(support_spend_test) BOOST_CHECK(is_best_claim("test", tx4)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx5)); + BOOST_CHECK(is_best_claim("test", tx5)); } /* update @@ -637,50 +616,50 @@ BOOST_AUTO_TEST_CASE(claimtrie_update_test) { //update preserves claim id ClaimTrieChainFixture fixture; - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); CMutableTransaction u1 = fixture.MakeUpdate(tx1, "test", "one", ClaimIdHash(tx1.GetHash(), 0), 2); fixture.IncrementBlocks(1); CClaimValue val; - pclaimTrie->getInfoForName("test",val); - BOOST_CHECK(val.claimId == ClaimIdHash(tx1.GetHash(),0)); - BOOST_CHECK(is_best_claim("test",u1)); + pclaimTrie->getInfoForName("test", val); + BOOST_CHECK(val.claimId == ClaimIdHash(tx1.GetHash(), 0)); + BOOST_CHECK(is_best_claim("test", u1)); fixture.DecrementBlocks(1); // update preserves supports - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx2, "test", 1); CMutableTransaction u2 = fixture.MakeUpdate(tx2, "test", "one", ClaimIdHash(tx2.GetHash(), 0), 1); fixture.IncrementBlocks(1); - BOOST_CHECK(best_claim_effective_amount_equals("test",2)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 2)); fixture.DecrementBlocks(1); // winning update on winning claim happens without delay - CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); - CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); + CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); + CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); fixture.IncrementBlocks(10); CMutableTransaction u3 = fixture.MakeUpdate(tx3, "test", "one", ClaimIdHash(tx3.GetHash(), 0), 2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",u3)); + BOOST_CHECK(is_best_claim("test", u3)); BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); fixture.DecrementBlocks(11); // losing update on winning claim happens without delay - CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",3); - CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 3); + CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(10); BOOST_CHECK(is_best_claim("test", tx5)); BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); CMutableTransaction u4 = fixture.MakeUpdate(tx5, "test", "one", ClaimIdHash(tx5.GetHash(), 0), 1); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx6)); + BOOST_CHECK(is_best_claim("test", tx6)); fixture.DecrementBlocks(1); BOOST_CHECK(is_best_claim("test", tx5)); fixture.DecrementBlocks(10); // update on losing claim happens with delay , and wins - CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",3); - CMutableTransaction tx8 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 3); + CMutableTransaction tx8 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(10); BOOST_CHECK(is_best_claim("test", tx7)); @@ -697,17 +676,17 @@ BOOST_AUTO_TEST_CASE(claimtrie_update_test) tx.vin[1].prevout.n = 0; tx.vin[1].scriptSig = CScript(); tx.vin[1].nSequence = std::numeric_limits::max(); - tx.vout[0].scriptPubKey = UpdateClaimScript("test",ClaimIdHash(tx8.GetHash(),0),"one"); + tx.vout[0].scriptPubKey = UpdateClaimScript("test", ClaimIdHash(tx8.GetHash(), 0), "one"); tx.vout[0].nValue = 4; fixture.CommitTx(tx); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx7)); + BOOST_CHECK(is_best_claim("test", tx7)); fixture.IncrementBlocks(10); - BOOST_CHECK(is_best_claim("test",tx)); + BOOST_CHECK(is_best_claim("test", tx)); fixture.DecrementBlocks(10); - BOOST_CHECK(is_best_claim("test",tx7)); + BOOST_CHECK(is_best_claim("test", tx7)); fixture.DecrementBlocks(11); } @@ -723,58 +702,58 @@ BOOST_AUTO_TEST_CASE(claimtrie_expire_test) pclaimTrie->setExpirationTime(5); // check claims expire and loses claim - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(pclaimTrie->nExpirationTime); - BOOST_CHECK(is_best_claim("test",tx1)); - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); + BOOST_CHECK(is_best_claim("test", tx1)); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx2)); + BOOST_CHECK(is_best_claim("test", tx2)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx1)); + BOOST_CHECK(is_best_claim("test", tx1)); fixture.DecrementBlocks(pclaimTrie->nExpirationTime); // check claims expire and is not updateable (may be changed in future soft fork) - CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx3)); + BOOST_CHECK(is_best_claim("test", tx3)); fixture.IncrementBlocks(pclaimTrie->nExpirationTime); - CMutableTransaction u1 = fixture.MakeUpdate(tx3,"test","two",ClaimIdHash(tx3.GetHash(),0) ,2); - BOOST_CHECK(!is_best_claim("test",u1)); + CMutableTransaction u1 = fixture.MakeUpdate(tx3, "test", "two", ClaimIdHash(tx3.GetHash(), 0), 2); + BOOST_CHECK(!is_best_claim("test", u1)); fixture.DecrementBlocks(pclaimTrie->nExpirationTime); - BOOST_CHECK(is_best_claim("test",tx3)); + BOOST_CHECK(is_best_claim("test", tx3)); fixture.DecrementBlocks(1); // check supports expire and can cause supported bid to lose claim - CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); - CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); - CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx4,"test",2); + CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); + CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx4, "test", 2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx4)); - CMutableTransaction u2 = fixture.MakeUpdate(tx4,"test","two",ClaimIdHash(tx4.GetHash(),0) ,1); - CMutableTransaction u3 = fixture.MakeUpdate(tx5,"test","two",ClaimIdHash(tx5.GetHash(),0) ,2); + BOOST_CHECK(is_best_claim("test", tx4)); + CMutableTransaction u2 = fixture.MakeUpdate(tx4, "test", "two", ClaimIdHash(tx4.GetHash(), 0), 1); + CMutableTransaction u3 = fixture.MakeUpdate(tx5, "test", "two", ClaimIdHash(tx5.GetHash(), 0), 2); fixture.IncrementBlocks(pclaimTrie->nExpirationTime); - BOOST_CHECK(is_best_claim("test",u3)); + BOOST_CHECK(is_best_claim("test", u3)); fixture.DecrementBlocks(pclaimTrie->nExpirationTime); - BOOST_CHECK(is_best_claim("test",tx4)); + BOOST_CHECK(is_best_claim("test", tx4)); fixture.DecrementBlocks(1); // check updated claims will extend expiration - CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx6)); - CMutableTransaction u4 = fixture.MakeUpdate(tx6,"test","two",ClaimIdHash(tx6.GetHash(),0) ,2); + BOOST_CHECK(is_best_claim("test", tx6)); + CMutableTransaction u4 = fixture.MakeUpdate(tx6, "test", "two", ClaimIdHash(tx6.GetHash(), 0), 2); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",u4)); - fixture.IncrementBlocks(pclaimTrie->nExpirationTime-1); - BOOST_CHECK(is_best_claim("test",u4)); + BOOST_CHECK(is_best_claim("test", u4)); + fixture.IncrementBlocks(pclaimTrie->nExpirationTime - 1); + BOOST_CHECK(is_best_claim("test", u4)); fixture.IncrementBlocks(1); - BOOST_CHECK(!is_best_claim("test",u4)); + BOOST_CHECK(!is_best_claim("test", u4)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",u4)); + BOOST_CHECK(is_best_claim("test", u4)); fixture.DecrementBlocks(pclaimTrie->nExpirationTime); - BOOST_CHECK(is_best_claim("test",tx6)); + BOOST_CHECK(is_best_claim("test", tx6)); } /* @@ -883,6 +862,89 @@ BOOST_AUTO_TEST_CASE(get_claim_by_id_test) BOOST_CHECK(claimValue2.claimId != claimId); } +BOOST_AUTO_TEST_CASE(get_claim_by_id_test_2) +{ + ClaimTrieChainFixture fixture; + const std::string name = "test"; + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 1); + uint160 claimId = ClaimIdHash(tx1.GetHash(), 0); + CMutableTransaction txx = fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 1); + uint160 claimIdx = ClaimIdHash(txx.GetHash(), 0); + + fixture.IncrementBlocks(1); + + CClaimValue claimValue; + std::string claimName; + pclaimTrie->getClaimById(claimId, claimName, claimValue); + BOOST_CHECK(claimName == name); + BOOST_CHECK(claimValue.claimId == claimId); + + CMutableTransaction txa = fixture.Spend(tx1); + CMutableTransaction txb = fixture.Spend(txx); + + fixture.IncrementBlocks(1); + BOOST_CHECK(!pclaimTrie->getClaimById(claimId, claimName, claimValue)); + BOOST_CHECK(!pclaimTrie->getClaimById(claimIdx, claimName, claimValue)); + + fixture.DecrementBlocks(1); + pclaimTrie->getClaimById(claimId, claimName, claimValue); + BOOST_CHECK(claimName == name); + BOOST_CHECK(claimValue.claimId == claimId); + + pclaimTrie->getClaimById(claimIdx, claimName, claimValue); + BOOST_CHECK(claimName == name); + BOOST_CHECK(claimValue.claimId == claimIdx); +} + +BOOST_AUTO_TEST_CASE(get_claim_by_id_test_3) +{ + ClaimTrieChainFixture fixture; + pclaimTrie->setExpirationTime(5); + const std::string name = "test"; + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 1); + uint160 claimId = ClaimIdHash(tx1.GetHash(), 0); + + fixture.IncrementBlocks(1); + + CClaimValue claimValue; + std::string claimName; + pclaimTrie->getClaimById(claimId, claimName, claimValue); + BOOST_CHECK(claimName == name); + BOOST_CHECK(claimValue.claimId == claimId); + // make second claim with activation delay 1 + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 2); + uint160 claimId2 = ClaimIdHash(tx2.GetHash(), 0); + + fixture.IncrementBlocks(1); + // second claim is not activated yet, but can still access by claim id + BOOST_CHECK(is_best_claim(name, tx1)); + BOOST_CHECK(pclaimTrie->getClaimById(claimId2, claimName, claimValue)); + BOOST_CHECK(claimName == name); + BOOST_CHECK(claimValue.claimId == claimId2); + + fixture.IncrementBlocks(1); + // second claim has activated + BOOST_CHECK(is_best_claim(name, tx2)); + BOOST_CHECK(pclaimTrie->getClaimById(claimId2, claimName, claimValue)); + BOOST_CHECK(claimName == name); + BOOST_CHECK(claimValue.claimId == claimId2); + + fixture.DecrementBlocks(1); + // second claim has been deactivated via decrement + // should still be accesible via claim id + BOOST_CHECK(is_best_claim(name, tx1)); + BOOST_CHECK(pclaimTrie->getClaimById(claimId2, claimName, claimValue)); + BOOST_CHECK(claimName == name); + BOOST_CHECK(claimValue.claimId == claimId2); + + fixture.IncrementBlocks(1); + // second claim should have been re activated via increment + BOOST_CHECK(is_best_claim(name, tx2)); + BOOST_CHECK(pclaimTrie->getClaimById(claimId2, claimName, claimValue)); + BOOST_CHECK(claimName == name); + BOOST_CHECK(claimValue.claimId == claimId2); +} + /* claim expiration for hard fork check claims do not expire post ExpirationForkHeight @@ -894,19 +956,19 @@ BOOST_AUTO_TEST_CASE(hardfork_claim_test) BOOST_CHECK_EQUAL(pclaimTrie->nExpirationTime, fixture.originalExpiration); // First create a claim and make sure it expires pre-fork - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",3); - fixture.IncrementBlocks(fixture.originalExpiration+1); - BOOST_CHECK(!is_best_claim("test",tx1)); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 3); + fixture.IncrementBlocks(fixture.originalExpiration + 1); + BOOST_CHECK(!is_best_claim("test", tx1)); fixture.DecrementBlocks(fixture.originalExpiration); - BOOST_CHECK(is_best_claim("test",tx1)); + BOOST_CHECK(is_best_claim("test", tx1)); fixture.IncrementBlocks(fixture.originalExpiration); - BOOST_CHECK(!is_best_claim("test",tx1)); + BOOST_CHECK(!is_best_claim("test", tx1)); // Create a claim 1 block before the fork height that will expire after the fork height - fixture.IncrementBlocks(fixture.expirationForkHeight - chainActive.Height() -2); - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test2","one",3); + fixture.IncrementBlocks(fixture.expirationForkHeight - chainActive.Height() - 2); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "test2", "one", 3); fixture.IncrementBlocks(1); - BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight -1); + BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight - 1); // Disable future expirations and fast-forward past the fork height fixture.IncrementBlocks(1); @@ -921,49 +983,49 @@ BOOST_AUTO_TEST_CASE(hardfork_claim_test) // make sure that claim created 1 block before the fork expires as expected // at the extended expiration times BOOST_CHECK(is_best_claim("test2", tx2)); - fixture.IncrementBlocks(fixture.extendedExpiration-1); + fixture.IncrementBlocks(fixture.extendedExpiration - 1); BOOST_CHECK(!is_best_claim("test2", tx2)); - fixture.DecrementBlocks(fixture.extendedExpiration-1); + fixture.DecrementBlocks(fixture.extendedExpiration - 1); // This first claim is still expired since it's pre-fork, even // after fork activation - BOOST_CHECK(!is_best_claim("test",tx1)); + BOOST_CHECK(!is_best_claim("test", tx1)); // This new claim created at the fork height cannot expire at original expiration BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight); - CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); + CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); fixture.IncrementBlocks(1); fixture.IncrementBlocks(fixture.originalExpiration); - BOOST_CHECK(is_best_claim("test",tx3)); - BOOST_CHECK(!is_best_claim("test",tx1)); + BOOST_CHECK(is_best_claim("test", tx3)); + BOOST_CHECK(!is_best_claim("test", tx1)); fixture.DecrementBlocks(fixture.originalExpiration); // but it expires at the extended expiration, and not a single block below fixture.IncrementBlocks(fixture.extendedExpiration); - BOOST_CHECK(!is_best_claim("test",tx3)); + BOOST_CHECK(!is_best_claim("test", tx3)); fixture.DecrementBlocks(fixture.extendedExpiration); - fixture.IncrementBlocks(fixture.extendedExpiration-1); - BOOST_CHECK(is_best_claim("test",tx3)); - fixture.DecrementBlocks(fixture.extendedExpiration-1); + fixture.IncrementBlocks(fixture.extendedExpiration - 1); + BOOST_CHECK(is_best_claim("test", tx3)); + fixture.DecrementBlocks(fixture.extendedExpiration - 1); // Ensure that we cannot update the original pre-fork expired claim - CMutableTransaction u1 = fixture.MakeUpdate(tx1,"test","two",ClaimIdHash(tx1.GetHash(),0), 3); + CMutableTransaction u1 = fixture.MakeUpdate(tx1, "test", "two", ClaimIdHash(tx1.GetHash(), 0), 3); fixture.IncrementBlocks(1); - BOOST_CHECK(!is_best_claim("test",u1)); + BOOST_CHECK(!is_best_claim("test", u1)); // Ensure that supports for the expired claim don't support it - CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),u1,"test",10); - BOOST_CHECK(!is_best_claim("test",u1)); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), u1, "test", 10); + BOOST_CHECK(!is_best_claim("test", u1)); // Ensure that we can update the new post-fork claim - CMutableTransaction u2 = fixture.MakeUpdate(tx3,"test","two",ClaimIdHash(tx3.GetHash(),0), 1); + CMutableTransaction u2 = fixture.MakeUpdate(tx3, "test", "two", ClaimIdHash(tx3.GetHash(), 0), 1); fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("test",u2)); + BOOST_CHECK(is_best_claim("test", u2)); // Ensure that supports for the new post-fork claim - CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(),u2,"test",3); - BOOST_CHECK(is_best_claim("test",u2)); + CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(), u2, "test", 3); + BOOST_CHECK(is_best_claim("test", u2)); } /* @@ -976,105 +1038,45 @@ BOOST_AUTO_TEST_CASE(hardfork_support_test) int blocks_before_fork = 10; fixture.IncrementBlocks(fixture.expirationForkHeight - chainActive.Height() - blocks_before_fork - 1); // Create claim and support it before the fork height - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); - CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx1,"test",2); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 2); // this claim will win without the support - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2); fixture.IncrementBlocks(1); fixture.IncrementBlocks(blocks_before_fork); // check that the claim expires as expected at the extended time, as does the support fixture.IncrementBlocks(fixture.originalExpiration - blocks_before_fork); - BOOST_CHECK(is_best_claim("test",tx1)); - BOOST_CHECK(best_claim_effective_amount_equals("test",3)); + BOOST_CHECK(is_best_claim("test", tx1)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 3)); fixture.DecrementBlocks(fixture.originalExpiration - blocks_before_fork); fixture.IncrementBlocks(fixture.extendedExpiration - blocks_before_fork); - BOOST_CHECK(!is_best_claim("test",tx1)); + BOOST_CHECK(!is_best_claim("test", tx1)); fixture.DecrementBlocks(fixture.extendedExpiration - blocks_before_fork); fixture.IncrementBlocks(fixture.extendedExpiration - blocks_before_fork - 1); - BOOST_CHECK(is_best_claim("test",tx1)); - BOOST_CHECK(best_claim_effective_amount_equals("test",3)); + BOOST_CHECK(is_best_claim("test", tx1)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 3)); fixture.DecrementBlocks(fixture.extendedExpiration - blocks_before_fork - 1); // update the claims at fork fixture.DecrementBlocks(1); - CMutableTransaction u1 = fixture.MakeUpdate(tx1,"test","two",ClaimIdHash(tx1.GetHash(),0),1); - CMutableTransaction u2 = fixture.MakeUpdate(tx2,"test","two",ClaimIdHash(tx2.GetHash(),0),2); + CMutableTransaction u1 = fixture.MakeUpdate(tx1, "test", "two", ClaimIdHash(tx1.GetHash(), 0), 1); + CMutableTransaction u2 = fixture.MakeUpdate(tx2, "test", "two", ClaimIdHash(tx2.GetHash(), 0), 2); fixture.IncrementBlocks(1); BOOST_CHECK_EQUAL(fixture.expirationForkHeight, chainActive.Height()); BOOST_CHECK(is_best_claim("test", u1)); - BOOST_CHECK(best_claim_effective_amount_equals("test",3)); - BOOST_CHECK(!is_claim_in_queue("test",tx1)); - BOOST_CHECK(!is_claim_in_queue("test",tx2)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 3)); + BOOST_CHECK(!is_claim_in_queue("test", tx1)); + BOOST_CHECK(!is_claim_in_queue("test", tx2)); // check that the support expires as expected fixture.IncrementBlocks(fixture.extendedExpiration - blocks_before_fork); BOOST_CHECK(is_best_claim("test", u2)); fixture.DecrementBlocks(fixture.extendedExpiration - blocks_before_fork); fixture.IncrementBlocks(fixture.extendedExpiration - blocks_before_fork - 1); - BOOST_CHECK(is_best_claim("test",u1)); - BOOST_CHECK(best_claim_effective_amount_equals("test",3)); - -} - -/* - activation_fall_through and supports_fall_through - Tests for where claims/supports in queues would be undone properly in a decrement. - See https://github.com/lbryio/lbrycrd/issues/243 for more details -*/ - -BOOST_AUTO_TEST_CASE(activations_fall_through) -{ - ClaimTrieChainFixture fixture; - - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 1); - fixture.IncrementBlocks(3); - BOOST_CHECK(pclaimTrie->nProportionalDelayFactor == 1); - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "2", 3); - fixture.IncrementBlocks(1); - - BOOST_CHECK(is_best_claim("A", tx1)); - fixture.IncrementBlocks(3); - BOOST_CHECK(is_best_claim("A", tx2)); - fixture.DecrementBlocks(3); - fixture.Spend(tx1); // this will trigger early activation on tx2 claim - fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("A", tx2)); - fixture.DecrementBlocks(1); //reorg the early activation - BOOST_CHECK(is_best_claim("A", tx1)); - fixture.Spend(tx1); - fixture.IncrementBlocks(1); // this should not cause tx2 to activate again and crash - BOOST_CHECK(is_best_claim("A", tx2)); -} - -BOOST_AUTO_TEST_CASE(supports_fall_through) -{ - ClaimTrieChainFixture fixture; - - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 3); - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "2", 1); - CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "3", 2); - fixture.IncrementBlocks(3); - BOOST_CHECK(pclaimTrie->nProportionalDelayFactor == 1); - CMutableTransaction sx2 = fixture.MakeSupport(fixture.GetCoinbase(), tx2, "A", 3); - fixture.IncrementBlocks(1); - - BOOST_CHECK(is_best_claim("A", tx1)); - fixture.IncrementBlocks(3); - BOOST_CHECK(is_best_claim("A", tx2)); - fixture.DecrementBlocks(3); - fixture.Spend(tx1); // this will trigger early activation - fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("A", tx2)); - fixture.DecrementBlocks(1); // reorg the early activation - BOOST_CHECK(is_best_claim("A", tx1)); - fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("A", tx1)); //tx2 support should not be active - fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("A", tx1)); //tx2 support should not be active - fixture.IncrementBlocks(1); - BOOST_CHECK(is_best_claim("A", tx2)); //tx2 support should be active now + BOOST_CHECK(is_best_claim("test", u1)); + BOOST_CHECK(best_claim_effective_amount_equals("test", 3)); } /* @@ -1096,38 +1098,38 @@ BOOST_AUTO_TEST_CASE(hardfork_disk_test) // Reset to disk, increment past the fork height and make sure we get // proper behavior fixture.DecrementBlocks(2); - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); - CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),tx1,"test",1); + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1); + CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 1); fixture.IncrementBlocks(1); - BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight -1); + BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight - 1); fixture.WriteClearReadClaimTrie(); - BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight-1); + BOOST_CHECK_EQUAL(chainActive.Height(), fixture.expirationForkHeight - 1); BOOST_CHECK_EQUAL(pclaimTrie->nExpirationTime, fixture.originalExpiration); fixture.IncrementBlocks(1); BOOST_CHECK_EQUAL(pclaimTrie->nExpirationTime, fixture.extendedExpiration); BOOST_CHECK(is_best_claim("test", tx1)); - BOOST_CHECK(best_claim_effective_amount_equals("test",2)); - fixture.IncrementBlocks(fixture.originalExpiration-1); + BOOST_CHECK(best_claim_effective_amount_equals("test", 2)); + fixture.IncrementBlocks(fixture.originalExpiration - 1); BOOST_CHECK(is_best_claim("test", tx1)); - BOOST_CHECK(best_claim_effective_amount_equals("test",2)); - fixture.DecrementBlocks(fixture.originalExpiration-1); - fixture.IncrementBlocks(fixture.extendedExpiration-1); + BOOST_CHECK(best_claim_effective_amount_equals("test", 2)); + fixture.DecrementBlocks(fixture.originalExpiration - 1); + fixture.IncrementBlocks(fixture.extendedExpiration - 1); BOOST_CHECK(!is_best_claim("test", tx1)); // Create a claim and support before the fork height, reset to disk, update the claim // increment past the fork height and make sure we get proper behavior - int height_of_update_before_expiration = 50; - fixture.DecrementBlocks(chainActive.Height() - fixture.expirationForkHeight + height_of_update_before_expiration+2); - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test2","one",1); - CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(),tx2,"test2",1); + int height_of_update_before_expiration = 50; + fixture.DecrementBlocks(chainActive.Height() - fixture.expirationForkHeight + height_of_update_before_expiration + 2); + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "test2", "one", 1); + CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(), tx2, "test2", 1); fixture.IncrementBlocks(1); fixture.WriteClearReadClaimTrie(); - CMutableTransaction u2 = fixture.MakeUpdate(tx2,"test2","two",ClaimIdHash(tx2.GetHash(),0),1); + CMutableTransaction u2 = fixture.MakeUpdate(tx2, "test2", "two", ClaimIdHash(tx2.GetHash(), 0), 1); // increment to fork fixture.IncrementBlocks(fixture.expirationForkHeight - chainActive.Height()); BOOST_CHECK(is_best_claim("test2", u2)); - BOOST_CHECK(best_claim_effective_amount_equals("test2",2)); + BOOST_CHECK(best_claim_effective_amount_equals("test2", 2)); // increment to original expiration, should not be expired fixture.IncrementBlocks(fixture.originalExpiration - height_of_update_before_expiration); BOOST_CHECK(is_best_claim("test2", u2)); @@ -1956,29 +1958,6 @@ BOOST_AUTO_TEST_CASE(claimtrienode_serialize_unserialize) BOOST_CHECK(n1 == n2); } -BOOST_AUTO_TEST_CASE(claimtrienode_remove_invalid_claim) -{ - uint160 hash160; - - CClaimTrieNode n1; - CClaimTrieNode n2; - CClaimValue throwaway; - - CClaimValue v1(COutPoint(uint256S("0000000000000000000000000000000000000000000000000000000000000001"), 0), hash160, 50, 0, 100); - CClaimValue v2(COutPoint(uint256S("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), 1), hash160, 100, 1, 101); - - n1.insertClaim(v1); - - n2.insertClaim(v2); - - bool invalidClaim = n2.removeClaim(v1.outPoint, throwaway); - BOOST_CHECK(invalidClaim == false); - - invalidClaim = n1.removeClaim(v2.outPoint, throwaway); - BOOST_CHECK(invalidClaim == false); -} - - BOOST_AUTO_TEST_CASE(invalid_claimid_test) { ClaimTrieChainFixture fixture; @@ -3011,31 +2990,31 @@ BOOST_AUTO_TEST_CASE(value_proof_test) CClaimTrieProof proof; - BOOST_CHECK(cache.getProofForName(sName1, proof)); + proof = cache.getProofForName(sName1); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName1)); BOOST_CHECK(proof.outPoint == tx1OutPoint); - BOOST_CHECK(cache.getProofForName(sName2, proof)); + proof = cache.getProofForName(sName2); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName2)); BOOST_CHECK(proof.outPoint == tx2OutPoint); - BOOST_CHECK(cache.getProofForName(sName3, proof)); + proof = cache.getProofForName(sName3); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName3)); BOOST_CHECK(proof.outPoint == tx3OutPoint); - BOOST_CHECK(cache.getProofForName(sName4, proof)); + proof = cache.getProofForName(sName4); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName4)); BOOST_CHECK(proof.outPoint == tx4OutPoint); - BOOST_CHECK(cache.getProofForName(sName5, proof)); + proof = cache.getProofForName(sName5); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName5)); BOOST_CHECK(proof.hasValue == false); - BOOST_CHECK(cache.getProofForName(sName6, proof)); + proof = cache.getProofForName(sName6); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName6)); BOOST_CHECK(proof.hasValue == false); - BOOST_CHECK(cache.getProofForName(sName7, proof)); + proof = cache.getProofForName(sName7); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName7)); BOOST_CHECK(proof.hasValue == false); @@ -3049,31 +3028,31 @@ BOOST_AUTO_TEST_CASE(value_proof_test) cache = CClaimTrieCache(pclaimTrie); - BOOST_CHECK(cache.getProofForName(sName1, proof)); + proof = cache.getProofForName(sName1); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName1)); BOOST_CHECK(proof.outPoint == tx1OutPoint); - BOOST_CHECK(cache.getProofForName(sName2, proof)); + proof = cache.getProofForName(sName2); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName2)); BOOST_CHECK(proof.outPoint == tx2OutPoint); - BOOST_CHECK(cache.getProofForName(sName3, proof)); + proof = cache.getProofForName(sName3); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName3)); BOOST_CHECK(proof.outPoint == tx3OutPoint); - BOOST_CHECK(cache.getProofForName(sName4, proof)); + proof = cache.getProofForName(sName4); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName4)); BOOST_CHECK(proof.outPoint == tx4OutPoint); - BOOST_CHECK(cache.getProofForName(sName5, proof)); + proof = cache.getProofForName(sName5); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName5)); BOOST_CHECK(proof.hasValue == false); - BOOST_CHECK(cache.getProofForName(sName6, proof)); + proof = cache.getProofForName(sName6); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName6)); BOOST_CHECK(proof.hasValue == false); - BOOST_CHECK(cache.getProofForName(sName7, proof)); + proof = cache.getProofForName(sName7); BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName7)); BOOST_CHECK(proof.outPoint == tx5OutPoint); @@ -3125,336 +3104,4 @@ BOOST_AUTO_TEST_CASE(bogus_claimtrie_hash_test) delete pblockTemp; } -/* - * tests for CClaimTrie::getClaimById basic consistency checks - */ -BOOST_AUTO_TEST_CASE(get_claim_by_id_test_2) -{ - ClaimTrieChainFixture fixture; - const std::string name = "test"; - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 1); - uint160 claimId = ClaimIdHash(tx1.GetHash(), 0); - CMutableTransaction txx = fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 1); - uint160 claimIdx = ClaimIdHash(txx.GetHash(), 0); - - fixture.IncrementBlocks(1); - - CClaimValue claimValue; - std::string claimName; - pclaimTrie->getClaimById(claimId, claimName, claimValue); - BOOST_CHECK(claimName == name); - BOOST_CHECK(claimValue.claimId == claimId); - - CMutableTransaction txa = fixture.Spend(tx1); - CMutableTransaction txb = fixture.Spend(txx); - - fixture.IncrementBlocks(1); - BOOST_CHECK(!pclaimTrie->getClaimById(claimId, claimName, claimValue)); - BOOST_CHECK(!pclaimTrie->getClaimById(claimIdx, claimName, claimValue)); - - fixture.DecrementBlocks(1); - pclaimTrie->getClaimById(claimId, claimName, claimValue); - BOOST_CHECK(claimName == name); - BOOST_CHECK(claimValue.claimId == claimId); - - // this test fails - pclaimTrie->getClaimById(claimIdx, claimName, claimValue); - BOOST_CHECK(claimName == name); - BOOST_CHECK(claimValue.claimId == claimIdx); -} - -BOOST_AUTO_TEST_CASE(get_claim_by_id_test_3) -{ - ClaimTrieChainFixture fixture; - pclaimTrie->setExpirationTime(5); - const std::string name = "test"; - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 1); - uint160 claimId = ClaimIdHash(tx1.GetHash(), 0); - - fixture.IncrementBlocks(1); - - CClaimValue claimValue; - std::string claimName; - pclaimTrie->getClaimById(claimId, claimName, claimValue); - BOOST_CHECK(claimName == name); - BOOST_CHECK(claimValue.claimId == claimId); - // make second claim with activation delay 1 - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 2); - uint160 claimId2 = ClaimIdHash(tx2.GetHash(), 0); - - fixture.IncrementBlocks(1); - // second claim is not activated yet, but can still access by claim id - BOOST_CHECK(is_best_claim(name, tx1)); - BOOST_CHECK(pclaimTrie->getClaimById(claimId2, claimName, claimValue)); - BOOST_CHECK(claimName == name); - BOOST_CHECK(claimValue.claimId == claimId2); - - fixture.IncrementBlocks(1); - // second claim has activated - BOOST_CHECK(is_best_claim(name, tx2)); - BOOST_CHECK(pclaimTrie->getClaimById(claimId2, claimName, claimValue)); - BOOST_CHECK(claimName == name); - BOOST_CHECK(claimValue.claimId == claimId2); - - - fixture.DecrementBlocks(1); - // second claim has been deactivated via decrement - // should still be accesible via claim id - BOOST_CHECK(is_best_claim(name, tx1)); - BOOST_CHECK(pclaimTrie->getClaimById(claimId2, claimName, claimValue)); - BOOST_CHECK(claimName == name); - BOOST_CHECK(claimValue.claimId == claimId2); - - fixture.IncrementBlocks(1); - // second claim should have been re activated via increment - BOOST_CHECK(is_best_claim(name, tx2)); - BOOST_CHECK(pclaimTrie->getClaimById(claimId2, claimName, claimValue)); - BOOST_CHECK(claimName == name); - BOOST_CHECK(claimValue.claimId == claimId2); -} - -BOOST_AUTO_TEST_CASE(getclaimsintrie_test) -{ - ClaimTrieChainFixture fixture; - std::string sName1("test"); - std::string sValue1("test"); - std::string sName2("test2"); - std::string sValue2("test2"); - - fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 42); - fixture.IncrementBlocks(1); - - uint256 blockHash = chainActive.Tip()->GetBlockHash(); - - fixture.MakeClaim(fixture.GetCoinbase(), sName2, sValue2, 43); - fixture.IncrementBlocks(1); - - rpcfn_type getclaimsintrie = tableRPC["getclaimsintrie"]->actor; - UniValue params(UniValue::VARR); - - UniValue results = getclaimsintrie(params, false); - BOOST_CHECK(results.size() == 2U); - BOOST_CHECK(results[0]["name"].get_str() == sName1); - BOOST_CHECK(results[1]["name"].get_str() == sName2); - - params.push_back(blockHash.GetHex()); - - results = getclaimsintrie(params, false); - BOOST_CHECK(results.size() == 1U); - BOOST_CHECK(results[0]["name"].get_str() == sName1); -} - -BOOST_AUTO_TEST_CASE(getclaimsintrie_test2) -{ - ClaimTrieChainFixture fixture; - std::string sName1("test"); - std::string sValue1("test"); - - uint256 blockHash = chainActive.Tip()->GetBlockHash(); - - rpcfn_type getclaimsintrie = tableRPC["getclaimsintrie"]->actor; - rpcfn_type getclaimtrie = tableRPC["getclaimtrie"]->actor; - UniValue params(UniValue::VARR); - params.push_back(blockHash.GetHex()); - UniValue results = getclaimsintrie(params, false); - BOOST_CHECK(results.size() == 0U); - results = getclaimtrie(params, false); - BOOST_CHECK(results.size() == 1U); - - fixture.IncrementBlocks(10); - fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 42); - fixture.IncrementBlocks(10); - results = getclaimsintrie(params, false); - BOOST_CHECK(results.size() == 0U); - results = getclaimtrie(params, false); - BOOST_CHECK(results.size() == 1U); -} - -BOOST_AUTO_TEST_CASE(getclaimtrie_test) -{ - ClaimTrieChainFixture fixture; - std::string sName1("test"); - std::string sValue1("test"); - std::string sName2("test2"); - std::string sValue2("test2"); - - int height = chainActive.Height(); - - fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 42); - fixture.IncrementBlocks(1); - - uint256 blockHash = chainActive.Tip()->GetBlockHash(); - - fixture.MakeClaim(fixture.GetCoinbase(), sName2, sValue2, 43); - fixture.IncrementBlocks(1); - - rpcfn_type getclaimtrie = tableRPC["getclaimtrie"]->actor; - UniValue params(UniValue::VARR); - - UniValue results = getclaimtrie(params, false); - BOOST_CHECK(results.size() == 6U); - BOOST_CHECK(results[4]["name"].get_str() == sName1); - BOOST_CHECK(results[5]["name"].get_str() == sName2); - BOOST_CHECK(results[4]["height"].get_int() == height + 1); - BOOST_CHECK(results[5]["height"].get_int() == height + 2); - - params.push_back(blockHash.GetHex()); - - results = getclaimtrie(params, false); - BOOST_CHECK(results.size() == 5U); - BOOST_CHECK(results[4]["name"].get_str() == sName1); - BOOST_CHECK(results[4]["height"].get_int() == height + 1); -} - -BOOST_AUTO_TEST_CASE(getvalueforname_test) -{ - ClaimTrieChainFixture fixture; - std::string sName1("testN"); - std::string sValue1("testV"); - - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 2); - fixture.IncrementBlocks(1); - - uint256 blockHash = chainActive.Tip()->GetBlockHash(); - - fixture.MakeSupport(fixture.GetCoinbase(), tx1, sName1, 3); - fixture.IncrementBlocks(10); - - rpcfn_type getvalueforname = tableRPC["getvalueforname"]->actor; - UniValue params(UniValue::VARR); - params.push_back(UniValue(sName1)); - - UniValue results = getvalueforname(params, false); - BOOST_CHECK(results["value"].get_str() == sValue1); - BOOST_CHECK(results["amount"].get_int() == 2); - BOOST_CHECK(results["effective amount"].get_int() == 5); - - params.push_back(blockHash.GetHex()); - - results = getvalueforname(params, false); - BOOST_CHECK(results["amount"].get_int() == 2); - BOOST_CHECK(results["effective amount"].get_int() == 2); -} - -BOOST_AUTO_TEST_CASE(getclaimsforname_test) -{ - ClaimTrieChainFixture fixture; - std::string sName1("testN"); - std::string sValue1("test1"); - std::string sValue2("test2"); - - int height = chainActive.Height(); - - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 2); - fixture.IncrementBlocks(1); - - uint256 blockHash = chainActive.Tip()->GetBlockHash(); - - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue2, 3); - fixture.IncrementBlocks(1); - - rpcfn_type getclaimsforname = tableRPC["getclaimsforname"]->actor; - UniValue params(UniValue::VARR); - params.push_back(UniValue(sName1)); - - UniValue results = getclaimsforname(params, false); - UniValue claims = results["claims"]; - BOOST_CHECK(claims.size() == 2U); - BOOST_CHECK(results["nLastTakeoverHeight"].get_int() == height + 1); - BOOST_CHECK(claims[0]["nEffectiveAmount"].get_int() == 0); - BOOST_CHECK(claims[1]["nEffectiveAmount"].get_int() == 2); - BOOST_CHECK(claims[0]["supports"].size() == 0U); - BOOST_CHECK(claims[1]["supports"].size() == 0U); - - fixture.IncrementBlocks(1); - - results = getclaimsforname(params, false); - claims = results["claims"]; - BOOST_CHECK(claims.size() == 2U); - BOOST_CHECK(results["nLastTakeoverHeight"].get_int() == height + 3); - BOOST_CHECK(claims[0]["nEffectiveAmount"].get_int() == 3); - BOOST_CHECK(claims[1]["nEffectiveAmount"].get_int() == 2); - BOOST_CHECK(claims[0]["supports"].size() == 0U); - BOOST_CHECK(claims[1]["supports"].size() == 0U); - - params.push_back(blockHash.GetHex()); - - results = getclaimsforname(params, false); - claims = results["claims"]; - BOOST_CHECK(claims.size() == 1U); - BOOST_CHECK(results["nLastTakeoverHeight"].get_int() == height + 1); - BOOST_CHECK(claims[0]["nEffectiveAmount"].get_int() == 2); - BOOST_CHECK(claims[0]["supports"].size() == 0U); -} - -BOOST_AUTO_TEST_CASE(claim_rpcs_rollback2_test) -{ - ClaimTrieChainFixture fixture; - std::string sName1("testN"); - std::string sValue1("test1"); - std::string sValue2("test2"); - - int height = chainActive.Height(); - - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 1); - fixture.IncrementBlocks(2); - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue2, 2); - fixture.IncrementBlocks(3); - - uint256 blockHash = chainActive.Tip()->GetBlockHash(); - - CMutableTransaction tx3 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, sValue1, 3); - fixture.IncrementBlocks(1); - - rpcfn_type getclaimsforname = tableRPC["getclaimsforname"]->actor; - rpcfn_type getvalueforname = tableRPC["getvalueforname"]->actor; - - UniValue params(UniValue::VARR); - params.push_back(UniValue(sName1)); - params.push_back(blockHash.GetHex()); - - UniValue claimsResults = getclaimsforname(params, false); - BOOST_CHECK(claimsResults["nLastTakeoverHeight"].get_int() == height + 5); - BOOST_CHECK(claimsResults["claims"][0]["supports"].size() == 0U); - BOOST_CHECK(claimsResults["claims"][1]["supports"].size() == 0U); - - UniValue valueResults = getvalueforname(params, false); - BOOST_CHECK(valueResults["value"].get_str() == sValue2); - BOOST_CHECK(valueResults["amount"].get_int() == 2); -} - -BOOST_AUTO_TEST_CASE(claim_rpcs_rollback3_test) -{ - ClaimTrieChainFixture fixture; - std::string sName1("testN"); - std::string sValue1("test1"); - std::string sValue2("test2"); - - int height = chainActive.Height(); - - CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 3); - fixture.IncrementBlocks(1); - CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue2, 2); - fixture.IncrementBlocks(2); - - uint256 blockHash = chainActive.Tip()->GetBlockHash(); - - CMutableTransaction tx3 = fixture.Spend(tx1); // abandon the claim - fixture.IncrementBlocks(1); - - rpcfn_type getclaimsforname = tableRPC["getclaimsforname"]->actor; - rpcfn_type getvalueforname = tableRPC["getvalueforname"]->actor; - - UniValue params(UniValue::VARR); - params.push_back(UniValue(sName1)); - params.push_back(blockHash.GetHex()); - - UniValue claimsResults = getclaimsforname(params, false); - BOOST_CHECK(claimsResults["nLastTakeoverHeight"].get_int() == height + 1); - - UniValue valueResults = getvalueforname(params, false); - BOOST_CHECK(valueResults["value"].get_str() == sValue1); - BOOST_CHECK(valueResults["amount"].get_int() == 3); -} - BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/claimtriecache_tests.cpp b/src/test/claimtriecache_tests.cpp index aa06fd19e..28dc60855 100644 --- a/src/test/claimtriecache_tests.cpp +++ b/src/test/claimtriecache_tests.cpp @@ -1,6 +1,5 @@ #include "claimtrie.h" #include "main.h" -#include "nameclaim.h" #include "uint256.h" #include "test/test_bitcoin.h" @@ -19,16 +18,10 @@ public: return CClaimTrieCache::recursiveComputeMerkleHash(tnCurrent, sPos); } - bool recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, std::string sName, bool* pfNullified) const + bool recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, std::string sName, bool* pfNullified) { return CClaimTrieCache::recursivePruneName(tnCurrent,nPos,sName, pfNullified); } - - bool insertSupportIntoMap(const std::string& name, CSupportValue support, bool fCheckTakeover) const - { - return CClaimTrieCache::insertSupportIntoMap(name, support, fCheckTakeover); - } - int cacheSize() { return cache.size(); @@ -194,48 +187,6 @@ BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test) BOOST_CHECK(pclaimTrie->checkConsistency()); } -BOOST_AUTO_TEST_CASE(basic_insertion_info_test) -{ - // test basic claim insertions and that get methods retreives information properly - BOOST_CHECK(pclaimTrie->empty()); - CClaimTrieCacheTest ctc(pclaimTrie); - - // create and insert claim - CClaimValue unused; - uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); - CMutableTransaction tx1 = BuildTransaction(hash0); - uint160 claimId = ClaimIdHash(tx1.GetHash(), 0); - COutPoint claimOutPoint(tx1.GetHash(), 0); - CAmount amount(10); - int height = 0; - int validHeight = 0; - CClaimValue claimVal(claimOutPoint, claimId, amount, height, validHeight); - ctc.insertClaimIntoTrie("test", claimVal); - - // try getClaimsForName, getEffectiveAmountForClaim, getInfoForName - claimsForNameType res = ctc.getClaimsForName("test"); - BOOST_CHECK(res.claims.size() == 1); - BOOST_CHECK(res.claims[0] == claimVal); - - BOOST_CHECK_EQUAL(10, ctc.getEffectiveAmountForClaim("test", claimId)); - - CClaimValue claim; - BOOST_CHECK(ctc.getInfoForName("test", claim)); - BOOST_CHECK(claim == claimVal); - - // insert a support - CAmount supportAmount(10); - uint256 hash1(uint256S("0000000000000000000000000000000000000000000000000000000000000002")); - CMutableTransaction tx2 = BuildTransaction(hash1); - COutPoint supportOutPoint(tx2.GetHash(), 0); - - CSupportValue support(supportOutPoint, claimId, supportAmount, height, validHeight); - ctc.insertSupportIntoMap("test", support, false); - - // try getEffectiveAmount - BOOST_CHECK_EQUAL(20, ctc.getEffectiveAmountForClaim("test", claimId)); -} - BOOST_AUTO_TEST_CASE(recursive_prune_test) { CClaimTrieCacheTest cc(pclaimTrie); @@ -274,58 +225,5 @@ BOOST_AUTO_TEST_CASE(recursive_prune_test) BOOST_CHECK_EQUAL(0, it->second->children.size()); } -BOOST_AUTO_TEST_CASE(iteratetrie_test) -{ - BOOST_CHECK(pclaimTrie->empty()); - CClaimTrieCacheTest ctc(pclaimTrie); - - uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); - CMutableTransaction tx1 = BuildTransaction(hash0); - - const uint256 txhash = tx1.GetHash(); - CClaimValue claimVal(COutPoint(txhash, 0), ClaimIdHash(txhash, 0), CAmount(10), 0, 0); - ctc.insertClaimIntoTrie("test", claimVal); - - - int count = 0; - - struct TestCallBack : public CNodeCallback { - TestCallBack(int& count) : count(count) - { - } - - void visit(const std::string& name, const CClaimTrieNode* node) - { - count++; - if (name == "test") { - BOOST_CHECK(node->claims.size() == 1); - } - } - - int& count; - } testCallback(count); - - BOOST_CHECK(ctc.iterateTrie(testCallback)); - BOOST_CHECK(count == 5); - - count = 3; - - struct TestCallBack2 : public CNodeCallback { - TestCallBack2(int& count) : count(count) - { - } - - void visit(const std::string& name, const CClaimTrieNode* node) - { - if (--count <= 0) - throw CRecursionInterruptionException(false); - } - - int& count; - } testCallback2(count); - - BOOST_CHECK(!ctc.iterateTrie(testCallback2)); - BOOST_CHECK(count == 0); -} BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/claimtriedb_tests.cpp b/src/test/claimtriedb_tests.cpp new file mode 100644 index 000000000..ef64d427f --- /dev/null +++ b/src/test/claimtriedb_tests.cpp @@ -0,0 +1,91 @@ +#include "claimtrie.h" +#include "main.h" +#include "uint256.h" + +#include "test/test_bitcoin.h" +#include +using namespace std; + +BOOST_FIXTURE_TEST_SUITE(claimtriedb_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(compatibility_test) +{ + const int value = 20; + const std::string test("test"); + + CClaimTrieNode base_node; + const CClaimValue test_claim(COutPoint(), uint160(), CAmount(value), 0, 0); + const CClaimIndexElement test_element = {test, test_claim}; + const CSupportValue test_support(COutPoint(), uint160(), CAmount(value), 0, 0); + + base_node.claims.push_back(test_claim); + const supportMapEntryType supportMap(1, test_support); + const queueNameRowType nameRows(1, outPointHeightType(COutPoint(), value)); + const claimQueueRowType claimRows(1, claimQueueEntryType(test, test_claim)); + const supportQueueRowType supportRows(1, supportQueueEntryType(test, test_support)); + const expirationQueueRowType expirationRows(1, nameOutPointType(test, COutPoint())); + const supportQueueNameRowType supportNameRows(1, outPointHeightType(COutPoint(), value)); + const supportExpirationQueueRowType supportExpirationRows(1, nameOutPointType(test, COutPoint())); + + CClaimTrieDb db(true, false); + + /// fill out char keys + db.Write(std::make_pair('n', test), base_node); + db.Write(std::make_pair('i', uint160()), test_element); + db.Write(std::make_pair('r', value), claimRows); + db.Write(std::make_pair('m', test), nameRows); + db.Write(std::make_pair('e', value), expirationRows); + db.Write(std::make_pair('s', test), supportMap); + db.Write(std::make_pair('u', value), supportRows); + db.Write(std::make_pair('p', test), supportNameRows); + db.Write(std::make_pair('x', value), supportExpirationRows); + db.Sync(); + + /// it should read same by types + CClaimTrieNode node; + db.getQueueRow(test, node); + BOOST_CHECK(node == base_node); + + CClaimIndexElement element; + db.getQueueRow(uint160(), element); + BOOST_CHECK(element.name == test_element.name); + BOOST_CHECK(element.claim == test_element.claim); + + claimQueueRowType claims; + db.getQueueRow(value, claims); + BOOST_CHECK(claims.size() == 1); + BOOST_CHECK(claims[0].first == claimRows[0].first); + BOOST_CHECK(claims[0].second == claimRows[0].second); + + queueNameRowType names; + db.getQueueRow(test, names); + BOOST_CHECK(names.size() == 1); + BOOST_CHECK(names[0].nHeight == nameRows[0].nHeight); + + expirationQueueRowType exps; + db.getQueueRow(value, exps); + BOOST_CHECK(exps.size() == 1); + BOOST_CHECK(exps[0].name == expirationRows[0].name); + + supportMapEntryType sups; + db.getQueueRow(test, sups); + BOOST_CHECK(sups.size() == 1); + BOOST_CHECK(sups[0] == supportMap[0]); + + supportQueueRowType supRows; + db.getQueueRow(value, supRows); + BOOST_CHECK(supRows.size() == 1); + BOOST_CHECK(supRows[0] == supportRows[0]); + + supportQueueNameRowType supNames; + db.getQueueRow(test, supNames); + BOOST_CHECK(supNames.size() == 1); + BOOST_CHECK(supNames[0].nHeight == supportNameRows[0].nHeight); + + supportExpirationQueueRowType supExps; + db.getQueueRow(value, supExps); + BOOST_CHECK(supExps.size() == 1); + BOOST_CHECK(supExps[0].name == supportExpirationRows[0].name); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/txdb.h b/src/txdb.h index 9186aab61..749802f0e 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -20,7 +20,7 @@ struct CDiskTxPos; class uint256; //! -dbcache default (MiB) -static const int64_t nDefaultDbCache = sizeof(void*) > 4 ? 700 : 500; +static const int64_t nDefaultDbCache = 100; //! max. -dbcache in (MiB) static const int64_t nMaxDbCache = sizeof(void*) > 4 ? 16384 : 1024; //! min. -dbcache in (MiB) diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index 5b7878b32..95aa4c259 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -58,17 +58,15 @@ bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector (nCLen); - EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); - if (!ctx) return false; + EVP_CIPHER_CTX ctx; bool fOk = true; - EVP_CIPHER_CTX_init(ctx); - if (fOk) fOk = EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, chKey, chIV) != 0; - if (fOk) fOk = EVP_EncryptUpdate(ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen) != 0; - if (fOk) fOk = EVP_EncryptFinal_ex(ctx, (&vchCiphertext[0]) + nCLen, &nFLen) != 0; - EVP_CIPHER_CTX_cleanup(ctx); - EVP_CIPHER_CTX_free(ctx); + EVP_CIPHER_CTX_init(&ctx); + if (fOk) fOk = EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV) != 0; + if (fOk) fOk = EVP_EncryptUpdate(&ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen) != 0; + if (fOk) fOk = EVP_EncryptFinal_ex(&ctx, (&vchCiphertext[0]) + nCLen, &nFLen) != 0; + EVP_CIPHER_CTX_cleanup(&ctx); if (!fOk) return false; @@ -87,17 +85,15 @@ bool CCrypter::Decrypt(const std::vector& vchCiphertext, CKeyingM vchPlaintext = CKeyingMaterial(nPLen); - EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); - if (!ctx) return false; + EVP_CIPHER_CTX ctx; bool fOk = true; - EVP_CIPHER_CTX_init(ctx); - if (fOk) fOk = EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, chKey, chIV) != 0; - if (fOk) fOk = EVP_DecryptUpdate(ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen) != 0; - if (fOk) fOk = EVP_DecryptFinal_ex(ctx, (&vchPlaintext[0]) + nPLen, &nFLen) != 0; - EVP_CIPHER_CTX_cleanup(ctx); - EVP_CIPHER_CTX_free(ctx); + EVP_CIPHER_CTX_init(&ctx); + if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV) != 0; + if (fOk) fOk = EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen) != 0; + if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0]) + nPLen, &nFLen) != 0; + EVP_CIPHER_CTX_cleanup(&ctx); if (!fOk) return false;