diff --git a/.github/workflows/komodo_mac_ci.yml b/.github/workflows/komodo_mac_ci.yml index c6a606aa725..1c25dbce07a 100644 --- a/.github/workflows/komodo_mac_ci.yml +++ b/.github/workflows/komodo_mac_ci.yml @@ -18,7 +18,7 @@ jobs: - name: Install deps (macOS) run: | brew update - brew upgrade + brew upgrade || true brew tap discoteq/discoteq; brew install flock brew install autoconf autogen automake brew install gcc@8 diff --git a/.github/workflows/komodo_win_ci.yml b/.github/workflows/komodo_win_ci.yml index b74370575bf..e1e100a8cfd 100644 --- a/.github/workflows/komodo_win_ci.yml +++ b/.github/workflows/komodo_win_ci.yml @@ -32,7 +32,7 @@ jobs: libncurses-dev \ unzip \ git \ - python \ + python3 \ zlib1g-dev \ wget \ bsdmainutils \ diff --git a/.github/workflows/komodod_cd.yml b/.github/workflows/komodod_cd.yml index 55f8c8404a5..6e97169e049 100644 --- a/.github/workflows/komodod_cd.yml +++ b/.github/workflows/komodod_cd.yml @@ -16,7 +16,7 @@ jobs: linux-build: name: Linux Build # using there as old release as possible with GHA worker to provide better compatibility - runs-on: ubuntu-16.04 + runs-on: ubuntu-20.04 steps: - name: Extract branch name @@ -79,7 +79,7 @@ jobs: - name: Install deps (macOS) run: | brew update - brew upgrade + brew upgrade || true brew tap discoteq/discoteq; brew install flock brew install autoconf autogen automake brew install gcc@8 diff --git a/.gitignore b/.gitignore index 2f85c6d195f..f875a16f921 100644 --- a/.gitignore +++ b/.gitignore @@ -161,5 +161,5 @@ Makefile.in configure doc/man/Makefile.in src/Makefile.in -src/cc/customcc.so +src/cc/libcc.so src/libcc.so diff --git a/Dockerfile.release b/Dockerfile.release index 9fef9424885..a10340fe2e9 100644 --- a/Dockerfile.release +++ b/Dockerfile.release @@ -1,4 +1,4 @@ -FROM ubuntu:18.04 +FROM ubuntu:20.04 RUN \ apt-get update &&\ apt-get install -y libgomp1 diff --git a/Makefile.am b/Makefile.am index 51d0430aca4..71a0d5f53b3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -344,3 +344,6 @@ DISTCHECK_CONFIGURE_FLAGS = --enable-man clean-local: rm -rf test_bitcoin.coverage/ zcash-gtest.coverage/ total.coverage/ + +clean-all: clean-local + $(MAKE) -C src clean-all diff --git a/README.md b/README.md index c8f99f2e16f..9568c70741a 100644 --- a/README.md +++ b/README.md @@ -58,11 +58,11 @@ Komodo is based on Zcash and has been extended by our innovative consensus algor ## Getting started -### Dependencies +### Dependencies (Ubuntu 20.04) ```shell #The following packages are needed: -sudo apt-get install build-essential pkg-config libc6-dev m4 g++-multilib autoconf libtool ncurses-dev unzip git python python-zmq zlib1g-dev wget libcurl4-gnutls-dev bsdmainutils automake curl libsodium-dev +sudo apt-get install build-essential pkg-config libc6-dev m4 g++-multilib autoconf libtool ncurses-dev unzip git python3 python3-zmq zlib1g-dev wget libcurl4-gnutls-dev bsdmainutils automake curl libsodium-dev ``` ### Build Komodo diff --git a/SECURITY.md b/SECURITY.md index 6bcbe7706fc..9ff0e03ac4d 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -9,22 +9,19 @@ Hash: SHA256 Contact: security@komodoplatform.com Contact: ca333@komodoplatform.com Contact: noashh@komodoplatform.com -Encryption: http://pgp.key-server.io:11371/0x379287998EE6CF47 ------BEGIN PGP SIGNATURE----- +Encryption: https://keys.openpgp.org/vks/v1/by-fingerprint/7D49C41069D4A78FFAC2B7232D420826CF311F19 +-----BEGIN PGP PUBLIC KEY BLOCK----- -iQJNBAEBCAA3FiEEVez5U2AlPa805zvqN5KHmY7mz0cFAlz6EuMZHGNhMzMzQGtv -bW9kb3BsYXRmb3JtLmNvbQAKCRA3koeZjubPR8cIEACP+JjyXDIzjgIewMMi/02b -tsYswPyQ+9bAoEJnis3r94d1FP1rqXmt4oNz6VwFTqQLEa5opW+gvvaxBTFJSPb0 -UzbS+1PjfAOox5cnT3Dnv9kcy4ECslnW/G+mH+85BUgz1HuqYc8A3kNQJL7KqLoi -YeD0Hd09KtlG+B4PWdnqLw/uvfbavSKdMn6WSIU6adNZWX0ewSubWPXvrWea5cI2 -yKDdMcDqB8Sc9J4JR2L9zW8NqPQuaxfLQbkCt2tg9QjlClrAqQgb8OZQJgY9f1T/ -kBlVXoA4ZUZeifvjSKxQ/3TdRFP+jbV9xsb6sr14zTx+Wcoqtgsh3l9F4+T3V2m8 -/c/iS4mFlK31pJtwYyrJAq9hpggqymdCVi0Pa3yLZsEj3orBPaPWbmq2v7xeF3J8 -y8vqAkt3M3T6251aZAKEcaN5RXYJW70CTseadwp0tmrAL2nIVmziNCMOF+Bufyxi -HddkasTcNX8VYfPCLWqBwrocx8d3n3E7dBGeS2x2iwuRVQ85pH5d+imxaMftcbqm -YrNuiqcI/0XDGk9pS6f1gpu5Eh5Q2QXGmOoRlfosfkAEfgFxfaMvmcu5Ay1s0gSR -MsTn0PrQyMYC3t3KpyP47C8ui9x7FtJFltR/QT4yzBF1QyDmINnK86ldQqSui402 -2+gQFt7YFvLIBUiy1fh1Jw== -=UITq ------END PGP SIGNATURE----- +mDMEY+62mRYJKwYBBAHaRw8BAQdAqK7CMI2SFtioUIFLSbpUq6QSmnWueIBTKJpB +Ar15JBS0LUtvbW9kbyBTZWN1cml0eSA8c2VjdXJpdHlAa29tb2RvcGxhdGZvcm0u +Y29tPoiZBBMWCgBBFiEEfUnEEGnUp4/6wrcjLUIIJs8xHxkFAmPutpkCGwMFCQPC +ZwAFCwkIBwICIgIGFQoJCAsCBBYCAwECHgcCF4AACgkQLUIIJs8xHxlU6AD/e/Z8 +T6w7AdNM6fXU/UXoyLU09BL+GBt/GU6RHXx1L9gBALyQFiyeFCEt4pbqkAYfp6l3 +GQ8W9r5x1V480mYPCesPuDgEY+62mRIKKwYBBAGXVQEFAQEHQNxl9WfOg69rsUPo +gu03kiyEyXY1bctRmiRsYhJ5NKRcAwEIB4h+BBgWCgAmFiEEfUnEEGnUp4/6wrcj +LUIIJs8xHxkFAmPutpkCGwwFCQPCZwAACgkQLUIIJs8xHxmRIQEA1Yy+bAqf7ZMJ +mDfSs67TPShM7/N7DpEDxvMcnFENyJIBALq2kCSyBYBUuPYbPUunMq3LwkNS/GUz +oH/1cpSRTLUF +=hTp/ +-----END PGP PUBLIC KEY BLOCK----- ``` diff --git a/configure.ac b/configure.ac index 2c9485c633f..937f6060c91 100644 --- a/configure.ac +++ b/configure.ac @@ -1,13 +1,13 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) -define(_CLIENT_VERSION_MINOR, 7) -define(_CLIENT_VERSION_REVISION, 2) +define(_CLIENT_VERSION_MINOR, 8) +define(_CLIENT_VERSION_REVISION, 0) define(_CLIENT_VERSION_BUILD, 0) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) -define(_COPYRIGHT_YEAR, 2022) +define(_COPYRIGHT_YEAR, 2023) AC_INIT([Komodo],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_SUFFIX(_ZC_BUILD_VAL)],[https://github.com/KomodoPlatform/komodo/issues],[komodo]) AC_CONFIG_SRCDIR([src/main.cpp]) AC_CONFIG_HEADERS([src/config/bitcoin-config.h]) @@ -199,7 +199,7 @@ AC_LANG_PUSH([C++]) AX_CHECK_COMPILE_FLAG([-Werror],[CXXFLAG_WERROR="-Werror"],[CXXFLAG_WERROR=""]) if test "x$enable_debug" = xyes; then - CPPFLAGS="$CPPFLAGS -DDEBUG -DDEBUG_LOCKORDER" + CPPFLAGS="$CPPFLAGS -DDEBUG" if test "x$GCC" = xyes; then CFLAGS="$CFLAGS -g3 -O0" fi diff --git a/depends/hosts/darwin.mk b/depends/hosts/darwin.mk index 7be744aebc0..43a4c88f2ab 100644 --- a/depends/hosts/darwin.mk +++ b/depends/hosts/darwin.mk @@ -8,10 +8,10 @@ darwin_CXX=g++-8 -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysro darwin_CFLAGS=-pipe darwin_CXXFLAGS=$(darwin_CFLAGS) -darwin_release_CFLAGS=-O1 +darwin_release_CFLAGS=-g -O2 darwin_release_CXXFLAGS=$(darwin_release_CFLAGS) -darwin_debug_CFLAGS=-O1 +darwin_debug_CFLAGS=-g -O0 darwin_debug_CXXFLAGS=$(darwin_debug_CFLAGS) darwin_native_toolchain=native_cctools diff --git a/depends/hosts/linux.mk b/depends/hosts/linux.mk index 31748d66226..857fe783079 100644 --- a/depends/hosts/linux.mk +++ b/depends/hosts/linux.mk @@ -1,12 +1,11 @@ linux_CFLAGS=-pipe linux_CXXFLAGS=$(linux_CFLAGS) -linux_release_CFLAGS=-O1 +linux_release_CFLAGS=-g -O2 linux_release_CXXFLAGS=$(linux_release_CFLAGS) -linux_debug_CFLAGS=-O1 +linux_debug_CFLAGS=-g -O0 linux_debug_CXXFLAGS=$(linux_debug_CFLAGS) - linux_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC ifeq (86,$(findstring 86,$(build_arch))) diff --git a/depends/hosts/mingw32.mk b/depends/hosts/mingw32.mk index b217bfdb547..857850b05b1 100644 --- a/depends/hosts/mingw32.mk +++ b/depends/hosts/mingw32.mk @@ -1,12 +1,11 @@ mingw32_CC=x86_64-w64-mingw32-gcc-posix mingw32_CXX=x86_64-w64-mingw32-g++-posix mingw32_CFLAGS=-pipe -std=c11 -mingw32_CXXFLAGS=$(mingw32_CFLAGS) -std=c++11 +mingw32_CXXFLAGS=-pipe -std=c++11 -mingw32_release_CFLAGS=-O1 -mingw32_release_CXXFLAGS=$(mingw32_release_CFLAGS) - -mingw32_debug_CFLAGS=-O1 -mingw32_debug_CXXFLAGS=$(mingw32_debug_CFLAGS) +mingw32_release_CFLAGS=-g -O2 +mingw32_release_CXXFLAGS=$(mingw32_CXXFLAGS) $(mingw32_release_CFLAGS) +mingw32_debug_CFLAGS=-g -O0 mingw32_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC +mingw32_debug_CXXFLAGS=$(mingw32_CXXFLAGS) $(mingw32_debug_CFLAGS) diff --git a/depends/packages/libevent.mk b/depends/packages/libevent.mk index ffe6f7e79ec..58b7c74fad7 100644 --- a/depends/packages/libevent.mk +++ b/depends/packages/libevent.mk @@ -1,18 +1,18 @@ package=libevent -$(package)_version=2.1.8 -$(package)_download_path=https://github.com/libevent/libevent/archive +$(package)_version=2.1.12-stable +$(package)_download_path=https://github.com/libevent/libevent/releases/download/release-$($(package)_version)/ $(package)_file_name=$(package)-$($(package)_version).tar.gz -$(package)_download_file=release-$($(package)_version)-stable.tar.gz -$(package)_sha256_hash=316ddb401745ac5d222d7c529ef1eada12f58f6376a66c1118eee803cb70f83d - -define $(package)_preprocess_cmds - ./autogen.sh -endef +$(package)_sha256_hash=92e6de1be9ec176428fd2367677e61ceffc2ee1cb119035037a27d346b0403bb +# When building for Windows, we set _WIN32_WINNT to target the same Windows +# version as we do in configure. Due to quirks in libevents build system, this +# is also required to enable support for ipv6. See #19375. define $(package)_set_vars - $(package)_config_opts=--disable-shared --disable-openssl --disable-libevent-regress + $(package)_config_opts=--disable-shared --disable-openssl --disable-libevent-regress --disable-samples + $(package)_config_opts += --disable-dependency-tracking --enable-option-checking $(package)_config_opts_release=--disable-debug-mode $(package)_config_opts_linux=--with-pic + $(package)_cppflags_mingw32=-D_WIN32_WINNT=0x0601 endef define $(package)_config_cmds @@ -28,4 +28,7 @@ define $(package)_stage_cmds endef define $(package)_postprocess_cmds + rm lib/*.la && \ + rm include/ev*.h && \ + rm include/event2/*_compat.h endef diff --git a/depends/packages/libgmp.mk b/depends/packages/libgmp.mk index b97bd622e0c..a76657ae791 100644 --- a/depends/packages/libgmp.mk +++ b/depends/packages/libgmp.mk @@ -22,7 +22,7 @@ $(package)_download_path=https://github.com/KomodoPlatform/libgmp/releases/downl $(package)_file_name=gmp-$($(package)_version).tar.bz2 $(package)_sha256_hash=a8109865f2893f1373b0a8ed5ff7429de8db696fc451b1036bd7bdf95bbeffd6 $(package)_dependencies= -$(package)_config_opts=--enable-cxx --disable-shared +$(package)_config_opts=--enable-cxx --disable-shared --with-pic endif define $(package)_config_cmds diff --git a/depends/packages/rust.mk b/depends/packages/rust.mk index 9cfb95054d9..84fd49e0c07 100644 --- a/depends/packages/rust.mk +++ b/depends/packages/rust.mk @@ -41,12 +41,12 @@ define $(package)_extract_cmds endef define $(package)_stage_cmds - ./install.sh --destdir=$($(package)_staging_dir) --prefix=$(host_prefix)/native --disable-ldconfig && \ + ./install.sh --destdir=$($(package)_staging_dir) --prefix=$(host_prefix)/native --disable-ldconfig --without=rust-docs && \ cp -r ../mingw32/rust-std-x86_64-pc-windows-gnu/lib/rustlib/x86_64-pc-windows-gnu $($(package)_staging_dir)$(host_prefix)/native/lib/rustlib endef else define $(package)_stage_cmds - ./install.sh --destdir=$($(package)_staging_dir) --prefix=$(host_prefix)/native --disable-ldconfig + ./install.sh --destdir=$($(package)_staging_dir) --prefix=$(host_prefix)/native --disable-ldconfig --without=rust-docs endef endif diff --git a/patches b/patches deleted file mode 100644 index 4f79cc9f774..00000000000 --- a/patches +++ /dev/null @@ -1,9072 +0,0 @@ -diff -crB ./configure.ac ../../komodo-jl777/configure.ac -*** ./configure.ac 2017-01-03 10:40:50.155326332 +0000 ---- ../../komodo-jl777/configure.ac 2017-01-03 09:49:08.848505929 +0000 -*************** -*** 2,8 **** - AC_PREREQ([2.60]) - define(_CLIENT_VERSION_MAJOR, 1) - define(_CLIENT_VERSION_MINOR, 0) -! define(_CLIENT_VERSION_REVISION, 0) - define(_CLIENT_VERSION_BUILD, 50) - define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) - define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) ---- 2,8 ---- - AC_PREREQ([2.60]) - define(_CLIENT_VERSION_MAJOR, 1) - define(_CLIENT_VERSION_MINOR, 0) -! define(_CLIENT_VERSION_REVISION, 3) - define(_CLIENT_VERSION_BUILD, 50) - define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) - define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) -Only in ../../komodo-jl777/contrib: bitcoin-cli.bash-completion -diff -crB ./contrib/bitcoind.bash-completion ../../komodo-jl777/contrib/bitcoind.bash-completion -*** ./contrib/bitcoind.bash-completion 2017-01-03 10:40:50.159326534 +0000 ---- ../../komodo-jl777/contrib/bitcoind.bash-completion 2017-01-03 09:49:08.848505929 +0000 -*************** -*** 1,102 **** -! # bash programmable completion for bitcoind(1) and bitcoin-cli(1) -! # Copyright (c) 2012,2014 Christian von Roques - # Distributed under the MIT software license, see the accompanying - # file COPYING or http://www.opensource.org/licenses/mit-license.php. - -! have bitcoind && { -! -! # call $bitcoind for RPC -! _bitcoin_rpc() { -! # determine already specified args necessary for RPC -! local rpcargs=() -! for i in ${COMP_LINE}; do -! case "$i" in -! -conf=*|-proxy*|-rpc*) -! rpcargs=( "${rpcargs[@]}" "$i" ) -! ;; -! esac -! done -! $bitcoind "${rpcargs[@]}" "$@" -! } -! -! # Add bitcoin accounts to COMPREPLY -! _bitcoin_accounts() { -! local accounts -! accounts=$(_bitcoin_rpc listaccounts | awk '/".*"/ { a=$1; gsub(/"/, "", a); print a}') -! COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "$accounts" -- "$cur" ) ) -! } -! -! _bitcoind() { - local cur prev words=() cword - local bitcoind - -! # save and use original argument to invoke bitcoind -! # bitcoind might not be in $PATH - bitcoind="$1" - - COMPREPLY=() - _get_comp_words_by_ref -n = cur prev words cword - -- if ((cword > 4)); then -- case ${words[cword-4]} in -- listtransactions) -- COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) -- return 0 -- ;; -- signrawtransaction) -- COMPREPLY=( $( compgen -W "ALL NONE SINGLE ALL|ANYONECANPAY NONE|ANYONECANPAY SINGLE|ANYONECANPAY" -- "$cur" ) ) -- return 0 -- ;; -- esac -- fi -- -- if ((cword > 3)); then -- case ${words[cword-3]} in -- addmultisigaddress) -- _bitcoin_accounts -- return 0 -- ;; -- getbalance|gettxout|importaddress|importprivkey|listreceivedbyaccount|listreceivedbyaddress|listsinceblock) -- COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) -- return 0 -- ;; -- esac -- fi -- -- if ((cword > 2)); then -- case ${words[cword-2]} in -- addnode) -- COMPREPLY=( $( compgen -W "add remove onetry" -- "$cur" ) ) -- return 0 -- ;; -- getblock|getrawtransaction|gettransaction|listaccounts|listreceivedbyaccount|listreceivedbyaddress|sendrawtransaction) -- COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) -- return 0 -- ;; -- move|setaccount) -- _bitcoin_accounts -- return 0 -- ;; -- esac -- fi -- -- case "$prev" in -- backupwallet|dumpwallet|importwallet) -- _filedir -- return 0 -- ;; -- getmempool|lockunspent|setgenerate) -- COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) -- return 0 -- ;; -- getaccountaddress|getaddressesbyaccount|getbalance|getnewaddress|getreceivedbyaccount|listtransactions|move|sendfrom|sendmany) -- _bitcoin_accounts -- return 0 -- ;; -- esac -- - case "$cur" in -! -conf=*|-pid=*|-loadblock=*|-wallet=*|-rpcsslcertificatechainfile=*|-rpcsslprivatekeyfile=*) - cur="${cur#*=}" - _filedir - return 0 ---- 1,21 ---- -! # bash programmable completion for bitcoind(1) and bitcoin-qt(1) -! # Copyright (c) 2012-2016 The Bitcoin Core developers - # Distributed under the MIT software license, see the accompanying - # file COPYING or http://www.opensource.org/licenses/mit-license.php. - -! _zcashd() { - local cur prev words=() cword - local bitcoind - -! # save and use original argument to invoke bitcoind for -help -! # it might not be in $PATH - bitcoind="$1" - - COMPREPLY=() - _get_comp_words_by_ref -n = cur prev words cword - - case "$cur" in -! -conf=*|-pid=*|-loadblock=*|-rootcertificates=*|-rpccookiefile=*|-wallet=*|-rpcsslcertificatechainfile=*|-rpcsslprivatekeyfile=*) - cur="${cur#*=}" - _filedir - return 0 -*************** -*** 110,129 **** - return 0 - ;; - *) -- local helpopts commands - -! # only parse --help if senseful - if [[ -z "$cur" || "$cur" =~ ^- ]]; then -! helpopts=$($bitcoind --help 2>&1 | awk '$1 ~ /^-/ { sub(/=.*/, "="); print $1 }' ) - fi - -- # only parse help if senseful -- if [[ -z "$cur" || "$cur" =~ ^[a-z] ]]; then -- commands=$(_bitcoin_rpc help 2>/dev/null | awk '$1 ~ /^[a-z]/ { print $1; }') -- fi -- -- COMPREPLY=( $( compgen -W "$helpopts $commands" -- "$cur" ) ) -- - # Prevent space if an argument is desired - if [[ $COMPREPLY == *= ]]; then - compopt -o nospace ---- 29,42 ---- - return 0 - ;; - *) - -! # only parse -help if senseful - if [[ -z "$cur" || "$cur" =~ ^- ]]; then -! local helpopts -! helpopts=$($bitcoind -help 2>&1 | awk '$1 ~ /^-/ { sub(/=.*/, "="); print $1 }' ) -! COMPREPLY=( $( compgen -W "$helpopts" -- "$cur" ) ) - fi - - # Prevent space if an argument is desired - if [[ $COMPREPLY == *= ]]; then - compopt -o nospace -*************** -*** 131,140 **** - return 0 - ;; - esac -! } -! -! complete -F _bitcoind bitcoind bitcoin-cli -! } - - # Local variables: - # mode: shell-script ---- 44,51 ---- - return 0 - ;; - esac -! } && -! complete -F _zcashd zcashd - - # Local variables: - # mode: shell-script -Only in ../../komodo-jl777/contrib: bitcoin-tx.bash-completion -diff -crB ./contrib/DEBIAN/changelog ../../komodo-jl777/contrib/DEBIAN/changelog -*** ./contrib/DEBIAN/changelog 2017-01-03 10:40:50.155326332 +0000 ---- ../../komodo-jl777/contrib/DEBIAN/changelog 2017-01-03 09:49:08.848505929 +0000 -*************** -*** 1,3 **** ---- 1,21 ---- -+ zcash (1.0.3) jessie; urgency=medium -+ -+ * 1.0.3 release. -+ -+ -- Zcash Company Wed, 17 Nov 2016 15:56:00 -0700 -+ -+ zcash (1.0.2) jessie; urgency=medium -+ -+ * 1.0.2 release. -+ -+ -- Zcash Company Mon, 07 Nov 2016 19:01:35 -0600 -+ -+ zcash (1.0.1) jessie; urgency=medium -+ -+ * 1.0.1 release. -+ -+ -- Zcash Company Thu, 03 Nov 2016 23:21:09 -0500 -+ - zcash (1.0.0-sprout) jessie; urgency=medium - - * 1.0.0 release. -diff -crB ./contrib/DEBIAN/control ../../komodo-jl777/contrib/DEBIAN/control -*** ./contrib/DEBIAN/control 2017-01-03 10:40:50.155326332 +0000 ---- ../../komodo-jl777/contrib/DEBIAN/control 2017-01-03 09:49:08.848505929 +0000 -*************** -*** 10,16 **** - Vcs-Git: https://github.com/zcash/zcash.git - Vcs-Browser: https://github.com/zcash/zcash - Package: zcash -! Version: 1.0.0-sprout - Architecture: amd64 - Depends: libgomp1 - Description: An implementation of the "Zerocash" protocol. ---- 10,16 ---- - Vcs-Git: https://github.com/zcash/zcash.git - Vcs-Browser: https://github.com/zcash/zcash - Package: zcash -! Version: 1.0.3 - Architecture: amd64 - Depends: libgomp1 - Description: An implementation of the "Zerocash" protocol. -diff -crB ./contrib/DEBIAN/manpages/zcash-cli.1 ../../komodo-jl777/contrib/DEBIAN/manpages/zcash-cli.1 -*** ./contrib/DEBIAN/manpages/zcash-cli.1 2017-01-03 10:40:50.155326332 +0000 ---- ../../komodo-jl777/contrib/DEBIAN/manpages/zcash-cli.1 2017-01-03 09:49:08.848505929 +0000 -*************** -*** 1,9 **** - .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.3. -! .TH ZCASH-CLI "1" "October 2016" "Zcash RPC client version v1.0.0-409dcb7" "User Commands" - .SH NAME - zcash-cli \- RPC client for the Zcash daemon - .SH DESCRIPTION -! Zcash RPC client version v1.0.0 - .SS "Usage:" - .TP - zcash\-cli [options] [params] ---- 1,9 ---- - .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.3. -! .TH ZCASH-CLI "1" "November 2016" "Zcash RPC client version v1.0.3" "User Commands" - .SH NAME - zcash-cli \- RPC client for the Zcash daemon - .SH DESCRIPTION -! Zcash RPC client version v1.0.3 - .SS "Usage:" - .TP - zcash\-cli [options] [params] -diff -crB ./contrib/DEBIAN/manpages/zcashd.1 ../../komodo-jl777/contrib/DEBIAN/manpages/zcashd.1 -*** ./contrib/DEBIAN/manpages/zcashd.1 2017-01-03 10:40:50.155326332 +0000 ---- ../../komodo-jl777/contrib/DEBIAN/manpages/zcashd.1 2017-01-03 09:49:08.848505929 +0000 -*************** -*** 1,9 **** - .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.3. -! .TH ZCASHD "1" "October 2016" "Zcash Daemon version v1.0.0-409dcb7" "User Commands" - .SH NAME - zcashd \- Network daemon for interacting with the Zcash blockchain - .SH DESCRIPTION -! Zcash Daemon version v1.0.0 - .SS "Usage:" - .TP - zcashd [options] ---- 1,9 ---- - .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.3. -! .TH ZCASHD "1" "November 2016" "Zcash Daemon version v1.0.3" "User Commands" - .SH NAME - zcashd \- Network daemon for interacting with the Zcash blockchain - .SH DESCRIPTION -! Zcash Daemon version v1.0.3 - .SS "Usage:" - .TP - zcashd [options] -*************** -*** 62,68 **** - .HP - \fB\-par=\fR - .IP -! Set the number of script verification threads (\fB\-4\fR to 16, 0 = auto, <0 = - leave that many cores free, default: 0) - .HP - \fB\-pid=\fR ---- 62,68 ---- - .HP - \fB\-par=\fR - .IP -! Set the number of script verification threads (\fB\-8\fR to 16, 0 = auto, <0 = - leave that many cores free, default: 0) - .HP - \fB\-pid=\fR -diff -crB ./contrib/gitian-descriptors/gitian-linux.yml ../../komodo-jl777/contrib/gitian-descriptors/gitian-linux.yml -*** ./contrib/gitian-descriptors/gitian-linux.yml 2017-01-03 10:40:50.159326534 +0000 ---- ../../komodo-jl777/contrib/gitian-descriptors/gitian-linux.yml 2017-01-03 09:49:08.848505929 +0000 -*************** -*** 1,5 **** - --- -! name: "zcash-1.0.0" - enable_cache: true - distro: "debian" - suites: ---- 1,5 ---- - --- -! name: "zcash-1.0.3" - enable_cache: true - distro: "debian" - suites: -diff -crB ./depends/packages/miniupnpc.mk ../../komodo-jl777/depends/packages/miniupnpc.mk -*** ./depends/packages/miniupnpc.mk 2017-01-03 10:40:50.179327547 +0000 ---- ../../komodo-jl777/depends/packages/miniupnpc.mk 2017-01-03 09:49:08.848505929 +0000 -*************** -*** 3,8 **** ---- 3,9 ---- - $(package)_download_path=http://miniupnp.free.fr/files - $(package)_file_name=$(package)-$($(package)_version).tar.gz - $(package)_sha256_hash=d434ceb8986efbe199c5ca53f90ed53eab290b1e6d0530b717eb6fa49d61f93b -+ $(package)_patches=fix-solaris-compilation.patch strlen-before-memcmp.patch patch-strlen-patch.patch - - define $(package)_set_vars - $(package)_build_opts=CC="$($(package)_cc)" -*************** -*** 14,20 **** - define $(package)_preprocess_cmds - mkdir dll && \ - sed -e 's|MINIUPNPC_VERSION_STRING \"version\"|MINIUPNPC_VERSION_STRING \"$($(package)_version)\"|' -e 's|OS/version|$(host)|' miniupnpcstrings.h.in > miniupnpcstrings.h && \ -! sed -i.old "s|miniupnpcstrings.h: miniupnpcstrings.h.in wingenminiupnpcstrings|miniupnpcstrings.h: miniupnpcstrings.h.in|" Makefile.mingw - endef - - define $(package)_build_cmds ---- 15,24 ---- - define $(package)_preprocess_cmds - mkdir dll && \ - sed -e 's|MINIUPNPC_VERSION_STRING \"version\"|MINIUPNPC_VERSION_STRING \"$($(package)_version)\"|' -e 's|OS/version|$(host)|' miniupnpcstrings.h.in > miniupnpcstrings.h && \ -! sed -i.old "s|miniupnpcstrings.h: miniupnpcstrings.h.in wingenminiupnpcstrings|miniupnpcstrings.h: miniupnpcstrings.h.in|" Makefile.mingw && \ -! patch -p2 < $($(package)_patch_dir)/fix-solaris-compilation.patch && \ -! patch -p2 < $($(package)_patch_dir)/strlen-before-memcmp.patch && \ -! patch -p2 < $($(package)_patch_dir)/patch-strlen-patch.patch - endef - - define $(package)_build_cmds -Only in ../../komodo-jl777/depends/patches: miniupnpc -Only in ../../komodo-jl777/doc: authors.md -diff -crB ./doc/developer-notes.md ../../komodo-jl777/doc/developer-notes.md -*** ./doc/developer-notes.md 2017-01-03 10:40:50.191328153 +0000 ---- ../../komodo-jl777/doc/developer-notes.md 2017-01-03 09:49:08.848505929 +0000 -*************** -*** 102,108 **** - If the code is behaving strangely, take a look in the debug.log file in the data directory; - error and debugging messages are written there. - -! The -debug=... command-line option controls debugging; running with just -debug will turn - on all categories (and give you a very large debug.log file). - - The Qt code routes qDebug() output to debug.log under category "qt": run with -debug=qt ---- 102,108 ---- - If the code is behaving strangely, take a look in the debug.log file in the data directory; - error and debugging messages are written there. - -! The -debug=... command-line option controls debugging; running with just -debug or -debug=1 will turn - on all categories (and give you a very large debug.log file). - - The Qt code routes qDebug() output to debug.log under category "qt": run with -debug=qt -diff -crB ./doc/payment-api.md ../../komodo-jl777/doc/payment-api.md -*** ./doc/payment-api.md 2017-01-03 10:40:50.191328153 +0000 ---- ../../komodo-jl777/doc/payment-api.md 2017-01-03 09:49:08.848505929 +0000 -*************** -*** 29,35 **** - RPC calls by category: - - * Accounting: z_getbalance, z_gettotalbalance -! * Addresses : z_getnewaddress, z_listaddresses - * Keys : z_exportkey, z_importkey, z_exportwallet, z_importwallet - * Operation: z_getoperationresult, z_getoperationstatus, z_listoperationids - * Payment : z_listreceivedbyaddress, z_sendmany ---- 29,35 ---- - RPC calls by category: - - * Accounting: z_getbalance, z_gettotalbalance -! * Addresses : z_getnewaddress, z_listaddresses, z_validateaddress - * Keys : z_exportkey, z_importkey, z_exportwallet, z_importwallet - * Operation: z_getoperationresult, z_getoperationstatus, z_listoperationids - * Payment : z_listreceivedbyaddress, z_sendmany -*************** -*** 55,60 **** ---- 55,61 ---- - --- | --- | --- - z_getnewaddress | | Return a new zaddr for sending and receiving payments. The spending key for this zaddr will be added to the node’s wallet.

Output:
zN68D8hSs3... - z_listaddresses | | Returns a list of all the zaddrs in this node’s wallet for which you have a spending key.

Output:
{ [“z123…”, “z456...”, “z789...”] } -+ z_validateaddress | | Return information about a given zaddr.

Output:
{"isvalid" : true,
"address" : "zcWsmq...",
"payingkey" : "f5bb3c...",
"transmissionkey" : "7a58c7...",
"ismine" : true} - - ### Key Management - -*************** -*** 70,76 **** - Command | Parameters | Description - --- | --- | --- - z_listreceivedbyaddress
| zaddr [minconf=1] | Return a list of amounts received by a zaddr belonging to the node’s wallet.

Optionally set the minimum number of confirmations which a received amount must have in order to be included in the result. Use 0 to count unconfirmed transactions.

Output:
[{
“txid”: “4a0f…”,
“amount”: 0.54,
“memo”:”F0FF…”,}, {...}, {...}
] -! z_sendmany
| fromaddress amounts [minconf=1] | _This is an Asynchronous RPC call_

Send funds from an address to multiple outputs. The address can be either a taddr or a zaddr.

Amounts is a list containing key/value pairs corresponding to the addresses and amount to pay. Each output address can be in taddr or zaddr format.

When sending to a zaddr, you also have the option of attaching a memo in hexadecimal format.

**NOTE:**When sending coinbase funds to a zaddr, the node's wallet does not allow any change. Put another way, spending a partial amount of a coinbase utxo is not allowed. This is not a consensus rule but a local wallet rule due to the current implementation of z_sendmany. In future, this rule may be removed.

Example of Outputs parameter:
[{“address”:”t123…”, “amount”:0.005},
,{“address”:”z010…”,”amount”:0.03, “memo”:”f508af…”}]

Optionally set the minimum number of confirmations which a private or transparent transaction must have in order to be used as an input.

The transaction fee will be determined by the node’s wallet. Any transparent change will be sent to a new transparent address. Any private change will be sent back to the zaddr being used as the source of funds.

Returns an operationid. You use the operationid value with z_getoperationstatus and z_getoperationresult to obtain the result of sending funds, which if successful, will be a txid. - - ### Operations - ---- 71,77 ---- - Command | Parameters | Description - --- | --- | --- - z_listreceivedbyaddress
| zaddr [minconf=1] | Return a list of amounts received by a zaddr belonging to the node’s wallet.

Optionally set the minimum number of confirmations which a received amount must have in order to be included in the result. Use 0 to count unconfirmed transactions.

Output:
[{
“txid”: “4a0f…”,
“amount”: 0.54,
“memo”:”F0FF…”,}, {...}, {...}
] -! z_sendmany
| fromaddress amounts [minconf=1] [fee=0.0001] | _This is an Asynchronous RPC call_

Send funds from an address to multiple outputs. The address can be either a taddr or a zaddr.

Amounts is a list containing key/value pairs corresponding to the addresses and amount to pay. Each output address can be in taddr or zaddr format.

When sending to a zaddr, you also have the option of attaching a memo in hexadecimal format.

**NOTE:**When sending coinbase funds to a zaddr, the node's wallet does not allow any change. Put another way, spending a partial amount of a coinbase utxo is not allowed. This is not a consensus rule but a local wallet rule due to the current implementation of z_sendmany. In future, this rule may be removed.

Example of Outputs parameter:
[{“address”:”t123…”, “amount”:0.005},
,{“address”:”z010…”,”amount”:0.03, “memo”:”f508af…”}]

Optionally set the minimum number of confirmations which a private or transparent transaction must have in order to be used as an input.

Optionally set a transaction fee, which by default is 0.0001 ZEC.

Any transparent change will be sent to a new transparent address. Any private change will be sent back to the zaddr being used as the source of funds.

Returns an operationid. You use the operationid value with z_getoperationstatus and z_getoperationresult to obtain the result of sending funds, which if successful, will be a txid. - - ### Operations - -*************** -*** 97,99 **** ---- 98,168 ---- - z_getoperationresult
| [operationids] | Return OperationStatus JSON objects for all completed operations the node is currently aware of, and then remove the operation from memory.

Operationids is an optional array to filter which operations you want to receive status objects for.

Output is a list of operation status objects, where the status is either "failed", "cancelled" or "success".
[
{“operationid”: “opid-11ee…”,
“status”: “cancelled”},
{“operationid”: “opid-9876”, “status”: ”failed”},
{“operationid”: “opid-0e0e”,
“status”:”success”,
“execution_time”:”25”,
“result”: {“txid”:”af3887654…”,...}
},
] - z_getoperationstatus
| [operationids] | Return OperationStatus JSON objects for all operations the node is currently aware of.

Operationids is an optional array to filter which operations you want to receive status objects for.

Output is a list of operation status objects.
[
{“operationid”: “opid-12ee…”,
“status”: “queued”},
{“operationid”: “opd-098a…”, “status”: ”executing”},
{“operationid”: “opid-9876”, “status”: ”failed”}
]

When the operation succeeds, the status object will also include the result.

{“operationid”: “opid-0e0e”,
“status”:”success”,
“execution_time”:”25”,
“result”: {“txid”:”af3887654…”,...}
} - z_listoperationids
| [state] | Return a list of operationids for all operations which the node is currently aware of.

State is an optional string parameter to filter the operations you want listed by their state. Acceptable parameter values are ‘queued’, ‘executing’, ‘success’, ‘failed’, ‘cancelled’.

[“opid-0e0e…”, “opid-1af4…”, … ] -+ -+ ## Asynchronous RPC call Error Codes -+ -+ Zcash error codes are defined in https://github.com/zcash/zcash/blob/master/src/rpcprotocol.h -+ -+ ### z_sendmany error codes -+ -+ RPC_INVALID_PARAMETER (-8) | _Invalid, missing or duplicate parameter_ -+ ---------------------------| ------------------------------------------------- -+ "Minconf cannot be negative" | Cannot accept negative minimum confirmation number. -+ "Minimum number of confirmations cannot be less than 0" | Cannot accept negative minimum confirmation number. -+ "From address parameter missing" | Missing an address to send funds from. -+ "No recipients" | Missing recipient addresses. -+ "Memo must be in hexadecimal format" | Encrypted memo field data must be in hexadecimal format. -+ "Memo size of __ is too big, maximum allowed is __ " | Encrypted memo field data exceeds maximum size of 512 bytes. -+ "From address does not belong to this node, zaddr spending key not found." | Sender address spending key not found. -+ "Invalid parameter, expected object" | Expected object. -+ "Invalid parameter, unknown key: __" | Unknown key. -+ "Invalid parameter, expected valid size" | Invalid size. -+ "Invalid parameter, expected hex txid" | Invalid txid. -+ "Invalid parameter, vout must be positive" | Invalid vout. -+ "Invalid parameter, duplicated address" | Address is duplicated. -+ "Invalid parameter, amounts array is empty" | Amounts array is empty. -+ "Invalid parameter, unknown key" | Key not found. -+ "Invalid parameter, unknown address format" | Unknown address format. -+ "Invalid parameter, size of memo" | Invalid memo field size. -+ "Invalid parameter, amount must be positive" | Invalid or negative amount. -+ "Invalid parameter, too many zaddr outputs" | z_address outputs exceed maximum allowed. -+ "Invalid parameter, expected memo data in hexadecimal format" | Encrypted memo field is not in hexadecimal format. -+ "Invalid parameter, size of memo is larger than maximum allowed __ " | Encrypted memo field data exceeds maximum size of 512 bytes. -+ -+ -+ RPC_INVALID_ADDRESS_OR_KEY (-5) | _Invalid address or key_ -+ --------------------------------| --------------------------- -+ "Invalid from address, no spending key found for zaddr" | z_address spending key not found. -+ "Invalid output address, not a valid taddr." | Transparent output address is invalid. -+ "Invalid from address, should be a taddr or zaddr." | Sender address is invalid. -+ "From address does not belong to this node, zaddr spending key not found." | Sender address spending key not found. -+ -+ -+ RPC_WALLET_INSUFFICIENT_FUNDS (-6) | _Not enough funds in wallet or account_ -+ -----------------------------------| ------------------------------------------ -+ "Insufficient funds, no UTXOs found for taddr from address." | Insufficient funds for sending address. -+ "Could not find any non-coinbase UTXOs to spend. Coinbase UTXOs can only be sent to a single zaddr recipient." | Must send Coinbase UTXO to a single z_address. -+ "Could not find any non-coinbase UTXOs to spend." | No available non-coinbase UTXOs. -+ "Insufficient funds, no unspent notes found for zaddr from address." | Insufficient funds for sending address. -+ "Insufficient transparent funds, have __, need __ plus fee __" | Insufficient funds from transparent address. -+ "Insufficient protected funds, have __, need __ plus fee __" | Insufficient funds from shielded address. -+ -+ RPC_WALLET_ERROR (-4) | _Unspecified problem with wallet_ -+ ----------------------| ------------------------------------- -+ "Could not find previous JoinSplit anchor" | Try restarting node with `-reindex`. -+ "Error decrypting output note of previous JoinSplit: __" | -+ "Could not find witness for note commitment" | Try restarting node with `-reindex`. -+ "Witness for note commitment is null" | Missing witness for note commitement. -+ "Witness for spendable note does not have same anchor as change input" | Invalid anchor for spendable note witness. -+ "Not enough funds to pay miners fee" | Retry with sufficient funds. -+ "Missing hex data for raw transaction" | Raw transaction data is null. -+ "Missing hex data for signed transaction" | Hex value for signed transaction is null. -+ "Send raw transaction did not return an error or a txid." | -+ -+ RPC_WALLET_ENCRYPTION_FAILED (-16) | _Failed to encrypt the wallet_ -+ -------------------------------------------------------------------------| ------------------------------------- -+ "Failed to sign transaction" | Transaction was not signed, sign transaction and retry. -+ -+ RPC_WALLET_KEYPOOL_RAN_OUT (-12) | _Keypool ran out, call keypoolrefill first_ -+ -------------------------------------------------------------------------| ----------------------------------------------- -+ "Could not generate a taddr to use as a change address" | Call keypoolrefill and retry. -diff -crB ./doc/release-notes/release-notes-0.11.2.z6.md ../../komodo-jl777/doc/release-notes/release-notes-0.11.2.z6.md -*** ./doc/release-notes/release-notes-0.11.2.z6.md 2017-01-03 10:40:50.191328153 +0000 ---- ../../komodo-jl777/doc/release-notes/release-notes-0.11.2.z6.md 2017-01-03 09:49:08.848505929 +0000 -*************** -*** 1,19 **** -! Jack Grigg: - Equihash: Only compare the first n/(k+1) bits when sorting. - Randomise the nonce in the block header. - Clear mempool before using it for benchmark test, fix parameter name. - Fix memory leak in large tx benchmark. - -! Sean Bowe: - Increase block size to 2MB and update performance test. - Make sigop limit `20000` just as in Bitcoin, ignoring our change to the blocksize limit. - Remove the mainnet checkpoints. - Fix performance test for block verification. - Make `validatelargetx` test more accurate. - -! Taylor Hornby: - Add example mock test of CheckTransaction. - -! aniemerg: - Suppress Libsnark Debugging Info. -- ---- 1,18 ---- -! Jack Grigg (4): - Equihash: Only compare the first n/(k+1) bits when sorting. - Randomise the nonce in the block header. - Clear mempool before using it for benchmark test, fix parameter name. - Fix memory leak in large tx benchmark. - -! Sean Bowe (5): - Increase block size to 2MB and update performance test. - Make sigop limit `20000` just as in Bitcoin, ignoring our change to the blocksize limit. - Remove the mainnet checkpoints. - Fix performance test for block verification. - Make `validatelargetx` test more accurate. - -! Taylor Hornby (1): - Add example mock test of CheckTransaction. - -! aniemerg (1): - Suppress Libsnark Debugging Info. -diff -crB ./doc/release-notes/release-notes-0.11.2.z9.md ../../komodo-jl777/doc/release-notes/release-notes-0.11.2.z9.md -*** ./doc/release-notes/release-notes-0.11.2.z9.md 2017-01-03 10:40:50.191328153 +0000 ---- ../../komodo-jl777/doc/release-notes/release-notes-0.11.2.z9.md 2017-01-03 09:49:08.848505929 +0000 -*************** -*** 1,5 **** -! -! Sean Bowe: - Change memo field size and relocate `ciphertexts` field of JoinSplit description. - Implement zkSNARK compression. - Perform curve parameter initialization at start of gtest suite. ---- 1,4 ---- -! Sean Bowe (6): - Change memo field size and relocate `ciphertexts` field of JoinSplit description. - Implement zkSNARK compression. - Perform curve parameter initialization at start of gtest suite. -*************** -*** 7,13 **** - Enable MONTGOMERY_OUTPUT everywhere. - Update proving/verifying keys. - -! Jack Grigg: - Add support for spending keys to the basic key store. - Merge AddSpendingKeyPaymentAddress into AddSpendingKey to simplify API. - Add methods for byte array expansion and compression. ---- 6,12 ---- - Enable MONTGOMERY_OUTPUT everywhere. - Update proving/verifying keys. - -! Jack Grigg (11): - Add support for spending keys to the basic key store. - Merge AddSpendingKeyPaymentAddress into AddSpendingKey to simplify API. - Add methods for byte array expansion and compression. -*************** -*** 20,26 **** - Add separate lock for SpendingKey key store operations. - Test conversion between solution indices and minimal representation. - -! Daira Hopwood: - Move bigint arithmetic implementations to libsnark. - Add mostly-static checks on consistency of Equihash parameters, MAX_HEADERS_RESULTS, and MAX_PROTOCOL_MESSAGE_LENGTH. - Change some asserts in equihash.cpp to be static. ---- 19,25 ---- - Add separate lock for SpendingKey key store operations. - Test conversion between solution indices and minimal representation. - -! Daira Hopwood (6): - Move bigint arithmetic implementations to libsnark. - Add mostly-static checks on consistency of Equihash parameters, MAX_HEADERS_RESULTS, and MAX_PROTOCOL_MESSAGE_LENGTH. - Change some asserts in equihash.cpp to be static. -*************** -*** 28,57 **** - Increment version numbers for z9 release. - Add these release notes for z9. - -! Taylor Hornby: - Disable hardening when building for coverage reports. - Upgrade libsodium for AVX2-detection bugfix. - Fix inconsistent optimization flags; single source of truth. - Add -fwrapv -fno-strict-aliasing; fix libzcash flags. - Use libsodium's s < L check, instead checking that libsodium checks that. - -! Simon Liu: - Fixes #1193 so that during verification benchmarking it does not unncessarily create thousands of CTransaction objects. - Closes #701 by adding documentation about the Payment RPC interface. - Add note about zkey and encrypted wallets. - -! Gaurav Rana: - Update zcash-cli stop message. - -! Tom Ritter: - Clarify comment about nonce space for Note Encryption. - -! Robert C. Seacord: - Memory safety and correctness fixes found in NCC audit. - -! Patrick Strateman (merged by Taylor Hornby): - Pull in some DoS mitigations from upstream. (#1258) - -! Wladimir J. van der Laan: - net: correctly initialize nMinPingUsecTime. -- ---- 27,55 ---- - Increment version numbers for z9 release. - Add these release notes for z9. - -! Taylor Hornby (5): - Disable hardening when building for coverage reports. - Upgrade libsodium for AVX2-detection bugfix. - Fix inconsistent optimization flags; single source of truth. - Add -fwrapv -fno-strict-aliasing; fix libzcash flags. - Use libsodium's s < L check, instead checking that libsodium checks that. - -! Simon Liu (3): - Fixes #1193 so that during verification benchmarking it does not unncessarily create thousands of CTransaction objects. - Closes #701 by adding documentation about the Payment RPC interface. - Add note about zkey and encrypted wallets. - -! Gaurav Rana (1): - Update zcash-cli stop message. - -! Tom Ritter (1): - Clarify comment about nonce space for Note Encryption. - -! Robert C. Seacord (1): - Memory safety and correctness fixes found in NCC audit. - -! Patrick Strateman (1): - Pull in some DoS mitigations from upstream. (#1258) - -! Wladimir J. van der Laan (1): - net: correctly initialize nMinPingUsecTime. -Only in ../../komodo-jl777/doc/release-notes: release-notes-1.0.1.md -Only in ../../komodo-jl777/doc/release-notes: release-notes-1.0.2.md -Only in ../../komodo-jl777/doc/release-notes: release-notes-1.0.3.md -diff -crB ./doc/release-process.md ../../komodo-jl777/doc/release-process.md -*** ./doc/release-process.md 2017-01-03 10:40:50.191328153 +0000 ---- ../../komodo-jl777/doc/release-process.md 2017-01-03 09:49:08.848505929 +0000 -*************** -*** 38,43 **** ---- 38,45 ---- - contrib/DEBIAN/control - contrib/gitian-descriptors/gitian-linux.yml - -+ Build and commit to update versions, and then perform the following commands: -+ - help2man -n "RPC client for the Zcash daemon" src/zcash-cli > contrib/DEBIAN/manpages/zcash-cli.1 - help2man -n "Network daemon for interacting with the Zcash blockchain" src/zcashd > contrib/DEBIAN/manpages/zcashd.1 - -*************** -*** 57,66 **** - - ### B2. Write release notes - -! git shortlog helps a lot, for example: - -! $ git shortlog --no-merges v${ZCASH_RELEASE_PREV}..HEAD \ -! > ./doc/release-notes/release-notes-${ZCASH_RELEASE}.md - - Update the Debian package changelog: - ---- 59,67 ---- - - ### B2. Write release notes - -! Run the release-notes.py script to generate release notes and update authors.md file. For example: - -! $ python zcutil/release-notes.py --version $ZCASH_RELEASE - - Update the Debian package changelog: - -diff -crB ./doc/security-warnings.md ../../komodo-jl777/doc/security-warnings.md -*** ./doc/security-warnings.md 2017-01-03 10:40:50.191328153 +0000 ---- ../../komodo-jl777/doc/security-warnings.md 2017-01-03 09:49:08.848505929 +0000 -*************** -*** 35,44 **** - from the earlier issue). - - - We were concerned about the resistance of the algorithm used to derive wallet -! encryption keys (inherited from Bitcoin) to dictionary attacks by a powerful -! attacker. If and when we re-enable wallet encryption, it is likely to be with -! a modern passphrase-based key derivation algorithm designed for greater -! resistance to dictionary attack, such as Argon2i. - - You should use full-disk encryption (or encryption of your home directory) to - protect your wallet at rest, and should assume (even unprivileged) users who are ---- 35,44 ---- - from the earlier issue). - - - We were concerned about the resistance of the algorithm used to derive wallet -! encryption keys (inherited from [Bitcoin](https://bitcoin.org/en/secure-your-wallet)) -! to dictionary attacks by a powerful attacker. If and when we re-enable wallet -! encryption, it is likely to be with a modern passphrase-based key derivation -! algorithm designed for greater resistance to dictionary attack, such as Argon2i. - - You should use full-disk encryption (or encryption of your home directory) to - protect your wallet at rest, and should assume (even unprivileged) users who are -diff -crB ./doc/tor.md ../../komodo-jl777/doc/tor.md -*** ./doc/tor.md 2017-01-03 10:40:50.191328153 +0000 ---- ../../komodo-jl777/doc/tor.md 2017-01-03 09:49:08.848505929 +0000 -*************** -*** 18,24 **** - -proxy=ip:port Set the proxy server. If SOCKS5 is selected (default), this proxy - server will be used to try to reach .onion addresses as well. - -! -onion=ip:port Set the proxy server to use for tor hidden services. You do not - need to set this if it's the same as -proxy. You can use -noonion - to explicitly disable access to hidden service. - ---- 18,24 ---- - -proxy=ip:port Set the proxy server. If SOCKS5 is selected (default), this proxy - server will be used to try to reach .onion addresses as well. - -! -onion=ip:port Set the proxy server to use for Tor hidden services. You do not - need to set this if it's the same as -proxy. You can use -noonion - to explicitly disable access to hidden service. - -diff -crB ./Dockerfile ../../komodo-jl777/Dockerfile -*** ./Dockerfile 2017-01-03 10:40:50.151326129 +0000 ---- ../../komodo-jl777/Dockerfile 2017-01-03 09:49:08.848505929 +0000 -*************** -*** 1,15 **** -! FROM ubuntu:16.04 -! MAINTAINER Mihail Fedorov -! -! # All the stuff -! # And clean out packages, keep space minimal -! RUN apt-get -y update && \ -! apt-get -y upgrade && \ -! apt-get -y install build-essential pkg-config libc6-dev m4 g++-multilib autoconf libtool ncurses-dev \ -! unzip python zlib1g-dev wget bsdmainutils automake libboost-all-dev libssl-dev libprotobuf-dev \ -! protobuf-compiler libqt4-dev libqrencode-dev libdb++-dev software-properties-common libcurl4-openssl-dev && \ -! apt-get clean && \ -! rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - - ADD ./ /komodo - ENV HOME /komodo ---- 1,5 ---- -! FROM kolobus/ubuntu:komodo -! MAINTAINER Mihail Fedorov - - ADD ./ /komodo - ENV HOME /komodo -*************** -*** 19,25 **** - RUN cd /komodo && \ - ./autogen.sh && \ - ./configure --with-incompatible-bdb --with-gui || true && \ -! ./zcutil/build.sh -j4 - - # Unknown stuff goes here - ---- 9,15 ---- - RUN cd /komodo && \ - ./autogen.sh && \ - ./configure --with-incompatible-bdb --with-gui || true && \ -! ./zcutil/build.sh -j$(nproc) - - # Unknown stuff goes here - -diff -crB ./.git/config ../../komodo-jl777/.git/config -*** ./.git/config 2017-01-03 10:40:50.131325117 +0000 ---- ../../komodo-jl777/.git/config 2017-01-03 09:49:08.884507813 +0000 -*************** -*** 4,11 **** - bare = false - logallrefupdates = true - [remote "origin"] -! url = https://github.com/j-cimb-barker/komodo.git - fetch = +refs/heads/*:refs/remotes/origin/* - [branch "master"] - remote = origin - merge = refs/heads/master ---- 4,14 ---- - bare = false - logallrefupdates = true - [remote "origin"] -! url = https://github.com/jl777/komodo.git - fetch = +refs/heads/*:refs/remotes/origin/* - [branch "master"] - remote = origin - merge = refs/heads/master -+ [branch "dev"] -+ remote = origin -+ merge = refs/heads/dev -diff -crB ./.git/HEAD ../../komodo-jl777/.git/HEAD -*** ./.git/HEAD 2017-01-03 10:40:50.131325117 +0000 ---- ../../komodo-jl777/.git/HEAD 2017-01-03 09:49:08.884507813 +0000 -*************** -*** 1 **** -! ref: refs/heads/master ---- 1 ---- -! ref: refs/heads/dev -Binary files ./.git/index and ../../komodo-jl777/.git/index differ -diff -crB ./.git/logs/HEAD ../../komodo-jl777/.git/logs/HEAD -*** ./.git/logs/HEAD 2017-01-03 10:40:50.131325117 +0000 ---- ../../komodo-jl777/.git/logs/HEAD 2017-01-03 09:49:08.884507813 +0000 -*************** -*** 1 **** -! 0000000000000000000000000000000000000000 d03fbd981fce86504b78d2a9582e4da988d59823 joel 1483440050 +0000 clone: from https://github.com/j-cimb-barker/komodo.git ---- 1,2 ---- -! 0000000000000000000000000000000000000000 d03fbd981fce86504b78d2a9582e4da988d59823 joel 1483436901 +0000 clone: from https://github.com/jl777/komodo.git -! d03fbd981fce86504b78d2a9582e4da988d59823 26ac06c4f5a6b4dc3163b36a1e5d24bfa7eccbd2 joel 1483436948 +0000 checkout: moving from master to dev -Only in ../../komodo-jl777/.git/logs/refs/heads: dev -diff -crB ./.git/logs/refs/heads/master ../../komodo-jl777/.git/logs/refs/heads/master -*** ./.git/logs/refs/heads/master 2017-01-03 10:40:50.131325117 +0000 ---- ../../komodo-jl777/.git/logs/refs/heads/master 2017-01-03 09:48:21.598032424 +0000 -*************** -*** 1 **** -! 0000000000000000000000000000000000000000 d03fbd981fce86504b78d2a9582e4da988d59823 joel 1483440050 +0000 clone: from https://github.com/j-cimb-barker/komodo.git ---- 1 ---- -! 0000000000000000000000000000000000000000 d03fbd981fce86504b78d2a9582e4da988d59823 joel 1483436901 +0000 clone: from https://github.com/jl777/komodo.git -diff -crB ./.git/logs/refs/remotes/origin/HEAD ../../komodo-jl777/.git/logs/refs/remotes/origin/HEAD -*** ./.git/logs/refs/remotes/origin/HEAD 2017-01-03 10:40:50.131325117 +0000 ---- ../../komodo-jl777/.git/logs/refs/remotes/origin/HEAD 2017-01-03 09:48:21.598032424 +0000 -*************** -*** 1 **** -! 0000000000000000000000000000000000000000 d03fbd981fce86504b78d2a9582e4da988d59823 joel 1483440050 +0000 clone: from https://github.com/j-cimb-barker/komodo.git ---- 1 ---- -! 0000000000000000000000000000000000000000 d03fbd981fce86504b78d2a9582e4da988d59823 joel 1483436901 +0000 clone: from https://github.com/jl777/komodo.git -Only in ./.git/objects/pack: pack-12e7bdf654b29f95604673fb1b3ee01a9bd52369.idx -Only in ./.git/objects/pack: pack-12e7bdf654b29f95604673fb1b3ee01a9bd52369.pack -Only in ../../komodo-jl777/.git/objects/pack: pack-3d08e40e89111c75a81ccd6099e05e09fd0e0f08.idx -Only in ../../komodo-jl777/.git/objects/pack: pack-3d08e40e89111c75a81ccd6099e05e09fd0e0f08.pack -diff -crB ./.git/packed-refs ../../komodo-jl777/.git/packed-refs -*** ./.git/packed-refs 2017-01-03 10:40:50.131325117 +0000 ---- ../../komodo-jl777/.git/packed-refs 2017-01-03 09:48:21.598032424 +0000 -*************** -*** 2,10 **** - fcd361184f09fe17546698b0d13caddac5b63500 refs/remotes/origin/PoS - 730a5006cbbfb0607ed93067db1a74d57584eb1f refs/remotes/origin/acspeed - 80259d4b4f193c7c438f3c057ce70af3beb1a099 refs/remotes/origin/auto -! 060c9a92939c62bbedb5fe560bf8ef6856e2b8f1 refs/remotes/origin/beta - ba9104dd7e9b6ba2b68ad352253ac8f3298092f4 refs/remotes/origin/dPoW -! cb42e5518262235ed4e4dbff43179e0308114d6a refs/remotes/origin/dev - 76b6eacf41395ddd2badd5d5dc3352e603c59df2 refs/remotes/origin/kolo - bb40eb8b043a1e63c3dc3b1c2e4d0f6e67e771d4 refs/remotes/origin/kolo-dev - d03fbd981fce86504b78d2a9582e4da988d59823 refs/remotes/origin/master ---- 2,10 ---- - fcd361184f09fe17546698b0d13caddac5b63500 refs/remotes/origin/PoS - 730a5006cbbfb0607ed93067db1a74d57584eb1f refs/remotes/origin/acspeed - 80259d4b4f193c7c438f3c057ce70af3beb1a099 refs/remotes/origin/auto -! f6f296f1acf8c2b177451ed0c9f8660f3a80ec3d refs/remotes/origin/beta - ba9104dd7e9b6ba2b68ad352253ac8f3298092f4 refs/remotes/origin/dPoW -! 26ac06c4f5a6b4dc3163b36a1e5d24bfa7eccbd2 refs/remotes/origin/dev - 76b6eacf41395ddd2badd5d5dc3352e603c59df2 refs/remotes/origin/kolo - bb40eb8b043a1e63c3dc3b1c2e4d0f6e67e771d4 refs/remotes/origin/kolo-dev - d03fbd981fce86504b78d2a9582e4da988d59823 refs/remotes/origin/master -Only in ../../komodo-jl777/.git/refs/heads: dev -diff -crB ./.gitignore ../../komodo-jl777/.gitignore -*** ./.gitignore 2017-01-03 10:40:50.151326129 +0000 ---- ../../komodo-jl777/.gitignore 2017-01-03 09:49:08.848505929 +0000 -*************** -*** 65,70 **** ---- 65,71 ---- - *.a - *.pb.cc - *.pb.h -+ .vscode - - *.log - *.trs -diff -crB ./Makefile.am ../../komodo-jl777/Makefile.am -*** ./Makefile.am 2017-01-03 10:40:50.151326129 +0000 ---- ../../komodo-jl777/Makefile.am 2017-01-03 09:49:08.848505929 +0000 -*************** -*** 258,267 **** - @qa/pull-tester/run-bitcoind-for-test.sh $(JAVA) -jar $(JAVA_COMPARISON_TOOL) qa/tmp/compTool $(COMPARISON_TOOL_REORG_TESTS) 2>&1 - endif - -! dist_noinst_SCRIPTS = autogen.sh - - EXTRA_DIST = $(top_srcdir)/share/genbuild.sh qa/pull-tester/rpc-tests.sh qa/pull-tester/run-bitcoin-cli qa/rpc-tests qa/zcash $(DIST_DOCS) $(BIN_CHECKS) - - CLEANFILES = $(OSX_DMG) $(BITCOIN_WIN_INSTALLER) - - .INTERMEDIATE: $(COVERAGE_INFO) ---- 258,271 ---- - @qa/pull-tester/run-bitcoind-for-test.sh $(JAVA) -jar $(JAVA_COMPARISON_TOOL) qa/tmp/compTool $(COMPARISON_TOOL_REORG_TESTS) 2>&1 - endif - -! dist_bin_SCRIPTS = zcutil/fetch-params.sh -! dist_noinst_SCRIPTS = autogen.sh zcutil/build-debian-package.sh zcutil/build.sh - - EXTRA_DIST = $(top_srcdir)/share/genbuild.sh qa/pull-tester/rpc-tests.sh qa/pull-tester/run-bitcoin-cli qa/rpc-tests qa/zcash $(DIST_DOCS) $(BIN_CHECKS) - -+ install-exec-hook: -+ mv $(DESTDIR)$(bindir)/fetch-params.sh $(DESTDIR)$(bindir)/zcash-fetch-params -+ - CLEANFILES = $(OSX_DMG) $(BITCOIN_WIN_INSTALLER) - - .INTERMEDIATE: $(COVERAGE_INFO) -Only in .: patches -diff -crB ./qa/pull-tester/rpc-tests.sh ../../komodo-jl777/qa/pull-tester/rpc-tests.sh -*** ./qa/pull-tester/rpc-tests.sh 2017-01-03 10:40:50.195328356 +0000 ---- ../../komodo-jl777/qa/pull-tester/rpc-tests.sh 2017-01-03 09:49:08.848505929 +0000 -*************** -*** 11,16 **** ---- 11,17 ---- - #Run the tests - - testScripts=( -+ 'wallet_treestate.py' - 'wallet_protectcoinbase.py' - 'wallet.py' - 'wallet_nullifiers.py' -diff -crB ./qa/rpc-tests/httpbasics.py ../../komodo-jl777/qa/rpc-tests/httpbasics.py -*** ./qa/rpc-tests/httpbasics.py 2017-01-03 10:40:50.195328356 +0000 ---- ../../komodo-jl777/qa/rpc-tests/httpbasics.py 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 38,50 **** - conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) - out1 = conn.getresponse().read(); - assert_equal('"error":null' in out1, True) -! assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open! -! -! #send 2nd request without closing connection -! conn.request('POST', '/', '{"method": "getchaintips"}', headers) -! out2 = conn.getresponse().read(); -! assert_equal('"error":null' in out1, True) #must also response with a correct json-rpc message -! assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open! - conn.close() - - #same should be if we add keep-alive because this should be the std. behaviour ---- 38,46 ---- - conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) - out1 = conn.getresponse().read(); - assert_equal('"error":null' in out1, True) -! -! # TODO #1856: Re-enable support for persistent connections. -! assert_equal(conn.sock!=None, False) - conn.close() - - #same should be if we add keep-alive because this should be the std. behaviour -*************** -*** 55,67 **** - conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) - out1 = conn.getresponse().read(); - assert_equal('"error":null' in out1, True) -! assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open! -! -! #send 2nd request without closing connection -! conn.request('POST', '/', '{"method": "getchaintips"}', headers) -! out2 = conn.getresponse().read(); -! assert_equal('"error":null' in out1, True) #must also response with a correct json-rpc message -! assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open! - conn.close() - - #now do the same with "Connection: close" ---- 51,59 ---- - conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) - out1 = conn.getresponse().read(); - assert_equal('"error":null' in out1, True) -! -! # TODO #1856: Re-enable support for persistent connections. -! assert_equal(conn.sock!=None, False) - conn.close() - - #now do the same with "Connection: close" -*************** -*** 96,102 **** - conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) - out1 = conn.getresponse().read(); - assert_equal('"error":null' in out1, True) -! assert_equal(conn.sock!=None, True) #connection must be closed because bitcoind should use keep-alive by default - - if __name__ == '__main__': - HTTPBasicsTest ().main () ---- 88,97 ---- - conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) - out1 = conn.getresponse().read(); - assert_equal('"error":null' in out1, True) -! -! # TODO #1856: Re-enable support for persistent connections. -! assert_equal(conn.sock!=None, False) -! conn.close() - - if __name__ == '__main__': - HTTPBasicsTest ().main () -diff -crB ./qa/rpc-tests/wallet_protectcoinbase.py ../../komodo-jl777/qa/rpc-tests/wallet_protectcoinbase.py -*** ./qa/rpc-tests/wallet_protectcoinbase.py 2017-01-03 10:40:50.199328558 +0000 ---- ../../komodo-jl777/qa/rpc-tests/wallet_protectcoinbase.py 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 8,14 **** - from test_framework.util import * - from time import * - -! class Wallet2Test (BitcoinTestFramework): - - def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) ---- 8,14 ---- - from test_framework.util import * - from time import * - -! class WalletProtectCoinbaseTest (BitcoinTestFramework): - - def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) -*************** -*** 23,43 **** - self.is_network_split=False - self.sync_all() - -! def wait_for_operationd_success(self, myopid): - print('waiting for async operation {}'.format(myopid)) - opids = [] - opids.append(myopid) -! timeout = 120 - status = None - for x in xrange(1, timeout): - results = self.nodes[0].z_getoperationresult(opids) - if len(results)==0: - sleep(1) - else: - status = results[0]["status"] - break - print('...returned status: {}'.format(status)) -! assert_equal("success", status) - - def run_test (self): - print "Mining blocks..." ---- 23,55 ---- - self.is_network_split=False - self.sync_all() - -! # Returns txid if operation was a success or None -! def wait_and_assert_operationid_status(self, myopid, in_status='success', in_errormsg=None): - print('waiting for async operation {}'.format(myopid)) - opids = [] - opids.append(myopid) -! timeout = 300 - status = None -+ errormsg = None -+ txid = None - for x in xrange(1, timeout): - results = self.nodes[0].z_getoperationresult(opids) - if len(results)==0: - sleep(1) - else: - status = results[0]["status"] -+ if status == "failed": -+ errormsg = results[0]['error']['message'] -+ elif status == "success": -+ txid = results[0]['result']['txid'] - break - print('...returned status: {}'.format(status)) -! assert_equal(in_status, status) -! if errormsg is not None: -! assert(in_errormsg is not None) -! assert_equal(in_errormsg in errormsg, True) -! print('...returned error: {}'.format(errormsg)) -! return txid - - def run_test (self): - print "Mining blocks..." -*************** -*** 94,100 **** - recipients = [] - recipients.append({"address":myzaddr, "amount": Decimal('20.0') - Decimal('0.0001')}) - myopid = self.nodes[0].z_sendmany(mytaddr, recipients) -! self.wait_for_operationd_success(myopid) - self.sync_all() - self.nodes[1].generate(1) - self.sync_all() ---- 106,112 ---- - recipients = [] - recipients.append({"address":myzaddr, "amount": Decimal('20.0') - Decimal('0.0001')}) - myopid = self.nodes[0].z_sendmany(mytaddr, recipients) -! self.wait_and_assert_operationid_status(myopid) - self.sync_all() - self.nodes[1].generate(1) - self.sync_all() -*************** -*** 109,116 **** - recipients = [] - recipients.append({"address":mytaddr, "amount":Decimal('10.0')}) - myopid = self.nodes[0].z_sendmany(myzaddr, recipients) -! self.wait_for_operationd_success(myopid) - self.sync_all() - self.nodes[1].generate(1) - self.sync_all() - ---- 121,134 ---- - recipients = [] - recipients.append({"address":mytaddr, "amount":Decimal('10.0')}) - myopid = self.nodes[0].z_sendmany(myzaddr, recipients) -! mytxid = self.wait_and_assert_operationid_status(myopid) -! assert(mytxid is not None) - self.sync_all() -+ -+ # check that priority of the tx sending from a zaddr is not 0 -+ mempool = self.nodes[0].getrawmempool(True) -+ assert(Decimal(mempool[mytxid]['startingpriority']) >= Decimal('1000000000000')) -+ - self.nodes[1].generate(1) - self.sync_all() - -*************** -*** 120,125 **** ---- 138,152 ---- - assert_equal(Decimal(resp["private"]), Decimal('9.9998')) - assert_equal(Decimal(resp["total"]), Decimal('39.9998')) - -+ # z_sendmany will return an error if there is transparent change output considered dust. -+ # UTXO selection in z_sendmany sorts in ascending order, so smallest utxos are consumed first. -+ # At this point in time, unspent notes all have a value of 10.0 and standard z_sendmany fee is 0.0001. -+ recipients = [] -+ amount = Decimal('10.0') - Decimal('0.00010000') - Decimal('0.00000001') # this leaves change at 1 zatoshi less than dust threshold -+ recipients.append({"address":self.nodes[0].getnewaddress(), "amount":amount }) -+ myopid = self.nodes[0].z_sendmany(mytaddr, recipients) -+ self.wait_and_assert_operationid_status(myopid, "failed", "Insufficient transparent funds, have 10.00, need 0.00000545 more to avoid creating invalid change output 0.00000001 (dust threshold is 0.00000546)") -+ - # Send will fail because send amount is too big, even when including coinbase utxos - errorString = "" - try: -*************** -*** 128,133 **** ---- 155,168 ---- - errorString = e.error['message'] - assert_equal("Insufficient funds" in errorString, True) - -+ # z_sendmany will fail because of insufficient funds -+ recipients = [] -+ recipients.append({"address":self.nodes[1].getnewaddress(), "amount":Decimal('10000.0')}) -+ myopid = self.nodes[0].z_sendmany(mytaddr, recipients) -+ self.wait_and_assert_operationid_status(myopid, "failed", "Insufficient transparent funds, have 10.00, need 10000.0001") -+ myopid = self.nodes[0].z_sendmany(myzaddr, recipients) -+ self.wait_and_assert_operationid_status(myopid, "failed", "Insufficient protected funds, have 9.9998, need 10000.0001") -+ - # Send will fail because of insufficient funds unless sender uses coinbase utxos - try: - self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 21) -*************** -*** 135,140 **** ---- 170,227 ---- - errorString = e.error['message'] - assert_equal("Insufficient funds, coinbase funds can only be spent after they have been sent to a zaddr" in errorString, True) - -+ # Verify that mempools accept tx with joinsplits which have at least the default z_sendmany fee. -+ # If this test passes, it confirms that issue #1851 has been resolved, where sending from -+ # a zaddr to 1385 taddr recipients fails because the default fee was considered too low -+ # given the tx size, resulting in mempool rejection. -+ errorString = '' -+ recipients = [] -+ num_t_recipients = 2500 -+ amount_per_recipient = Decimal('0.00000546') # dust threshold -+ # Note that regtest chainparams does not require standard tx, so setting the amount to be -+ # less than the dust threshold, e.g. 0.00000001 will not result in mempool rejection. -+ for i in xrange(0,num_t_recipients): -+ newtaddr = self.nodes[2].getnewaddress() -+ recipients.append({"address":newtaddr, "amount":amount_per_recipient}) -+ myopid = self.nodes[0].z_sendmany(myzaddr, recipients) -+ try: -+ self.wait_and_assert_operationid_status(myopid) -+ except JSONRPCException as e: -+ print("JSONRPC error: "+e.error['message']) -+ assert(False) -+ except Exception as e: -+ print("Unexpected exception caught during testing: "+str(sys.exc_info()[0])) -+ assert(False) -+ -+ self.sync_all() -+ self.nodes[1].generate(1) -+ self.sync_all() -+ -+ # check balance -+ node2balance = amount_per_recipient * num_t_recipients -+ assert_equal(self.nodes[2].getbalance(), node2balance) -+ -+ # Send will fail because fee is negative -+ try: -+ self.nodes[0].z_sendmany(myzaddr, recipients, 1, -1) -+ except JSONRPCException,e: -+ errorString = e.error['message'] -+ assert_equal("Invalid amount" in errorString, True) -+ -+ # Send will fail because fee is larger than MAX_MONEY -+ try: -+ self.nodes[0].z_sendmany(myzaddr, recipients, 1, Decimal('21000000.00000001')) -+ except JSONRPCException,e: -+ errorString = e.error['message'] -+ assert_equal("Invalid amount" in errorString, True) -+ -+ # Send will fail because fee is larger than sum of outputs -+ try: -+ self.nodes[0].z_sendmany(myzaddr, recipients, 1, (amount_per_recipient * num_t_recipients) + Decimal('0.00000001')) -+ except JSONRPCException,e: -+ errorString = e.error['message'] -+ assert_equal("is greater than the sum of outputs" in errorString, True) -+ - # Send will succeed because the balance of non-coinbase utxos is 10.0 - try: - self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 9) -*************** -*** 146,152 **** - self.sync_all() - - # check balance -! assert_equal(self.nodes[2].getbalance(), 9) - - if __name__ == '__main__': -! Wallet2Test ().main () ---- 233,263 ---- - self.sync_all() - - # check balance -! node2balance = node2balance + 9 -! assert_equal(self.nodes[2].getbalance(), node2balance) -! -! # Check that chained joinsplits in a single tx are created successfully. -! recipients = [] -! num_recipients = 3 -! amount_per_recipient = Decimal('0.002') -! minconf = 1 -! send_amount = num_recipients * amount_per_recipient -! custom_fee = Decimal('0.00012345') -! zbalance = self.nodes[0].z_getbalance(myzaddr) -! for i in xrange(0,num_recipients): -! newzaddr = self.nodes[2].z_getnewaddress() -! recipients.append({"address":newzaddr, "amount":amount_per_recipient}) -! myopid = self.nodes[0].z_sendmany(myzaddr, recipients, minconf, custom_fee) -! self.wait_and_assert_operationid_status(myopid) -! self.sync_all() -! self.nodes[1].generate(1) -! self.sync_all() -! -! # check balances -! resp = self.nodes[2].z_gettotalbalance() -! assert_equal(Decimal(resp["private"]), send_amount) -! resp = self.nodes[0].z_getbalance(myzaddr) -! assert_equal(Decimal(resp), zbalance - custom_fee - send_amount) - - if __name__ == '__main__': -! WalletProtectCoinbaseTest().main() -diff -crB ./qa/rpc-tests/wallet.py ../../komodo-jl777/qa/rpc-tests/wallet.py -*** ./qa/rpc-tests/wallet.py 2017-01-03 10:40:50.199328558 +0000 ---- ../../komodo-jl777/qa/rpc-tests/wallet.py 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 244,249 **** ---- 244,295 ---- - myvjoinsplits = mytxdetails["vjoinsplit"] - assert_equal(0, len(myvjoinsplits)) - -+ # z_sendmany is expected to fail if tx size breaks limit -+ myzaddr = self.nodes[0].z_getnewaddress() -+ -+ recipients = [] -+ num_t_recipients = 3000 -+ amount_per_recipient = Decimal('0.00000001') -+ errorString = '' -+ for i in xrange(0,num_t_recipients): -+ newtaddr = self.nodes[2].getnewaddress() -+ recipients.append({"address":newtaddr, "amount":amount_per_recipient}) -+ try: -+ self.nodes[0].z_sendmany(myzaddr, recipients) -+ except JSONRPCException,e: -+ errorString = e.error['message'] -+ assert("Too many outputs, size of raw transaction" in errorString) -+ -+ recipients = [] -+ num_t_recipients = 2000 -+ num_z_recipients = 50 -+ amount_per_recipient = Decimal('0.00000001') -+ errorString = '' -+ for i in xrange(0,num_t_recipients): -+ newtaddr = self.nodes[2].getnewaddress() -+ recipients.append({"address":newtaddr, "amount":amount_per_recipient}) -+ for i in xrange(0,num_z_recipients): -+ newzaddr = self.nodes[2].z_getnewaddress() -+ recipients.append({"address":newzaddr, "amount":amount_per_recipient}) -+ try: -+ self.nodes[0].z_sendmany(myzaddr, recipients) -+ except JSONRPCException,e: -+ errorString = e.error['message'] -+ assert("size of raw transaction would be larger than limit" in errorString) -+ -+ recipients = [] -+ num_z_recipients = 100 -+ amount_per_recipient = Decimal('0.00000001') -+ errorString = '' -+ for i in xrange(0,num_z_recipients): -+ newzaddr = self.nodes[2].z_getnewaddress() -+ recipients.append({"address":newzaddr, "amount":amount_per_recipient}) -+ try: -+ self.nodes[0].z_sendmany(myzaddr, recipients) -+ except JSONRPCException,e: -+ errorString = e.error['message'] -+ assert("Invalid parameter, too many zaddr outputs" in errorString) -+ - # add zaddr to node 2 - myzaddr = self.nodes[2].z_getnewaddress() - -Only in ../../komodo-jl777/qa/rpc-tests: wallet_treestate.py -diff -crB ./qa/rpc-tests/zcjoinsplit.py ../../komodo-jl777/qa/rpc-tests/zcjoinsplit.py -*** ./qa/rpc-tests/zcjoinsplit.py 2017-01-03 10:40:50.203328760 +0000 ---- ../../komodo-jl777/qa/rpc-tests/zcjoinsplit.py 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 36,41 **** ---- 36,49 ---- - receive_result = self.nodes[0].zcrawreceive(zcsecretkey, joinsplit_result["encryptednote1"]) - assert_equal(receive_result["exists"], True) - -+ # The pure joinsplit we create should be mined in the next block -+ # despite other transactions being in the mempool. -+ addrtest = self.nodes[0].getnewaddress() -+ for xx in range(0,10): -+ self.nodes[0].generate(1) -+ for x in range(0,50): -+ self.nodes[0].sendtoaddress(addrtest, 0.01); -+ - joinsplit_tx = self.nodes[0].createrawtransaction([], {}) - joinsplit_result = self.nodes[0].zcrawjoinsplit(joinsplit_tx, {receive_result["note"] : zcsecretkey}, {zcaddress: 39.8}, 0, 0.1) - -diff -crB ./qa/zcash/performance-measurements.sh ../../komodo-jl777/qa/zcash/performance-measurements.sh -*** ./qa/zcash/performance-measurements.sh 2017-01-03 10:40:50.203328760 +0000 ---- ../../komodo-jl777/qa/zcash/performance-measurements.sh 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 88,93 **** ---- 88,99 ---- - validatelargetx) - zcash_rpc zcbenchmark validatelargetx 5 - ;; -+ trydecryptnotes) -+ zcash_rpc zcbenchmark trydecryptnotes 1000 "${@:3}" -+ ;; -+ incnotewitnesses) -+ zcash_rpc zcbenchmark incnotewitnesses 100 "${@:3}" -+ ;; - *) - zcashd_stop - echo "Bad arguments." -*************** -*** 116,121 **** ---- 122,133 ---- - verifyequihash) - zcash_rpc zcbenchmark verifyequihash 1 - ;; -+ trydecryptnotes) -+ zcash_rpc zcbenchmark trydecryptnotes 1 "${@:3}" -+ ;; -+ incnotewitnesses) -+ zcash_rpc zcbenchmark incnotewitnesses 1 "${@:3}" -+ ;; - *) - zcashd_massif_stop - echo "Bad arguments." -*************** -*** 145,150 **** ---- 157,168 ---- - verifyequihash) - zcash_rpc zcbenchmark verifyequihash 1 - ;; -+ trydecryptnotes) -+ zcash_rpc zcbenchmark trydecryptnotes 1 "${@:3}" -+ ;; -+ incnotewitnesses) -+ zcash_rpc zcbenchmark incnotewitnesses 1 "${@:3}" -+ ;; - *) - zcashd_valgrind_stop - echo "Bad arguments." -diff -crB ./README.md ../../komodo-jl777/README.md -*** ./README.md 2017-01-03 10:40:50.151326129 +0000 ---- ../../komodo-jl777/README.md 2017-01-03 09:49:08.848505929 +0000 -*************** -*** 1,43 **** -- <<<<<<< HEAD - -- Zcash -- ===== -- -- https://z.cash/ -- -- Where do I begin? -- ----------------- -- -- We have a guide for joining the public testnet: https://github.com/zcash/zcash/wiki/Beta-Guide -- -- What is Zcash? -- -------------- -- -- Zcash is an implementation of the "Zerocash" protocol. Based on Bitcoin's code, it intends to -- offer a far higher standard of privacy and anonymity through a sophisticiated zero-knowledge -- proving scheme which preserves confidentiality of transaction metadata. -- -- **Zcash is unfinished and highly experimental.** Use at your own risk. -- -- Participation in the Zcash project is subject to a [Code of Conduct](code_of_conduct.md). -- -- ======= -- Zcash 1.0.0 -- =========== - - What is Zcash? - -------------- - - [Zcash](https://z.cash/) is an implementation of the "Zerocash" protocol. - Based on Bitcoin's code, it intends to offer a far higher standard of privacy -! and anonymity through a sophisticated zero-knowledge proving scheme that -! preserves confidentiality of transaction metadata. Technical details are -! available in our [Protocol Specification](https://github.com/zcash/zips/raw/master/protocol/protocol.pdf). - - This software is the Zcash client. It downloads and stores the entire history - of Zcash transactions; depending on the speed of your computer and network - connection, the synchronization process could take a day or more once the -! block chain has reached a significant size. - - Security Warnings - ----------------- ---- 1,18 ---- - - - What is Zcash? - -------------- - - [Zcash](https://z.cash/) is an implementation of the "Zerocash" protocol. - Based on Bitcoin's code, it intends to offer a far higher standard of privacy -! through a sophisticated zero-knowledge proving scheme that preserves -! confidentiality of transaction metadata. Technical details are available -! in our [Protocol Specification](https://github.com/zcash/zips/raw/master/protocol/protocol.pdf). - - This software is the Zcash client. It downloads and stores the entire history - of Zcash transactions; depending on the speed of your computer and network - connection, the synchronization process could take a day or more once the -! blockchain has reached a significant size. - - Security Warnings - ----------------- -*************** -*** 165,173 **** - - Where do I begin? - ----------------- -! -! We have a guide for joining the public testnet: -! https://github.com/zcash/zcash/wiki/Beta-Guide - - ### Need Help? - ---- 140,147 ---- - - Where do I begin? - ----------------- -! We have a guide for joining the main Zcash network: -! https://github.com/zcash/zcash/wiki/1.0-User-Guide - - ### Need Help? - -*************** -*** 182,188 **** - -------- - - Build Zcash along with most dependencies from source by running -! ./zcutil/build.sh. Currently only Linux is supported. - - License - ------- ---- 156,162 ---- - -------- - - Build Zcash along with most dependencies from source by running -! ./zcutil/build.sh. Currently only Linux is officially supported. - - License - ------- -diff -crB ./src/assetchains ../../komodo-jl777/src/assetchains -*** ./src/assetchains 2017-01-03 10:40:50.211329166 +0000 ---- ../../komodo-jl777/src/assetchains 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 3,96 **** - source pubkey.txt - echo $pubkey - -! ./komodod -pubkey=$pubkey -ac_name=REVS -ac_supply=1300000 -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=SUPERNET -ac_supply=816061 -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=DEX -ac_supply=999999 -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=PANGEA -ac_supply=999999 -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=JUMBLR -ac_supply=999999 -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=BET -ac_supply=999999 -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=CRYPTO -ac_supply=999999 -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=HODL -ac_supply=9999999 -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=SHARK -ac_supply=1401 -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=BOTS -ac_supply=999999 -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=MGW -ac_supply=999999 -addnode=78.47.196.146 $1 & - -! ./komodod -pubkey=$pubkey -ac_name=USD -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=EUR -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=JPY -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=GBP -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=AUD -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=CAD -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=CHF -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=NZD -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=CNY -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=RUB -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=MXN -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=BRL -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=INR -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=HKD -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=TRY -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=ZAR -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=PLN -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=NOK -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=SEK -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=DKK -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=CZK -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=HUF -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=ILS -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=KRW -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=MYR -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=PHP -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=RON -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=SGD -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=THB -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=BGN -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=IDR -addnode=78.47.196.146 $1 & -! ./komodod -pubkey=$pubkey -ac_name=HRK -addnode=78.47.196.146 $1 & -! -! curl --url "http://127.0.0.1:7776" --data "{\"timeout\":60000,\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"REVS\",\"pubkey\":\"$pubkey\"}" -! -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"SUPERNET\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"DEX\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"PANGEA\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"JUMBLR\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"BET\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"CRYPTO\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"HODL\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"SHARK\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"BOTS\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"MGW\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"USD\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"EUR\",\"pubkey\":\"$pubkey\"}" -! -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"JPY\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"GBP\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"AUD\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"CAD\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"CHF\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"NZD\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"CNY\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"RUB\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"MXN\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"BRL\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"INR\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"HKD\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"TRY\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"ZAR\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"PLN\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"NOK\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"SEK\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"DKK\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"CZK\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"HUF\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"ILS\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"KRW\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"MYR\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"PHP\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"RON\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"SGD\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"THB\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"BGN\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"IDR\",\"pubkey\":\"$pubkey\"}" -! curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"HRK\",\"pubkey\":\"$pubkey\"}" - ---- 3,50 ---- - source pubkey.txt - echo $pubkey - -! ./komodod -pubkey=$pubkey -ac_name=REVS -ac_supply=1300000 -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=SUPERNET -ac_supply=816061 -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=DEX -ac_supply=999999 -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=PANGEA -ac_supply=999999 -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=JUMBLR -ac_supply=999999 -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=BET -ac_supply=999999 -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=CRYPTO -ac_supply=999999 -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=HODL -ac_supply=9999999 -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=SHARK -ac_supply=1401 -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=BOTS -ac_supply=999999 -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=MGW -ac_supply=999999 -addnode=78.47.196.146 $1 -gen & - -! ./komodod -pubkey=$pubkey -ac_name=USD -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=EUR -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=JPY -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=GBP -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=AUD -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=CAD -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=CHF -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=NZD -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=CNY -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=RUB -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=MXN -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=BRL -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=INR -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=HKD -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=TRY -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=ZAR -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=PLN -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=NOK -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=SEK -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=DKK -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=CZK -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=HUF -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=ILS -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=KRW -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=MYR -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=PHP -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=RON -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=SGD -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=THB -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=BGN -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=IDR -addnode=78.47.196.146 $1 -gen & -! ./komodod -pubkey=$pubkey -ac_name=HRK -addnode=78.47.196.146 $1 -gen & - -diff -crB ./src/bitcoind.cpp ../../komodo-jl777/src/bitcoind.cpp -*** ./src/bitcoind.cpp 2017-01-03 10:40:50.215329368 +0000 ---- ../../komodo-jl777/src/bitcoind.cpp 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 41,47 **** - // Tell the main threads to shutdown. - while (!fShutdown) - { -! MilliSleep(10000); - komodo_passport_iteration(); - fShutdown = ShutdownRequested(); - } ---- 41,47 ---- - // Tell the main threads to shutdown. - while (!fShutdown) - { -! MilliSleep(16000); - komodo_passport_iteration(); - fShutdown = ShutdownRequested(); - } -diff -crB ./src/chainparams.cpp ../../komodo-jl777/src/chainparams.cpp -*** ./src/chainparams.cpp 2017-01-03 10:40:50.215329368 +0000 ---- ../../komodo-jl777/src/chainparams.cpp 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 43,48 **** ---- 43,49 ---- - CMainParams() - { - strNetworkID = "main"; -+ strCurrencyUnits = "KMD"; - consensus.fCoinbaseMustBeProtected = false;//true; - consensus.nSubsidySlowStartInterval = 20000; - consensus.nSubsidyHalvingInterval = 840000; -*************** -*** 119,129 **** - checkpointData = (Checkpoints::CCheckpointData) - { - boost::assign::map_list_of -! ( 0, consensus.hashGenesisBlock), -! genesis.nTime, // * UNIX timestamp of last checkpoint block -! 0, // * total number of transactions between genesis and last checkpoint -! // (the tx=... number in the SetBestChain debug.log lines) -! 0 // * estimated number of transactions per day after checkpoint - }; - if ( pthread_create((pthread_t *)malloc(sizeof(pthread_t)),NULL,chainparams_commandline,(void *)&consensus) != 0 ) - { ---- 120,134 ---- - checkpointData = (Checkpoints::CCheckpointData) - { - boost::assign::map_list_of -! (0, consensus.hashGenesisBlock), -! //(2500, uint256S("0x0e6a3d5a46eba97c4e7618d66a39f115729e1176433c98481124c2bf733aa54e")) -! //(15000, uint256S("0x00f0bd236790e903321a2d22f85bd6bf8a505f6ef4eddb20458a65d37e14d142")), -! //(100000, uint256S("0x0f02eb1f3a4b89df9909fec81a4bd7d023e32e24e1f5262d9fc2cc36a715be6f")), -! 1481120910, // * UNIX timestamp of last checkpoint block -! 110415, // * total number of transactions between genesis and last checkpoint -! // (the tx=... number in the SetBestChain debug.log lines) -! 4240 // * estimated number of transactions per day after checkpoint -! // total number of tx / (checkpoint block height / (24 * 24)) - }; - if ( pthread_create((pthread_t *)malloc(sizeof(pthread_t)),NULL,chainparams_commandline,(void *)&consensus) != 0 ) - { -*************** -*** 160,165 **** ---- 165,171 ---- - public: - CTestNetParams() { - strNetworkID = "test"; -+ strCurrencyUnits = "TAZ"; - consensus.nMajorityEnforceBlockUpgrade = 51; - consensus.nMajorityRejectBlockOutdated = 75; - consensus.nMajorityWindow = 400; -*************** -*** 222,227 **** ---- 228,234 ---- - public: - CRegTestParams() { - strNetworkID = "regtest"; -+ strCurrencyUnits = "REG"; - consensus.fCoinbaseMustBeProtected = false; - consensus.nSubsidySlowStartInterval = 0; - consensus.nSubsidyHalvingInterval = 150; -diff -crB ./src/chainparams.h ../../komodo-jl777/src/chainparams.h -*** ./src/chainparams.h 2017-01-03 10:40:50.215329368 +0000 ---- ../../komodo-jl777/src/chainparams.h 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 69,74 **** ---- 69,75 ---- - int64_t PruneAfterHeight() const { return nPruneAfterHeight; } - unsigned int EquihashN() const { return nEquihashN; } - unsigned int EquihashK() const { return nEquihashK; } -+ std::string CurrencyUnits() const { return strCurrencyUnits; } - /** Make miner stop after a block is found. In RPC, don't return until nGenProcLimit blocks are generated */ - bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; } - /** In the future use NetworkIDString() for RPC fields */ -*************** -*** 107,112 **** ---- 108,114 ---- - std::vector vSeeds; - std::vector base58Prefixes[MAX_BASE58_TYPES]; - std::string strNetworkID; -+ std::string strCurrencyUnits; - CBlock genesis; - std::vector vFixedSeeds; - bool fRequireRPCPassword = false; -diff -crB ./src/clientversion.h ../../komodo-jl777/src/clientversion.h -*** ./src/clientversion.h 2017-01-03 10:40:50.215329368 +0000 ---- ../../komodo-jl777/src/clientversion.h 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 16,22 **** - //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it - #define CLIENT_VERSION_MAJOR 1 - #define CLIENT_VERSION_MINOR 0 -! #define CLIENT_VERSION_REVISION 0 - #define CLIENT_VERSION_BUILD 50 - - //! Set to true for release, false for prerelease or test build ---- 16,22 ---- - //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it - #define CLIENT_VERSION_MAJOR 1 - #define CLIENT_VERSION_MINOR 0 -! #define CLIENT_VERSION_REVISION 3 - #define CLIENT_VERSION_BUILD 50 - - //! Set to true for release, false for prerelease or test build -diff -crB ./src/coins.cpp ../../komodo-jl777/src/coins.cpp -*** ./src/coins.cpp 2017-01-03 10:40:50.215329368 +0000 ---- ../../komodo-jl777/src/coins.cpp 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 6,11 **** ---- 6,12 ---- - - #include "memusage.h" - #include "random.h" -+ #include "version.h" - - #include - -*************** -*** 176,186 **** - // case restoring the "old" anchor during a reorg must - // have no effect. - if (currentRoot != newrt) { -! CAnchorsMap::iterator ret = cacheAnchors.insert(std::make_pair(currentRoot, CAnchorsCacheEntry())).first; - -! ret->second.entered = false; -! ret->second.flags = CAnchorsCacheEntry::DIRTY; - - hashAnchor = newrt; - } - } ---- 177,196 ---- - // case restoring the "old" anchor during a reorg must - // have no effect. - if (currentRoot != newrt) { -! // Bring the current best anchor into our local cache -! // so that its tree exists in memory. -! { -! ZCIncrementalMerkleTree tree; -! assert(GetAnchorAt(currentRoot, tree)); -! } - -! // Mark the anchor as unentered, removing it from view -! cacheAnchors[currentRoot].entered = false; - -+ // Mark the cache entry as dirty so it's propagated -+ cacheAnchors[currentRoot].flags = CAnchorsCacheEntry::DIRTY; -+ -+ // Mark the new root as the best anchor - hashAnchor = newrt; - } - } -*************** -*** 303,318 **** - CAnchorsMap::iterator parent_it = cacheAnchors.find(child_it->first); - - if (parent_it == cacheAnchors.end()) { -! if (child_it->second.entered) { -! // Parent doesn't have an entry, but child has a new commitment root. -! -! CAnchorsCacheEntry& entry = cacheAnchors[child_it->first]; -! entry.entered = true; -! entry.tree = child_it->second.tree; -! entry.flags = CAnchorsCacheEntry::DIRTY; - -! cachedCoinsUsage += memusage::DynamicUsage(entry.tree); -! } - } else { - if (parent_it->second.entered != child_it->second.entered) { - // The parent may have removed the entry. ---- 313,324 ---- - CAnchorsMap::iterator parent_it = cacheAnchors.find(child_it->first); - - if (parent_it == cacheAnchors.end()) { -! CAnchorsCacheEntry& entry = cacheAnchors[child_it->first]; -! entry.entered = child_it->second.entered; -! entry.tree = child_it->second.tree; -! entry.flags = CAnchorsCacheEntry::DIRTY; - -! cachedCoinsUsage += memusage::DynamicUsage(entry.tree); - } else { - if (parent_it->second.entered != child_it->second.entered) { - // The parent may have removed the entry. -*************** -*** 332,345 **** - CNullifiersMap::iterator parent_it = cacheNullifiers.find(child_it->first); - - if (parent_it == cacheNullifiers.end()) { -! if (child_it->second.entered) { -! // Parent doesn't have an entry, but child has a SPENT nullifier. -! // Move the spent nullifier up. -! -! CNullifiersCacheEntry& entry = cacheNullifiers[child_it->first]; -! entry.entered = true; -! entry.flags = CNullifiersCacheEntry::DIRTY; -! } - } else { - if (parent_it->second.entered != child_it->second.entered) { - parent_it->second.entered = child_it->second.entered; ---- 338,346 ---- - CNullifiersMap::iterator parent_it = cacheNullifiers.find(child_it->first); - - if (parent_it == cacheNullifiers.end()) { -! CNullifiersCacheEntry& entry = cacheNullifiers[child_it->first]; -! entry.entered = child_it->second.entered; -! entry.flags = CNullifiersCacheEntry::DIRTY; - } else { - if (parent_it->second.entered != child_it->second.entered) { - parent_it->second.entered = child_it->second.entered; -*************** -*** 469,474 **** ---- 470,476 ---- - { - if (tx.IsCoinBase()) - return 0.0; -+ CAmount nTotalIn = 0; - double dResult = 0.0; - BOOST_FOREACH(const CTxIn& txin, tx.vin) - { -*************** -*** 477,484 **** ---- 479,512 ---- - if (!coins->IsAvailable(txin.prevout.n)) continue; - if (coins->nHeight < nHeight) { - dResult += coins->vout[txin.prevout.n].nValue * (nHeight-coins->nHeight); -+ nTotalIn += coins->vout[txin.prevout.n].nValue; - } - } -+ -+ // If a transaction contains a joinsplit, we boost the priority of the transaction. -+ // Joinsplits do not reveal any information about the value or age of a note, so we -+ // cannot apply the priority algorithm used for transparent utxos. Instead, we pick a -+ // very large number and multiply it by the transaction's fee per 1000 bytes of data. -+ // One trillion, 1000000000000, is equivalent to 1 ZEC utxo * 10000 blocks (~17 days). -+ if (tx.vjoinsplit.size() > 0) { -+ unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); -+ nTotalIn += tx.GetJoinSplitValueIn(); -+ CAmount fee = nTotalIn - tx.GetValueOut(); -+ CFeeRate feeRate(fee, nTxSize); -+ CAmount feePerK = feeRate.GetFeePerK(); -+ -+ if (feePerK == 0) { -+ feePerK = 1; -+ } -+ -+ dResult += 1000000000000 * double(feePerK); -+ // We cast feePerK from int64_t to double because if feePerK is a large number, say -+ // close to MAX_MONEY, the multiplication operation will result in an integer overflow. -+ // The variable dResult should never overflow since a 64-bit double in C++ is typically -+ // a double-precision floating-point number as specified by IEE 754, with a maximum -+ // value DBL_MAX of 1.79769e+308. -+ } -+ - return tx.ComputePriority(dResult); - } - -Only in ../../komodo-jl777/src: dpowassets -Only in ../../komodo-jl777/src: fundnotaries -diff -crB ./src/gtest/test_checkblock.cpp ../../komodo-jl777/src/gtest/test_checkblock.cpp -*** ./src/gtest/test_checkblock.cpp 2017-01-03 10:40:50.227329975 +0000 ---- ../../komodo-jl777/src/gtest/test_checkblock.cpp 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 29,31 **** ---- 29,74 ---- - EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "version-too-low", false)).Times(1); - EXPECT_FALSE(CheckBlock(0,0,block, state, false, false)); - } -+ -+ TEST(ContextualCheckBlock, BadCoinbaseHeight) { -+ SelectParams(CBaseChainParams::MAIN); -+ -+ // Create a block with no height in scriptSig -+ CMutableTransaction mtx; -+ mtx.vin.resize(1); -+ mtx.vin[0].prevout.SetNull(); -+ mtx.vin[0].scriptSig = CScript() << OP_0; -+ mtx.vout.resize(1); -+ mtx.vout[0].scriptPubKey = CScript() << OP_TRUE; -+ mtx.vout[0].nValue = 0; -+ CTransaction tx {mtx}; -+ CBlock block; -+ block.vtx.push_back(tx); -+ -+ // Treating block as genesis should pass -+ MockCValidationState state; -+ EXPECT_TRUE(ContextualCheckBlock(block, state, NULL)); -+ -+ // Treating block as non-genesis should fail -+ mtx.vout.push_back(CTxOut(GetBlockSubsidy(1, Params().GetConsensus())/5, Params().GetFoundersRewardScriptAtHeight(1))); -+ CTransaction tx2 {mtx}; -+ block.vtx[0] = tx2; -+ CBlock prev; -+ CBlockIndex indexPrev {prev}; -+ indexPrev.nHeight = 0; -+ EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-height", false)).Times(1); -+ EXPECT_FALSE(ContextualCheckBlock(block, state, &indexPrev)); -+ -+ // Setting to an incorrect height should fail -+ mtx.vin[0].scriptSig = CScript() << 2 << OP_0; -+ CTransaction tx3 {mtx}; -+ block.vtx[0] = tx3; -+ EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-height", false)).Times(1); -+ EXPECT_FALSE(ContextualCheckBlock(block, state, &indexPrev)); -+ -+ // After correcting the scriptSig, should pass -+ mtx.vin[0].scriptSig = CScript() << 1 << OP_0; -+ CTransaction tx4 {mtx}; -+ block.vtx[0] = tx4; -+ EXPECT_TRUE(ContextualCheckBlock(block, state, &indexPrev)); -+ } -diff -crB ./src/gtest/test_joinsplit.cpp ../../komodo-jl777/src/gtest/test_joinsplit.cpp -*** ./src/gtest/test_joinsplit.cpp 2017-01-03 10:40:50.227329975 +0000 ---- ../../komodo-jl777/src/gtest/test_joinsplit.cpp 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 15,20 **** ---- 15,23 ---- - - void test_full_api(ZCJoinSplit* js) - { -+ // Create verification context. -+ auto verifier = libzcash::ProofVerifier::Strict(); -+ - // The recipient's information. - SpendingKey recipient_key = SpendingKey::random(); - PaymentAddress recipient_addr = recipient_key.address(); -*************** -*** 69,74 **** ---- 72,78 ---- - // Verify the transaction: - ASSERT_TRUE(js->verify( - proof, -+ verifier, - pubKeyHash, - randomSeed, - macs, -*************** -*** 143,148 **** ---- 147,153 ---- - // Verify the transaction: - ASSERT_TRUE(js->verify( - proof, -+ verifier, - pubKeyHash, - randomSeed, - macs, -*************** -*** 154,159 **** ---- 159,222 ---- - )); - } - -+ // Invokes the API (but does not compute a proof) -+ // to test exceptions -+ void invokeAPI( -+ ZCJoinSplit* js, -+ const boost::array& inputs, -+ const boost::array& outputs, -+ uint64_t vpub_old, -+ uint64_t vpub_new, -+ const uint256& rt -+ ) { -+ uint256 ephemeralKey; -+ uint256 randomSeed; -+ uint256 pubKeyHash = random_uint256(); -+ boost::array macs; -+ boost::array nullifiers; -+ boost::array commitments; -+ boost::array ciphertexts; -+ -+ boost::array output_notes; -+ -+ ZCProof proof = js->prove( -+ inputs, -+ outputs, -+ output_notes, -+ ciphertexts, -+ ephemeralKey, -+ pubKeyHash, -+ randomSeed, -+ macs, -+ nullifiers, -+ commitments, -+ vpub_old, -+ vpub_new, -+ rt, -+ false -+ ); -+ } -+ -+ void invokeAPIFailure( -+ ZCJoinSplit* js, -+ const boost::array& inputs, -+ const boost::array& outputs, -+ uint64_t vpub_old, -+ uint64_t vpub_new, -+ const uint256& rt, -+ std::string reason -+ ) -+ { -+ try { -+ invokeAPI(js, inputs, outputs, vpub_old, vpub_new, rt); -+ FAIL() << "It worked, when it shouldn't have!"; -+ } catch(std::invalid_argument const & err) { -+ EXPECT_EQ(err.what(), reason); -+ } catch(...) { -+ FAIL() << "Expected invalid_argument exception."; -+ } -+ } -+ - TEST(joinsplit, h_sig) - { - auto js = ZCJoinSplit::Unopened(); -*************** -*** 233,242 **** ---- 296,515 ---- - delete js; - } - -+ void increment_note_witnesses( -+ const uint256& element, -+ std::vector& witnesses, -+ ZCIncrementalMerkleTree& tree -+ ) -+ { -+ tree.append(element); -+ for (ZCIncrementalWitness& w : witnesses) { -+ w.append(element); -+ } -+ witnesses.push_back(tree.witness()); -+ } -+ - TEST(joinsplit, full_api_test) - { - auto js = ZCJoinSplit::Generate(); - -+ { -+ std::vector witnesses; -+ ZCIncrementalMerkleTree tree; -+ increment_note_witnesses(uint256(), witnesses, tree); -+ SpendingKey sk = SpendingKey::random(); -+ PaymentAddress addr = sk.address(); -+ Note note1(addr.a_pk, 100, random_uint256(), random_uint256()); -+ increment_note_witnesses(note1.cm(), witnesses, tree); -+ Note note2(addr.a_pk, 100, random_uint256(), random_uint256()); -+ increment_note_witnesses(note2.cm(), witnesses, tree); -+ Note note3(addr.a_pk, 2100000000000001, random_uint256(), random_uint256()); -+ increment_note_witnesses(note3.cm(), witnesses, tree); -+ Note note4(addr.a_pk, 1900000000000000, random_uint256(), random_uint256()); -+ increment_note_witnesses(note4.cm(), witnesses, tree); -+ Note note5(addr.a_pk, 1900000000000000, random_uint256(), random_uint256()); -+ increment_note_witnesses(note5.cm(), witnesses, tree); -+ -+ // Should work -+ invokeAPI(js, -+ { -+ JSInput(), -+ JSInput() -+ }, -+ { -+ JSOutput(), -+ JSOutput() -+ }, -+ 0, -+ 0, -+ tree.root()); -+ -+ // lhs > MAX_MONEY -+ invokeAPIFailure(js, -+ { -+ JSInput(), -+ JSInput() -+ }, -+ { -+ JSOutput(), -+ JSOutput() -+ }, -+ 2100000000000001, -+ 0, -+ tree.root(), -+ "nonsensical vpub_old value"); -+ -+ // rhs > MAX_MONEY -+ invokeAPIFailure(js, -+ { -+ JSInput(), -+ JSInput() -+ }, -+ { -+ JSOutput(), -+ JSOutput() -+ }, -+ 0, -+ 2100000000000001, -+ tree.root(), -+ "nonsensical vpub_new value"); -+ -+ // input witness for the wrong element -+ invokeAPIFailure(js, -+ { -+ JSInput(witnesses[0], note1, sk), -+ JSInput() -+ }, -+ { -+ JSOutput(), -+ JSOutput() -+ }, -+ 0, -+ 100, -+ tree.root(), -+ "witness of wrong element for joinsplit input"); -+ -+ // input witness doesn't match up with -+ // real root -+ invokeAPIFailure(js, -+ { -+ JSInput(witnesses[1], note1, sk), -+ JSInput() -+ }, -+ { -+ JSOutput(), -+ JSOutput() -+ }, -+ 0, -+ 100, -+ uint256(), -+ "joinsplit not anchored to the correct root"); -+ -+ // input is in the tree now! this should work -+ invokeAPI(js, -+ { -+ JSInput(witnesses[1], note1, sk), -+ JSInput() -+ }, -+ { -+ JSOutput(), -+ JSOutput() -+ }, -+ 0, -+ 100, -+ tree.root()); -+ -+ // Wrong secret key -+ invokeAPIFailure(js, -+ { -+ JSInput(witnesses[1], note1, SpendingKey::random()), -+ JSInput() -+ }, -+ { -+ JSOutput(), -+ JSOutput() -+ }, -+ 0, -+ 0, -+ tree.root(), -+ "input note not authorized to spend with given key"); -+ -+ // Absurd input value -+ invokeAPIFailure(js, -+ { -+ JSInput(witnesses[3], note3, sk), -+ JSInput() -+ }, -+ { -+ JSOutput(), -+ JSOutput() -+ }, -+ 0, -+ 0, -+ tree.root(), -+ "nonsensical input note value"); -+ -+ // Absurd total input value -+ invokeAPIFailure(js, -+ { -+ JSInput(witnesses[4], note4, sk), -+ JSInput(witnesses[5], note5, sk) -+ }, -+ { -+ JSOutput(), -+ JSOutput() -+ }, -+ 0, -+ 0, -+ tree.root(), -+ "nonsensical left hand size of joinsplit balance"); -+ -+ // Absurd output value -+ invokeAPIFailure(js, -+ { -+ JSInput(), -+ JSInput() -+ }, -+ { -+ JSOutput(addr, 2100000000000001), -+ JSOutput() -+ }, -+ 0, -+ 0, -+ tree.root(), -+ "nonsensical output value"); -+ -+ // Absurd total output value -+ invokeAPIFailure(js, -+ { -+ JSInput(), -+ JSInput() -+ }, -+ { -+ JSOutput(addr, 1900000000000000), -+ JSOutput(addr, 1900000000000000) -+ }, -+ 0, -+ 0, -+ tree.root(), -+ "nonsensical right hand side of joinsplit balance"); -+ -+ // Absurd total output value -+ invokeAPIFailure(js, -+ { -+ JSInput(), -+ JSInput() -+ }, -+ { -+ JSOutput(addr, 1900000000000000), -+ JSOutput() -+ }, -+ 0, -+ 0, -+ tree.root(), -+ "invalid joinsplit balance"); -+ } -+ - test_full_api(js); - - js->saveProvingKey("./zcashTest.pk"); -diff -crB ./src/gtest/test_merkletree.cpp ../../komodo-jl777/src/gtest/test_merkletree.cpp -*** ./src/gtest/test_merkletree.cpp 2017-01-03 10:40:50.227329975 +0000 ---- ../../komodo-jl777/src/gtest/test_merkletree.cpp 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 5,10 **** ---- 5,11 ---- - #include "test/data/merkle_serialization.json.h" - #include "test/data/merkle_witness_serialization.json.h" - #include "test/data/merkle_path.json.h" -+ #include "test/data/merkle_commitments.json.h" - - #include - -*************** -*** 55,86 **** - } - - template -! void test_tree(Array root_tests, Array ser_tests, Array witness_ser_tests, Array path_tests) { - Array::iterator root_iterator = root_tests.begin(); - Array::iterator ser_iterator = ser_tests.begin(); - Array::iterator witness_ser_iterator = witness_ser_tests.begin(); - Array::iterator path_iterator = path_tests.begin(); - -- uint256 test_commitment = uint256S("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); -- - Tree tree; - - // The root of the tree at this point is expected to be the root of the - // empty tree. - ASSERT_TRUE(tree.root() == Tree::empty_root()); - - // We need to witness at every single point in the tree, so - // that the consistency of the tree and the merkle paths can - // be checked. - vector witnesses; - - for (size_t i = 0; i < 16; i++) { - // Witness here - witnesses.push_back(tree.witness()); - - // Now append a commitment to the tree - tree.append(test_commitment); - - // Check tree root consistency - expect_test_vector(root_iterator, tree.root()); - ---- 56,101 ---- - } - - template -! void test_tree( -! Array commitment_tests, -! Array root_tests, -! Array ser_tests, -! Array witness_ser_tests, -! Array path_tests -! ) -! { -! Array::iterator commitment_iterator = commitment_tests.begin(); - Array::iterator root_iterator = root_tests.begin(); - Array::iterator ser_iterator = ser_tests.begin(); - Array::iterator witness_ser_iterator = witness_ser_tests.begin(); - Array::iterator path_iterator = path_tests.begin(); - - Tree tree; - - // The root of the tree at this point is expected to be the root of the - // empty tree. - ASSERT_TRUE(tree.root() == Tree::empty_root()); - -+ // The tree doesn't have a 'last' element added since it's blank. -+ ASSERT_THROW(tree.last(), std::runtime_error); -+ - // We need to witness at every single point in the tree, so - // that the consistency of the tree and the merkle paths can - // be checked. - vector witnesses; - - for (size_t i = 0; i < 16; i++) { -+ uint256 test_commitment = uint256S((commitment_iterator++)->get_str()); -+ - // Witness here - witnesses.push_back(tree.witness()); - - // Now append a commitment to the tree - tree.append(test_commitment); - -+ // Last element added to the tree was `test_commitment` -+ ASSERT_TRUE(tree.last() == test_commitment); -+ - // Check tree root consistency - expect_test_vector(root_iterator, tree.root()); - -*************** -*** 95,100 **** ---- 110,116 ---- - - if (first) { - ASSERT_THROW(wit.path(), std::runtime_error); -+ ASSERT_THROW(wit.element(), std::runtime_error); - } else { - auto path = wit.path(); - -*************** -*** 119,125 **** - - std::vector commitment_bv; - { -! std::vector commitment_v(test_commitment.begin(), test_commitment.end()); - commitment_bv = convertBytesVectorToVector(commitment_v); - } - ---- 135,142 ---- - - std::vector commitment_bv; - { -! uint256 witnessed_commitment = wit.element(); -! std::vector commitment_v(witnessed_commitment.begin(), witnessed_commitment.end()); - commitment_bv = convertBytesVectorToVector(commitment_v); - } - -*************** -*** 174,181 **** - Array ser_tests = read_json(std::string(json_tests::merkle_serialization, json_tests::merkle_serialization + sizeof(json_tests::merkle_serialization))); - Array witness_ser_tests = read_json(std::string(json_tests::merkle_witness_serialization, json_tests::merkle_witness_serialization + sizeof(json_tests::merkle_witness_serialization))); - Array path_tests = read_json(std::string(json_tests::merkle_path, json_tests::merkle_path + sizeof(json_tests::merkle_path))); - -! test_tree(root_tests, ser_tests, witness_ser_tests, path_tests); - } - - TEST(merkletree, emptyroots) { ---- 191,199 ---- - Array ser_tests = read_json(std::string(json_tests::merkle_serialization, json_tests::merkle_serialization + sizeof(json_tests::merkle_serialization))); - Array witness_ser_tests = read_json(std::string(json_tests::merkle_witness_serialization, json_tests::merkle_witness_serialization + sizeof(json_tests::merkle_witness_serialization))); - Array path_tests = read_json(std::string(json_tests::merkle_path, json_tests::merkle_path + sizeof(json_tests::merkle_path))); -+ Array commitment_tests = read_json(std::string(json_tests::merkle_commitments, json_tests::merkle_commitments + sizeof(json_tests::merkle_commitments))); - -! test_tree(commitment_tests, root_tests, ser_tests, witness_ser_tests, path_tests); - } - - TEST(merkletree, emptyroots) { -Only in ../../komodo-jl777/src/gtest: test_metrics.cpp -diff -crB ./src/gtest/test_proofs.cpp ../../komodo-jl777/src/gtest/test_proofs.cpp -*** ./src/gtest/test_proofs.cpp 2017-01-03 10:40:50.227329975 +0000 ---- ../../komodo-jl777/src/gtest/test_proofs.cpp 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 336,341 **** ---- 336,364 ---- - auto example = libsnark::generate_r1cs_example_with_field_input(250, 4); - example.constraint_system.swap_AB_if_beneficial(); - auto kp = libsnark::r1cs_ppzksnark_generator(example.constraint_system); -+ auto vkprecomp = libsnark::r1cs_ppzksnark_verifier_process_vk(kp.vk); -+ -+ for (size_t i = 0; i < 20; i++) { -+ auto badproof = ZCProof::random_invalid(); -+ auto proof = badproof.to_libsnark_proof>(); -+ -+ auto verifierEnabled = ProofVerifier::Strict(); -+ auto verifierDisabled = ProofVerifier::Disabled(); -+ // This verifier should catch the bad proof -+ ASSERT_FALSE(verifierEnabled.check( -+ kp.vk, -+ vkprecomp, -+ example.primary_input, -+ proof -+ )); -+ // This verifier won't! -+ ASSERT_TRUE(verifierDisabled.check( -+ kp.vk, -+ vkprecomp, -+ example.primary_input, -+ proof -+ )); -+ } - - for (size_t i = 0; i < 20; i++) { - auto proof = libsnark::r1cs_ppzksnark_prover( -*************** -*** 345,350 **** ---- 368,390 ---- - example.constraint_system - ); - -+ { -+ auto verifierEnabled = ProofVerifier::Strict(); -+ auto verifierDisabled = ProofVerifier::Disabled(); -+ ASSERT_TRUE(verifierEnabled.check( -+ kp.vk, -+ vkprecomp, -+ example.primary_input, -+ proof -+ )); -+ ASSERT_TRUE(verifierDisabled.check( -+ kp.vk, -+ vkprecomp, -+ example.primary_input, -+ proof -+ )); -+ } -+ - ASSERT_TRUE(libsnark::r1cs_ppzksnark_verifier_strong_IC( - kp.vk, - example.primary_input, -diff -crB ./src/gtest/test_random.cpp ../../komodo-jl777/src/gtest/test_random.cpp -*** ./src/gtest/test_random.cpp 2017-01-03 10:40:50.227329975 +0000 ---- ../../komodo-jl777/src/gtest/test_random.cpp 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 24,27 **** ---- 24,35 ---- - std::vector em2 {0, 1, 2, 3, 4}; - EXPECT_EQ(ea2, a2); - EXPECT_EQ(em2, m2); -+ -+ auto a3 = a; -+ auto m3 = m; -+ MappedShuffle(a3.begin(), m3.begin(), a3.size(), GenIdentity); -+ std::vector ea3 {8, 4, 6, 3, 5}; -+ std::vector em3 {0, 1, 2, 3, 4}; -+ EXPECT_EQ(ea3, a3); -+ EXPECT_EQ(em3, m3); - } -diff -crB ./src/init.cpp ../../komodo-jl777/src/init.cpp -*** ./src/init.cpp 2017-01-03 10:40:50.227329975 +0000 ---- ../../komodo-jl777/src/init.cpp 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 62,68 **** - bool fFeeEstimatesInitialized = false; - - #ifdef WIN32 -! // Win32 LevelDB doesn't use filedescriptors, and the ones used for - // accessing block files don't count towards the fd_set size limit - // anyway. - #define MIN_CORE_FILEDESCRIPTORS 0 ---- 62,68 ---- - bool fFeeEstimatesInitialized = false; - - #ifdef WIN32 -! // Win32 LevelDB doesn't use file descriptors, and the ones used for - // accessing block files don't count towards the fd_set size limit - // anyway. - #define MIN_CORE_FILEDESCRIPTORS 0 -*************** -*** 348,354 **** - strUsage += HelpMessageOpt("-mintxfee=", strprintf("Fees (in BTC/Kb) smaller than this are considered zero fee for transaction creation (default: %s)", - FormatMoney(CWallet::minTxFee.GetFeePerK()))); - strUsage += HelpMessageOpt("-paytxfee=", strprintf(_("Fee (in BTC/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK()))); -! strUsage += HelpMessageOpt("-rescan", _("Rescan the block chain for missing wallet transactions") + " " + _("on startup")); - strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup")); - strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), 0)); - strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), 1)); ---- 348,354 ---- - strUsage += HelpMessageOpt("-mintxfee=", strprintf("Fees (in BTC/Kb) smaller than this are considered zero fee for transaction creation (default: %s)", - FormatMoney(CWallet::minTxFee.GetFeePerK()))); - strUsage += HelpMessageOpt("-paytxfee=", strprintf(_("Fee (in BTC/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK()))); -! strUsage += HelpMessageOpt("-rescan", _("Rescan the blockchain for missing wallet transactions") + " " + _("on startup")); - strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup")); - strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), 0)); - strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), 1)); -*************** -*** 380,386 **** - if (mode == HMM_BITCOIN_QT) - debugCategories += ", qt"; - strUsage += HelpMessageOpt("-debug=", strprintf(_("Output debugging information (default: %u, supplying is optional)"), 0) + ". " + -! _("If is not supplied, output all debugging information.") + _(" can be:") + " " + debugCategories + "."); - #ifdef ENABLE_WALLET - strUsage += HelpMessageOpt("-gen", strprintf(_("Generate coins (default: %u)"), 0)); - strUsage += HelpMessageOpt("-genproclimit=", strprintf(_("Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)"), 1)); ---- 380,386 ---- - if (mode == HMM_BITCOIN_QT) - debugCategories += ", qt"; - strUsage += HelpMessageOpt("-debug=", strprintf(_("Output debugging information (default: %u, supplying is optional)"), 0) + ". " + -! _("If is not supplied or if = 1, output all debugging information.") + _(" can be:") + " " + debugCategories + "."); - #ifdef ENABLE_WALLET - strUsage += HelpMessageOpt("-gen", strprintf(_("Generate coins (default: %u)"), 0)); - strUsage += HelpMessageOpt("-genproclimit=", strprintf(_("Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)"), 1)); -*************** -*** 425,431 **** - strUsage += HelpMessageOpt("-rpcport=", strprintf(_("Listen for JSON-RPC connections on (default: %u or testnet: %u)"), 8232, 18232)); - strUsage += HelpMessageOpt("-rpcallowip=", _("Allow JSON-RPC connections from specified source. Valid for are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times")); - strUsage += HelpMessageOpt("-rpcthreads=", strprintf(_("Set the number of threads to service RPC calls (default: %d)"), 4)); -! strUsage += HelpMessageOpt("-rpckeepalive", strprintf(_("RPC support for HTTP persistent connections (default: %d)"), 1)); - - // Disabled until we can lock notes and also tune performance of libsnark which by default uses multiple threads - //strUsage += HelpMessageOpt("-rpcasyncthreads=", strprintf(_("Set the number of threads to service Async RPC calls (default: %d)"), 1)); ---- 425,434 ---- - strUsage += HelpMessageOpt("-rpcport=", strprintf(_("Listen for JSON-RPC connections on (default: %u or testnet: %u)"), 8232, 18232)); - strUsage += HelpMessageOpt("-rpcallowip=", _("Allow JSON-RPC connections from specified source. Valid for are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times")); - strUsage += HelpMessageOpt("-rpcthreads=", strprintf(_("Set the number of threads to service RPC calls (default: %d)"), 4)); -! -! // TODO #1856: Re-enable support for persistent connections. -! // Disabled to avoid rpc deadlock #1680, until we backport upstream changes which replace boost::asio with libevent, or another solution is implemented. -! //strUsage += HelpMessageOpt("-rpckeepalive", strprintf(_("RPC support for HTTP persistent connections (default: %d)"), 1)); - - // Disabled until we can lock notes and also tune performance of libsnark which by default uses multiple threads - //strUsage += HelpMessageOpt("-rpcasyncthreads=", strprintf(_("Set the number of threads to service Async RPC calls (default: %d)"), 1)); -*************** -*** 447,452 **** ---- 450,460 ---- - strUsage += HelpMessageOpt("-min", _("Start minimized")); - strUsage += HelpMessageOpt("-rootcertificates=", _("Set SSL root certificates for payment request (default: -system-)")); - strUsage += HelpMessageOpt("-splash", _("Show splash screen on startup (default: 1)")); -+ } else if (mode == HMM_BITCOIND) { -+ strUsage += HelpMessageGroup(_("Metrics Options (only if -daemon and -printtoconsole are not set):")); -+ strUsage += HelpMessageOpt("-showmetrics", _("Show metrics on stdout (default: 1 if running in a console, 0 otherwise)")); -+ strUsage += HelpMessageOpt("-metricsui", _("Set to 1 for a persistent metrics screen, 0 for sequential metrics output (default: 1 if running in a console, 0 otherwise)")); -+ strUsage += HelpMessageOpt("-metricsrefreshtime", strprintf(_("Number of seconds between metrics refreshes (default: %u if running in a console, %u otherwise)"), 1, 600)); - } - - return strUsage; -*************** -*** 538,548 **** - RenameThread("zcash-loadblk"); - // -reindex - if (fReindex) { -- #ifdef ENABLE_WALLET -- if (pwalletMain) { -- pwalletMain->ClearNoteWitnessCache(); -- } -- #endif - CImportingNow imp; - int nFile = 0; - while (true) { ---- 546,551 ---- -*************** -*** 980,1000 **** - CScheduler::Function serviceLoop = boost::bind(&CScheduler::serviceQueue, &scheduler); - threadGroup.create_thread(boost::bind(&TraceThread, "scheduler", serviceLoop)); - - if ((chainparams.NetworkIDString() != "regtest") && -! GetBoolArg("-showmetrics", false) && - !fPrintToConsole && !GetBoolArg("-daemon", false)) { - // Start the persistent metrics interface - ConnectMetricsScreen(); - threadGroup.create_thread(&ThreadShowMetricsScreen); - } - -- // Initialize Zcash circuit parameters -- ZC_LoadParams(); - // These must be disabled for now, they are buggy and we probably don't - // want any of libsnark's profiling in production anyway. - libsnark::inhibit_profiling_info = true; - libsnark::inhibit_profiling_counters = true; - - /* Start the RPC server already. It will be started in "warmup" mode - * and not really process calls already (but it will signify connections - * that the server is there and will be ready later). Warmup mode will ---- 983,1007 ---- - CScheduler::Function serviceLoop = boost::bind(&CScheduler::serviceQueue, &scheduler); - threadGroup.create_thread(boost::bind(&TraceThread, "scheduler", serviceLoop)); - -+ // Count uptime -+ MarkStartTime(); -+ - if ((chainparams.NetworkIDString() != "regtest") && -! GetBoolArg("-showmetrics", 0) && - !fPrintToConsole && !GetBoolArg("-daemon", false)) { - // Start the persistent metrics interface - ConnectMetricsScreen(); - threadGroup.create_thread(&ThreadShowMetricsScreen); - } - - // These must be disabled for now, they are buggy and we probably don't - // want any of libsnark's profiling in production anyway. - libsnark::inhibit_profiling_info = true; - libsnark::inhibit_profiling_counters = true; - -+ // Initialize Zcash circuit parameters -+ ZC_LoadParams(); -+ - /* Start the RPC server already. It will be started in "warmup" mode - * and not really process calls already (but it will signify connections - * that the server is there and will be ready later). Warmup mode will -*************** -*** 1379,1385 **** ---- 1386,1395 ---- - - CBlockIndex *pindexRescan = chainActive.Tip(); - if (GetBoolArg("-rescan", false)) -+ { -+ pwalletMain->ClearNoteWitnessCache(); - pindexRescan = chainActive.Genesis(); -+ } - else - { - CWalletDB walletdb(strWalletFile); -diff -crB ./src/komodo_gateway.h ../../komodo-jl777/src/komodo_gateway.h -*** ./src/komodo_gateway.h 2017-01-03 10:40:50.231330177 +0000 ---- ../../komodo-jl777/src/komodo_gateway.h 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 87,95 **** ---- 87,105 ---- - return(pax); - } - -+ void komodo_paxdelete(struct pax_transaction *pax) -+ { -+ return; // breaks when out of order -+ pthread_mutex_lock(&komodo_mutex); -+ HASH_DELETE(hh,PAX,pax); -+ pthread_mutex_unlock(&komodo_mutex); -+ } -+ - void komodo_gateway_deposit(char *coinaddr,uint64_t value,char *symbol,uint64_t fiatoshis,uint8_t *rmd160,uint256 txid,uint16_t vout,uint8_t type,int32_t height,int32_t otherheight,char *source,int32_t approved) // assetchain context - { - struct pax_transaction *pax; uint8_t buf[35]; int32_t addflag = 0; struct komodo_state *sp; char str[16],dest[16],*s; -+ if ( KOMODO_PAX == 0 ) -+ return; - sp = komodo_stateptr(str,dest); - pthread_mutex_lock(&komodo_mutex); - pax_keyset(buf,txid,vout,type); -*************** -*** 178,190 **** - int32_t komodo_issued_opreturn(char *base,uint256 *txids,uint16_t *vouts,int64_t *values,int64_t *srcvalues,int32_t *kmdheights,int32_t *otherheights,int8_t *baseids,uint8_t *rmd160s,uint8_t *opretbuf,int32_t opretlen,int32_t iskomodo) - { - struct pax_transaction p,*pax; int32_t i,n=0,j,len=0,incr,height,otherheight; uint8_t type,rmd160[20]; uint64_t fiatoshis; char symbol[16]; -! incr = 34 + (iskomodo * (2*sizeof(fiatoshis) + 2*sizeof(height) + 20 + 4)); -! for (i=0; i<4; i++) -! base[i] = opretbuf[opretlen-4+i]; - //for (i=0; itype == 'A' || pax->type == 'D' || pax->type == 'X' ) - str = pax->symbol; - else str = pax->source; - basesp = komodo_stateptrget(str); -! if ( basesp != 0 && pax->didstats == 0 && pax->type == 'I' ) - { -! if ( (pax2= komodo_paxfind(pax->txid,pax->vout,'D')) != 0 ) - { - if ( pax2->fiatoshis != 0 ) - { ---- 251,300 ---- - return(n); - } - -+ int32_t komodo_paxcmp(char *symbol,int32_t kmdheight,uint64_t value,uint64_t checkvalue,uint64_t seed) -+ { -+ int32_t ratio; -+ if ( seed == 0 && checkvalue != 0 ) -+ { -+ ratio = ((value << 6) / checkvalue); -+ if ( ratio >= 63 && ratio <= 65 ) -+ return(0); -+ else -+ { -+ if ( kmdheight >= 86150 ) -+ printf("ht.%d ignore mismatched %s value %lld vs checkvalue %lld -> ratio.%d\n",kmdheight,symbol,(long long)value,(long long)checkvalue,ratio); -+ return(-1); -+ } -+ } -+ else if ( checkvalue != 0 ) -+ { -+ ratio = ((value << 10) / checkvalue); -+ if ( ratio >= 1023 && ratio <= 1025 ) -+ return(0); -+ } -+ return(value != checkvalue); -+ } -+ - uint64_t komodo_paxtotal() - { - struct pax_transaction *pax,*pax2,*tmp,*tmp2; char symbol[16],dest[16],*str; int32_t i,ht; int64_t checktoshis; uint64_t seed,total = 0; struct komodo_state *basesp; -+ if ( KOMODO_PAX == 0 ) -+ return(0); - if ( komodo_isrealtime(&ht) == 0 ) - return(0); - else - { - HASH_ITER(hh,PAX,pax,tmp) - { -+ if ( pax->marked != 0 ) -+ continue; - if ( pax->type == 'A' || pax->type == 'D' || pax->type == 'X' ) - str = pax->symbol; - else str = pax->source; - basesp = komodo_stateptrget(str); -! if ( basesp != 0 && pax->didstats == 0 ) - { -! if ( pax->type == 'I' && (pax2= komodo_paxfind(pax->txid,pax->vout,'D')) != 0 ) - { - if ( pax2->fiatoshis != 0 ) - { -*************** -*** 267,305 **** - pax->marked = pax->height; - } - } - } - } - } - komodo_stateptr(symbol,dest); - HASH_ITER(hh,PAX,pax,tmp) - { -! //printf("pax.%s marked.%d %.8f -> %.8f\n",pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis)); -! if ( strcmp(symbol,pax->symbol) == 0 ) - { - if ( pax->marked == 0 ) - { - if ( komodo_is_issuer() != 0 ) -! total += pax->fiatoshis; -! else if ( pax->approved != 0 ) - { - if ( pax->validated != 0 ) - total += pax->komodoshis; - else - { - seed = 0; - checktoshis = komodo_paxprice(&seed,pax->height,pax->source,(char *)"KMD",(uint64_t)pax->fiatoshis); - //printf("PAX_fiatdest ht.%d price %s %.8f -> KMD %.8f vs %.8f\n",pax->height,pax->symbol,(double)pax->fiatoshis/COIN,(double)pax->komodoshis/COIN,(double)checktoshis/COIN); - //printf(" v%d %.8f k.%d ht.%d\n",pax->vout,dstr(pax->komodoshis),pax->height,pax->otherheight); -! if ( seed != 0 ) - { -! if ( checktoshis >= pax->komodoshis ) - { - total += pax->komodoshis; - pax->validated = pax->komodoshis; - } else pax->marked = pax->height; - } - } - } - } - } - } ---- 308,382 ---- - pax->marked = pax->height; - } - } -+ else if ( pax->type == 'W' ) -+ { -+ //bitcoin_address(coinaddr,addrtype,rmd160,20); -+ if ( (checktoshis= komodo_paxprice(&seed,pax->height,pax->source,(char *)"KMD",(uint64_t)pax->fiatoshis)) != 0 ) -+ { -+ if ( komodo_paxcmp(pax->source,pax->height,pax->komodoshis,checktoshis,seed) != 0 ) -+ { -+ pax->marked = pax->height; -+ //printf("WITHDRAW.%s mark <- %d %.8f != %.8f\n",pax->source,pax->height,dstr(checktoshis),dstr(pax->komodoshis)); -+ } -+ else if ( pax->validated == 0 ) -+ { -+ pax->validated = pax->komodoshis = checktoshis; -+ //int32_t j; for (j=0; j<32; j++) -+ // printf("%02x",((uint8_t *)&pax->txid)[j]); -+ //if ( strcmp(str,ASSETCHAINS_SYMBOL) == 0 ) -+ // printf(" v%d %p got WITHDRAW.%s kmd.%d ht.%d %.8f -> %.8f/%.8f\n",pax->vout,pax,pax->source,pax->height,pax->otherheight,dstr(pax->fiatoshis),dstr(pax->komodoshis),dstr(checktoshis)); -+ } -+ } -+ } - } - } - } - komodo_stateptr(symbol,dest); - HASH_ITER(hh,PAX,pax,tmp) - { -! pax->ready = 0; -! if ( 0 && pax->type == 'A' ) -! printf("%p pax.%s <- %s marked.%d %.8f -> %.8f validated.%d approved.%d\n",pax,pax->symbol,pax->source,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->validated != 0,pax->approved != 0); -! if ( pax->marked != 0 ) -! continue; -! if ( strcmp(symbol,pax->symbol) == 0 || pax->type == 'A' ) - { - if ( pax->marked == 0 ) - { - if ( komodo_is_issuer() != 0 ) -! { -! if ( pax->validated != 0 && pax->type == 'D' ) -! { -! total += pax->fiatoshis; -! pax->ready = 1; -! } -! } -! else if ( pax->approved != 0 && pax->type == 'A' ) - { - if ( pax->validated != 0 ) -+ { - total += pax->komodoshis; -+ pax->ready = 1; -+ } - else - { - seed = 0; - checktoshis = komodo_paxprice(&seed,pax->height,pax->source,(char *)"KMD",(uint64_t)pax->fiatoshis); - //printf("PAX_fiatdest ht.%d price %s %.8f -> KMD %.8f vs %.8f\n",pax->height,pax->symbol,(double)pax->fiatoshis/COIN,(double)pax->komodoshis/COIN,(double)checktoshis/COIN); - //printf(" v%d %.8f k.%d ht.%d\n",pax->vout,dstr(pax->komodoshis),pax->height,pax->otherheight); -! if ( seed != 0 && checktoshis != 0 ) - { -! if ( checktoshis == pax->komodoshis ) - { - total += pax->komodoshis; - pax->validated = pax->komodoshis; -+ pax->ready = 1; - } else pax->marked = pax->height; - } - } - } -+ if ( 0 && pax->ready != 0 ) -+ printf("%p (%c) pax.%s marked.%d %.8f -> %.8f validated.%d approved.%d\n",pax,pax->type,pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->validated != 0,pax->approved != 0); - } - } - } -*************** -*** 307,373 **** - return(total); - } - -! int32_t komodo_pending_withdraws(char *opretstr) - { -! struct pax_transaction *pax,*tmp; uint8_t opretbuf[16384]; int32_t ht,len=0; uint64_t total = 0; - if ( komodo_isrealtime(&ht) == 0 || ASSETCHAINS_SYMBOL[0] != 0 ) - return(0); - HASH_ITER(hh,PAX,pax,tmp) - { -! //printf("pax %s marked.%u approved.%u\n",pax->symbol,pax->marked,pax->approved); -! if ( pax->marked == 0 && strcmp((char *)"KMD",pax->symbol) == 0 && pax->approved == 0 ) - { -! // add 'A' opreturn entry -! if ( len == 0 ) -! opretbuf[len++] = 'A'; -! len += komodo_rwapproval(1,&opretbuf[len],pax); -! //printf("%s.(marked.%u approved.%d) %p\n",pax->source,pax->marked,pax->approved,pax); - } - } -! if ( len > 0 ) -! init_hexbytes_noT(opretstr,opretbuf,len); -! else opretstr[0] = 0; -! fprintf(stderr,"komodo_pending_withdraws len.%d PAXTOTAL %.8f\n",len,dstr(komodo_paxtotal())); - return(len); - } - - int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *base,int32_t tokomodo) - { - struct pax_transaction *pax,*tmp; char symbol[16],dest[16]; uint8_t *script,opcode,opret[16384],data[16384]; int32_t i,baseid,ht,len=0,opretlen=0,numvouts=1; struct komodo_state *sp; uint64_t available,deposited,issued,withdrawn,approved,redeemed,mask; - sp = komodo_stateptr(symbol,dest); - strcpy(symbol,base); - PENDING_KOMODO_TX = 0; - if ( tokomodo == 0 ) - { - opcode = 'I'; - if ( komodo_isrealtime(&ht) == 0 ) - return(0); -! } else opcode = 'X'; - HASH_ITER(hh,PAX,pax,tmp) - { -- //printf("pax.%s marked.%d %.8f -> %.8f\n",pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis)); -- if ( strcmp(symbol,"KMD") == 0 && pax->approved == 0 ) -- continue; -- //else if ( strcmp(symbol,"KMD") != 0 ) - { - #ifdef KOMODO_ASSETCHAINS_WAITNOTARIZE -! struct komodo_state *kmdsp = komodo_stateptrget((char *)"KMD"); -! if ( kmdsp != 0 && kmdsp->NOTARIZED_HEIGHT >= pax->height ) // assumes same chain as notarize - pax->validated = pax->komodoshis; //kmdsp->NOTARIZED_HEIGHT; - #endif - } -! if ( pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,symbol) != 0 || available < pax->fiatoshis ) - { -! printf("miner: skip %s %.8f when avail %.8f\n",symbol,dstr(pax->fiatoshis),dstr(available)); - continue; - } -! if ( pax->marked != 0 ) - continue; -! if ( strcmp(pax->symbol,symbol) != 0 || pax->validated == 0 ) - { - //printf("pax->symbol.%s != %s or null pax->validated %.8f\n",pax->symbol,symbol,dstr(pax->validated)); - continue; - } - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - printf("pax.%s marked.%d %.8f -> %.8f\n",ASSETCHAINS_SYMBOL,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis)); - txNew->vout.resize(numvouts+1); ---- 384,518 ---- - return(total); - } - -! static int _paxorder(const void *a,const void *b) - { -! #define pax_a (*(struct pax_transaction **)a) -! #define pax_b (*(struct pax_transaction **)b) -! uint64_t aval,bval; -! aval = pax_a->fiatoshis + pax_a->komodoshis + pax_a->height; -! bval = pax_b->fiatoshis + pax_b->komodoshis + pax_b->height; -! if ( bval > aval ) -! return(-1); -! else if ( bval < aval ) -! return(1); -! return(0); -! #undef pax_a -! #undef pax_b -! } -! -! int32_t komodo_pending_withdraws(char *opretstr) // todo: enforce deterministic order -! { -! struct pax_transaction *pax,*pax2,*tmp,*paxes[64]; uint8_t opretbuf[16384]; int32_t i,n,ht,len=0; uint64_t total = 0; -! if ( KOMODO_PAX == 0 ) -! return(0); - if ( komodo_isrealtime(&ht) == 0 || ASSETCHAINS_SYMBOL[0] != 0 ) - return(0); -+ n = 0; - HASH_ITER(hh,PAX,pax,tmp) - { -! if ( pax->type == 'W' ) - { -! if ( (pax2= komodo_paxfind(pax->txid,pax->vout,'A')) != 0 ) -! { -! if ( pax2->approved != 0 ) -! pax->approved = pax2->approved; -! } -! else if ( (pax2= komodo_paxfind(pax->txid,pax->vout,'X')) != 0 ) -! pax->approved = pax->height; -! //printf("pax %s marked.%u approved.%u validated.%llu\n",pax->symbol,pax->marked,pax->approved,(long long)pax->validated); -! if ( pax->marked == 0 && strcmp((char *)"KMD",pax->symbol) == 0 && pax->approved == 0 && pax->validated != 0 ) -! { -! if ( n < sizeof(paxes)/sizeof(*paxes) ) -! { -! paxes[n++] = pax; -! //int32_t j; for (j=0; j<32; j++) -! // printf("%02x",((uint8_t *)&pax->txid)[j]); -! //printf(" %s.(kmdht.%d ht.%d marked.%u approved.%d validated %.8f) %.8f\n",pax->source,pax->height,pax->otherheight,pax->marked,pax->approved,dstr(pax->validated),dstr(pax->komodoshis)); -! } -! } - } - } -! opretstr[0] = 0; -! if ( n > 0 ) -! { -! opretbuf[len++] = 'A'; -! qsort(paxes,n,sizeof(*paxes),_paxorder); -! for (i=0; i>3)*7 ) -! len += komodo_rwapproval(1,&opretbuf[len],paxes[i]); -! } -! if ( len > 0 ) -! init_hexbytes_noT(opretstr,opretbuf,len); -! } -! //fprintf(stderr,"komodo_pending_withdraws len.%d PAXTOTAL %.8f\n",len,dstr(komodo_paxtotal())); - return(len); - } - - int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *base,int32_t tokomodo) - { - struct pax_transaction *pax,*tmp; char symbol[16],dest[16]; uint8_t *script,opcode,opret[16384],data[16384]; int32_t i,baseid,ht,len=0,opretlen=0,numvouts=1; struct komodo_state *sp; uint64_t available,deposited,issued,withdrawn,approved,redeemed,mask; -+ if ( KOMODO_PAX == 0 ) -+ return(0); -+ struct komodo_state *kmdsp = komodo_stateptrget((char *)"KMD"); - sp = komodo_stateptr(symbol,dest); - strcpy(symbol,base); -+ if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) < 0 ) -+ return(0); - PENDING_KOMODO_TX = 0; - if ( tokomodo == 0 ) - { - opcode = 'I'; - if ( komodo_isrealtime(&ht) == 0 ) - return(0); -! } -! else -! { -! opcode = 'X'; -! if ( komodo_paxtotal() == 0 ) -! return(0); -! } - HASH_ITER(hh,PAX,pax,tmp) - { - { - #ifdef KOMODO_ASSETCHAINS_WAITNOTARIZE -! if ( kmdsp != 0 && (kmdsp->NOTARIZED_HEIGHT >= pax->height || kmdsp->CURRENT_HEIGHT > pax->height+30) ) // assumes same chain as notarize - pax->validated = pax->komodoshis; //kmdsp->NOTARIZED_HEIGHT; -+ else pax->validated = pax->ready = 0; - #endif - } -! if ( ASSETCHAINS_SYMBOL[0] != 0 && (pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,symbol) != 0 || available < pax->fiatoshis) ) - { -! if ( strcmp(ASSETCHAINS_SYMBOL,symbol) == 0 ) -! printf("miner.[%s]: skip %s %.8f when avail %.8f\n",ASSETCHAINS_SYMBOL,symbol,dstr(pax->fiatoshis),dstr(available)); - continue; - } -! /*printf("pax.%s marked.%d %.8f -> %.8f ready.%d validated.%d\n",pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->ready!=0,pax->validated!=0); -! if ( pax->marked != 0 || (pax->type != 'D' && pax->type != 'A') || pax->ready == 0 ) -! { -! printf("reject 2\n"); - continue; -! }*/ -! if ( ASSETCHAINS_SYMBOL[0] != 0 && (strcmp(pax->symbol,symbol) != 0 || pax->validated == 0) ) - { - //printf("pax->symbol.%s != %s or null pax->validated %.8f\n",pax->symbol,symbol,dstr(pax->validated)); - continue; - } -+ if ( pax->ready == 0 ) -+ continue; -+ if ( pax->type == 'A' && ASSETCHAINS_SYMBOL[0] == 0 ) -+ { -+ if ( kmdsp != 0 ) -+ { -+ if ( (baseid= komodo_baseid(pax->symbol)) < 0 || ((1LL << baseid) & sp->RTmask) == 0 ) -+ { -+ printf("not RT for (%s) %llx baseid.%d %llx\n",pax->symbol,(long long)sp->RTmask,baseid,(long long)(1LL< %.8f ready.%d validated.%d approved.%d\n",tokomodo,pax->type,pax,pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->ready!=0,pax->validated!=0,pax->approved!=0); - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - printf("pax.%s marked.%d %.8f -> %.8f\n",ASSETCHAINS_SYMBOL,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis)); - txNew->vout.resize(numvouts+1); -*************** -*** 392,398 **** - { - len += komodo_rwapproval(1,&data[len],pax); - PENDING_KOMODO_TX += pax->komodoshis; -! //printf(" vout.%u DEPOSIT %.8f <- pax.%s pending %.8f | ",pax->vout,(double)txNew->vout[numvouts].nValue/COIN,symbol,dstr(PENDING_KOMODO_TX)); - } - if ( numvouts++ >= 64 ) - break; ---- 537,543 ---- - { - len += komodo_rwapproval(1,&data[len],pax); - PENDING_KOMODO_TX += pax->komodoshis; -! printf(" vout.%u DEPOSIT %.8f <- pax.%s pending %.8f | ",pax->vout,(double)txNew->vout[numvouts].nValue/COIN,symbol,dstr(PENDING_KOMODO_TX)); - } - if ( numvouts++ >= 64 ) - break; -*************** -*** 419,424 **** ---- 564,571 ---- - int32_t komodo_check_deposit(int32_t height,const CBlock& block) // verify above block is valid pax pricing - { - int32_t i,j,n,num,opretlen,offset=1,errs=0,matched=0,kmdheights[64],otherheights[64]; uint256 hash,txids[64]; char symbol[16],base[16]; uint16_t vouts[64]; int8_t baseids[64]; uint8_t *script,opcode,rmd160s[64*20]; uint64_t available,deposited,issued,withdrawn,approved,redeemed; int64_t values[64],srcvalues[64]; struct pax_transaction *pax; -+ if ( KOMODO_PAX == 0 ) -+ return(0); - memset(baseids,0xff,sizeof(baseids)); - memset(values,0,sizeof(values)); - memset(srcvalues,0,sizeof(srcvalues)); -*************** -*** 442,447 **** ---- 589,603 ---- - { - strcpy(symbol,ASSETCHAINS_SYMBOL); - opcode = 'I'; -+ if ( komodo_baseid(symbol) < 0 ) -+ { -+ if ( block.vtx[0].vout.size() != 1 ) -+ { -+ printf("%s has more than one coinbase?\n",symbol); -+ return(-1); -+ } -+ return(0); -+ } - } - if ( script[offset] == opcode && opretlen < block.vtx[0].vout[n-1].scriptPubKey.size() ) - { -*************** -*** 449,455 **** - { - for (i=1; itype = opcode; - if ( opcode == 'I' && pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,symbol) != 0 || available < pax->fiatoshis ) ---- 605,611 ---- - { - for (i=1; itype = opcode; - if ( opcode == 'I' && pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,symbol) != 0 || available < pax->fiatoshis ) -*************** -*** 461,476 **** - { - if ( pax->marked != 0 && height >= 80820 ) - { -! printf("%c errs.%d i.%d match %.8f vs %.8f pax.%p\n",opcode,errs,i,dstr(opcode == 'I' ? pax->fiatoshis : pax->komodoshis),dstr(block.vtx[0].vout[i].nValue),pax); - errs++; -! } else matched++; - } - else - { - for (j=0; j<32; j++) - printf("%02x",((uint8_t *)&txids[i-1])[j]); - printf(" cant paxfind %c txid\n",opcode); -! printf("%c errs.%d i.%d match %.8f vs %.8f pax.%p\n",opcode,errs,i,dstr(opcode == 'I' ? pax->fiatoshis : pax->komodoshis),dstr(block.vtx[0].vout[i].nValue),pax); - } - } - else ---- 617,638 ---- - { - if ( pax->marked != 0 && height >= 80820 ) - { -! printf(">>>>>>>>>>> %c errs.%d i.%d match %.8f vs %.8f pax.%p\n",opcode,errs,i,dstr(opcode == 'I' ? pax->fiatoshis : pax->komodoshis),dstr(block.vtx[0].vout[i].nValue),pax); - errs++; -! } -! else -! { -! if ( opcode == 'X' ) -! printf("check deposit validates %s %.8f -> %.8f\n",CURRENCIES[baseids[i]],dstr(srcvalues[i]),dstr(values[i])); -! matched++; -! } - } - else - { - for (j=0; j<32; j++) - printf("%02x",((uint8_t *)&txids[i-1])[j]); - printf(" cant paxfind %c txid\n",opcode); -! printf(">>>>>>>>>>> %c errs.%d i.%d match %.8f vs %.8f pax.%p\n",opcode,errs,i,dstr(opcode == 'I' ? pax->fiatoshis : pax->komodoshis),dstr(block.vtx[0].vout[i].nValue),pax); - } - } - else -*************** -*** 478,491 **** - hash = block.GetHash(); - for (j=0; j<32; j++) - printf("%02x",((uint8_t *)&hash)[j]); -! printf(" ht.%d blockhash X couldnt find vout.[%d]\n",height,i); - } - } -! if ( matched != num ) - { - printf("WOULD REJECT %s: ht.%d (%c) matched.%d vs num.%d\n",symbol,height,opcode,matched,num); - // can easily happen depending on order of loading -! if ( height > 100000 ) //&& opcode == 'X' ) - { - printf("REJECT: ht.%d (%c) matched.%d vs num.%d\n",height,opcode,matched,num); - return(-1); ---- 640,653 ---- - hash = block.GetHash(); - for (j=0; j<32; j++) - printf("%02x",((uint8_t *)&hash)[j]); -! printf(" kht.%d ht.%d %.8f %.8f blockhash couldnt find vout.[%d]\n",kmdheights[i-1],otherheights[i-1],dstr(values[i-1]),dstr(srcvalues[i]),i); - } - } -! if ( height <= chainActive.Tip()->nHeight && matched != num ) - { - printf("WOULD REJECT %s: ht.%d (%c) matched.%d vs num.%d\n",symbol,height,opcode,matched,num); - // can easily happen depending on order of loading -! if ( height > 200000 ) - { - printf("REJECT: ht.%d (%c) matched.%d vs num.%d\n",height,opcode,matched,num); - return(-1); -*************** -*** 497,530 **** - return(0); - } - -- int32_t komodo_paxcmp(char *symbol,int32_t kmdheight,uint64_t value,uint64_t checkvalue,uint64_t seed) -- { -- int32_t ratio; -- if ( seed == 0 && checkvalue != 0 ) -- { -- ratio = ((value << 6) / checkvalue); -- if ( ratio >= 63 && ratio <= 65 ) -- return(0); -- else -- { -- if ( kmdheight >= 86150 ) -- printf("ht.%d ignore mismatched %s value %lld vs checkvalue %lld -> ratio.%d\n",kmdheight,symbol,(long long)value,(long long)checkvalue,ratio); -- return(-1); -- } -- } -- else if ( checkvalue != 0 ) -- { -- ratio = ((value << 10) / checkvalue); -- if ( ratio >= 1023 && ratio <= 1025 ) -- return(0); -- } -- return(value != checkvalue); -- } -- - const char *komodo_opreturn(int32_t height,uint64_t value,uint8_t *opretbuf,int32_t opretlen,uint256 txid,uint16_t vout,char *source) - { - uint8_t rmd160[20],rmd160s[64*20],addrtype,shortflag,pubkey33[33]; int32_t didstats,i,j,n,len,tokomodo,kmdheight,otherheights[64],kmdheights[64]; int8_t baseids[64]; char base[4],coinaddr[64],destaddr[64]; uint256 txids[64]; uint16_t vouts[64]; uint64_t convtoshis,seed; int64_t fiatoshis,komodoshis,checktoshis,values[64],srcvalues[64]; struct pax_transaction *pax,*pax2; struct komodo_state *basesp; double diff; - const char *typestr = "unknown"; - memset(baseids,0xff,sizeof(baseids)); - memset(values,0,sizeof(values)); - memset(srcvalues,0,sizeof(srcvalues)); ---- 659,675 ---- - return(0); - } - - const char *komodo_opreturn(int32_t height,uint64_t value,uint8_t *opretbuf,int32_t opretlen,uint256 txid,uint16_t vout,char *source) - { - uint8_t rmd160[20],rmd160s[64*20],addrtype,shortflag,pubkey33[33]; int32_t didstats,i,j,n,len,tokomodo,kmdheight,otherheights[64],kmdheights[64]; int8_t baseids[64]; char base[4],coinaddr[64],destaddr[64]; uint256 txids[64]; uint16_t vouts[64]; uint64_t convtoshis,seed; int64_t fiatoshis,komodoshis,checktoshis,values[64],srcvalues[64]; struct pax_transaction *pax,*pax2; struct komodo_state *basesp; double diff; - const char *typestr = "unknown"; -+ if ( KOMODO_PAX == 0 ) -+ return("nopax"); -+ if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) < 0 ) -+ { -+ //printf("komodo_opreturn skip %s\n",ASSETCHAINS_SYMBOL); -+ return("assetchain"); -+ } - memset(baseids,0xff,sizeof(baseids)); - memset(values,0,sizeof(values)); - memset(srcvalues,0,sizeof(srcvalues)); -*************** -*** 546,552 **** - if ( kmdheight <= height ) - { - didstats = 0; -! if ( strcmp(base,ASSETCHAINS_SYMBOL) == 0 ) - { - printf("(%s) (%s) kmdheight.%d vs height.%d check %.8f vs %.8f tokomodo.%d %d seed.%llx\n",ASSETCHAINS_SYMBOL,base,kmdheight,height,dstr(checktoshis),dstr(value),komodo_is_issuer(),strncmp(ASSETCHAINS_SYMBOL,base,strlen(base)) == 0,(long long)seed); - for (i=0; i<32; i++) ---- 691,697 ---- - if ( kmdheight <= height ) - { - didstats = 0; -! if ( 0 && strcmp(base,ASSETCHAINS_SYMBOL) == 0 ) - { - printf("(%s) (%s) kmdheight.%d vs height.%d check %.8f vs %.8f tokomodo.%d %d seed.%llx\n",ASSETCHAINS_SYMBOL,base,kmdheight,height,dstr(checktoshis),dstr(value),komodo_is_issuer(),strncmp(ASSETCHAINS_SYMBOL,base,strlen(base)) == 0,(long long)seed); - for (i=0; i<32; i++) -*************** -*** 592,598 **** - pax2->fiatoshis = pax->fiatoshis; - pax2->komodoshis = pax->komodoshis; - pax->marked = pax2->marked = pax->height; -! pax->otherheight = height; - if ( pax2->didstats == 0 ) - { - if ( (basesp= komodo_stateptrget(base)) != 0 ) ---- 737,743 ---- - pax2->fiatoshis = pax->fiatoshis; - pax2->komodoshis = pax->komodoshis; - pax->marked = pax2->marked = pax->height; -! pax2->height = pax->height = height; - if ( pax2->didstats == 0 ) - { - if ( (basesp= komodo_stateptrget(base)) != 0 ) -*************** -*** 632,638 **** - { - pax->type = opretbuf[0]; - strcpy(pax->source,(char *)&opretbuf[opretlen-4]); -! if ( (pax2= komodo_paxfind(txids[i],vouts[i],'D')) != 0 ) - { - // realtime path? - pax->fiatoshis = pax2->fiatoshis; ---- 777,783 ---- - { - pax->type = opretbuf[0]; - strcpy(pax->source,(char *)&opretbuf[opretlen-4]); -! if ( (pax2= komodo_paxfind(txids[i],vouts[i],'D')) != 0 && pax2->fiatoshis != 0 && pax2->komodoshis != 0 ) - { - // realtime path? - pax->fiatoshis = pax2->fiatoshis; -*************** -*** 651,665 **** - } - } - } -- komodo_paxmark(pax->height,txids[i],vouts[i],'D',height); - } - } - } else printf("opreturn none issued?\n"); - } -- if ( strcmp(source,ASSETCHAINS_SYMBOL) == 0 ) -- printf("source.%s opreturn[I] matches %s\n",source,(char *)&opretbuf[opretlen-4]); - } -! else if ( opretbuf[0] == 'W' && opretlen >= 38 ) - { - tokomodo = 1; - iguana_rwnum(0,&opretbuf[34],sizeof(kmdheight),&kmdheight); ---- 796,811 ---- - } - } - } - } -+ if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'I',height)) != 0 ) -+ komodo_paxdelete(pax); -+ if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'D',height)) != 0 ) -+ komodo_paxdelete(pax); - } - } else printf("opreturn none issued?\n"); - } - } -! else if ( opretbuf[0] == 'W' )//&& opretlen >= 38 ) - { - tokomodo = 1; - iguana_rwnum(0,&opretbuf[34],sizeof(kmdheight),&kmdheight); -*************** -*** 668,676 **** - bitcoin_address(coinaddr,addrtype,rmd160,20); - checktoshis = PAX_fiatdest(&seed,tokomodo,destaddr,pubkey33,coinaddr,kmdheight,base,value); - typestr = "withdraw"; -! //printf("%s.height.%d vs height.%d check %.8f/%.8f vs %.8f tokomodo.%d %d seed.%llx -> (%s)\n",ASSETCHAINS_SYMBOL,kmdheight,height,dstr(checktoshis),dstr(komodoshis),dstr(value),komodo_is_issuer(),strncmp(ASSETCHAINS_SYMBOL,base,strlen(base)) == 0,(long long)seed,coinaddr); - didstats = 0; -! if ( komodo_paxcmp(base,kmdheight,komodoshis,checktoshis,seed) == 0 ) - { - if ( value != 0 && ((pax= komodo_paxfind(txid,vout,'W')) == 0 || pax->didstats == 0) ) - { ---- 814,823 ---- - bitcoin_address(coinaddr,addrtype,rmd160,20); - checktoshis = PAX_fiatdest(&seed,tokomodo,destaddr,pubkey33,coinaddr,kmdheight,base,value); - typestr = "withdraw"; -! if ( 0 && strcmp(base,"RUB") == 0 ) -! printf("RUB WITHDRAW %s.height.%d vs height.%d check %.8f/%.8f vs %.8f tokomodo.%d %d seed.%llx -> (%s) len.%d\n",ASSETCHAINS_SYMBOL,kmdheight,height,dstr(checktoshis),dstr(komodoshis),dstr(value),komodo_is_issuer(),strncmp(ASSETCHAINS_SYMBOL,base,strlen(base)) == 0,(long long)seed,coinaddr,opretlen); - didstats = 0; -! //if ( komodo_paxcmp(base,kmdheight,komodoshis,checktoshis,seed) == 0 ) - { - if ( value != 0 && ((pax= komodo_paxfind(txid,vout,'W')) == 0 || pax->didstats == 0) ) - { -*************** -*** 679,697 **** - basesp->withdrawn += value; - didstats = 1; - if ( strcmp(base,ASSETCHAINS_SYMBOL) == 0 ) -! printf("########### %p withdrawn %s += %.8f\n",basesp,base,dstr(value)); - } -! //printf("notarize %s %.8f -> %.8f kmd.%d other.%d\n",ASSETCHAINS_SYMBOL,dstr(value),dstr(komodoshis),kmdheight,height); - } -! komodo_gateway_deposit(coinaddr,komodoshis,(char *)"KMD",value,rmd160,txid,vout,'W',kmdheight,height,source,0); - if ( (pax= komodo_paxfind(txid,vout,'W')) != 0 ) - { -- if ( didstats != 0 ) -- pax->didstats = 1; - pax->type = opretbuf[0]; -! pax->validated = komodoshis; - } -! } - } - else if ( tokomodo != 0 && opretbuf[0] == 'A' ) - { ---- 826,848 ---- - basesp->withdrawn += value; - didstats = 1; - if ( strcmp(base,ASSETCHAINS_SYMBOL) == 0 ) -! printf("########### %p withdrawn %s += %.8f check %.8f\n",basesp,base,dstr(value),dstr(checktoshis)); - } -! if ( 0 && strcmp(base,"RUB") == 0 && (pax == 0 || pax->approved == 0) ) -! printf("notarize %s %.8f -> %.8f kmd.%d other.%d\n",ASSETCHAINS_SYMBOL,dstr(value),dstr(komodoshis),kmdheight,height); - } -! komodo_gateway_deposit(coinaddr,0,(char *)"KMD",value,rmd160,txid,vout,'W',kmdheight,height,source,0); - if ( (pax= komodo_paxfind(txid,vout,'W')) != 0 ) - { - pax->type = opretbuf[0]; -! strcpy(pax->source,base); -! strcpy(pax->symbol,"KMD"); -! pax->height = kmdheight; -! pax->otherheight = height; -! pax->komodoshis = komodoshis; - } -! } // else printf("withdraw %s paxcmp ht.%d %d error value %.8f -> %.8f vs %.8f\n",base,kmdheight,height,dstr(value),dstr(komodoshis),dstr(checktoshis)); -! // need to allocate pax - } - else if ( tokomodo != 0 && opretbuf[0] == 'A' ) - { -*************** -*** 700,756 **** - { - for (i=0; i 0 ) - { - for (i=0; i KMD %.8f vs %.8f\n",kmdheights[i],CURRENCIES[baseids[i]],(double)srcvalues[i]/COIN,(double)values[i]/COIN,(double)checktoshis/COIN); -- for (j=0; j<32; j++) -- printf("%02x",((uint8_t *)&txids[i])[j]); -- printf(" v%d %.8f k.%d ht.%d base.%d\n",vouts[i],dstr(values[i]),kmdheights[i],otherheights[i],baseids[i]);*/ -- if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) == 0 ) - { -! bitcoin_address(coinaddr,60,&rmd160s[i*20],20); -! komodo_gateway_deposit(coinaddr,values[i],CURRENCIES[baseids[i]],srcvalues[i],&rmd160s[i*20],txids[i],vouts[i],'A',kmdheights[i],otherheights[i],CURRENCIES[baseids[i]],kmdheights[i]); -! komodo_paxmark(height,txids[i],vouts[i],'W',height); -! komodo_paxmark(height,txids[i],vouts[i],'A',height); -! if ( srcvalues[i] != 0 && (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) - { -! basesp->approved += srcvalues[i]; -! didstats = 1; -! if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 ) -! printf("########### %p approved %s += %.8f\n",basesp,CURRENCIES[baseids[i]],dstr(srcvalues[i])); - } -! //printf(" i.%d (%s) <- %.8f ADDFLAG APPROVED\n",i,coinaddr,dstr(values[i])); - } -! else if ( pax->didstats == 0 && srcvalues[i] != 0 ) -! { -! if ( (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) - { -! basesp->approved += srcvalues[i]; -! didstats = 1; -! if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 ) -! printf("########### %p approved %s += %.8f\n",basesp,CURRENCIES[baseids[i]],dstr(srcvalues[i])); - } -- } //else printf(" i.%d of n.%d pax.%p baseids[] %d\n",i,n,pax,baseids[i]); -- if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) != 0 ) -- { -- pax->type = opretbuf[0]; -- pax->approved = kmdheights[i]; -- if ( didstats != 0 ) -- pax->didstats = 1; -- if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 ) -- printf(" i.%d approved.%d <<<<<<<<<<<<< APPROVED %p\n",i,kmdheights[i],pax); - } - } -! } - //printf("extra.[%d] after %.8f\n",n,dstr(komodo_paxtotal())); - } - else if ( opretbuf[0] == 'X' ) ---- 851,928 ---- - { - for (i=0; i 0 ) - { - for (i=0; isymbol); -! printf("override neg1 with (%s)\n",pax->symbol); - } -! if ( baseids[i] < 0 ) -! continue; - } -! didstats = 0; -! seed = 0; -! checktoshis = komodo_paxprice(&seed,kmdheights[i],CURRENCIES[baseids[i]],(char *)"KMD",(uint64_t)values[i]); -! //printf("PAX_fiatdest ht.%d price %s %.8f -> KMD %.8f vs %.8f\n",kmdheights[i],CURRENCIES[baseids[i]],(double)values[i]/COIN,(double)srcvalues[i]/COIN,(double)checktoshis/COIN); -! if ( srcvalues[i] == checktoshis ) -! { -! if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) == 0 ) -! { -! bitcoin_address(coinaddr,60,&rmd160s[i*20],20); -! komodo_gateway_deposit(coinaddr,srcvalues[i],CURRENCIES[baseids[i]],values[i],&rmd160s[i*20],txids[i],vouts[i],'A',kmdheights[i],otherheights[i],CURRENCIES[baseids[i]],kmdheights[i]); -! if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) == 0 ) -! printf("unexpected null pax for approve\n"); -! else pax->validated = checktoshis; -! if ( (pax2= komodo_paxfind(txids[i],vouts[i],'W')) != 0 ) -! pax2->approved = kmdheights[i]; -! komodo_paxmark(height,txids[i],vouts[i],'W',height); -! //komodo_paxmark(height,txids[i],vouts[i],'A',height); -! if ( values[i] != 0 && (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) -! { -! basesp->approved += values[i]; -! didstats = 1; -! if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 ) -! printf("pax.%p ########### %p approved %s += %.8f -> %.8f/%.8f kht.%d %d\n",pax,basesp,CURRENCIES[baseids[i]],dstr(values[i]),dstr(srcvalues[i]),dstr(checktoshis),kmdheights[i],otherheights[i]); -! } -! //printf(" i.%d (%s) <- %.8f ADDFLAG APPROVED\n",i,coinaddr,dstr(values[i])); -! } -! else if ( pax->didstats == 0 && srcvalues[i] != 0 ) - { -! if ( (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) -! { -! basesp->approved += values[i]; -! didstats = 1; -! if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 ) -! printf("pax.%p ########### %p approved %s += %.8f -> %.8f/%.8f\n",pax,basesp,CURRENCIES[baseids[i]],dstr(values[i]),dstr(srcvalues[i]),dstr(checktoshis)); -! } -! } //else printf(" i.%d of n.%d pax.%p baseids[] %d\n",i,n,pax,baseids[i]); -! if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) != 0 ) -! { -! pax->type = opretbuf[0]; -! pax->approved = kmdheights[i]; -! pax->validated = checktoshis; -! if ( didstats != 0 ) -! pax->didstats = 1; -! //if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 ) -! //printf(" i.%d approved.%d <<<<<<<<<<<<< APPROVED %p\n",i,kmdheights[i],pax); - } - } - } -! } else printf("n.%d from opreturns\n",n); - //printf("extra.[%d] after %.8f\n",n,dstr(komodo_paxtotal())); - } - else if ( opretbuf[0] == 'X' ) -*************** -*** 770,783 **** - if ( (pax= komodo_paxfind(txids[i],vouts[i],'X')) != 0 ) - { - pax->type = opretbuf[0]; -! if ( baseids[i] >= 0 && srcvalues[i] != 0 && (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) - { -! basesp->redeemed += srcvalues[i]; - pax->didstats = 1; -! if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 ) -! printf("########### %p redeemed %s += %.8f\n",basesp,CURRENCIES[baseids[i]],dstr(srcvalues[i])); - } - } - } - } //else printf("komodo_issued_opreturn returned %d\n",n); - } ---- 942,964 ---- - if ( (pax= komodo_paxfind(txids[i],vouts[i],'X')) != 0 ) - { - pax->type = opretbuf[0]; -! if ( height < 121842 ) // fields got switched around due to legacy issues and approves -! value = srcvalues[i]; -! else value = values[i]; -! if ( baseids[i] >= 0 && value != 0 && (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) - { -! basesp->redeemed += value; - pax->didstats = 1; -! //if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 ) -! printf("ht.%d %.8f ########### %p redeemed %s += %.8f %.8f kht.%d ht.%d\n",height,dstr(value),basesp,CURRENCIES[baseids[i]],dstr(value),dstr(srcvalues[i]),kmdheights[i],otherheights[i]); - } - } -+ if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'W',height)) != 0 ) -+ komodo_paxdelete(pax); -+ if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'A',height)) != 0 ) -+ komodo_paxdelete(pax); -+ if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'X',height)) != 0 ) -+ komodo_paxdelete(pax); - } - } //else printf("komodo_issued_opreturn returned %d\n",n); - } -*************** -*** 788,802 **** - { - static long lastpos[34]; static char userpass[33][1024]; - FILE *fp; int32_t baseid,isrealtime,refid,blocks,longest; struct komodo_state *sp,*refsp; char *retstr,fname[512],*base,symbol[16],dest[16]; uint32_t buf[3]; cJSON *infoobj,*result; uint64_t RTmask = 0; - while ( KOMODO_INITDONE == 0 ) - { -! fprintf(stderr,"PASSPORT iteration waiting for KOMODO_INITDONE\n"); - sleep(3); - } - refsp = komodo_stateptr(symbol,dest); - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - refid = 33; -! else refid = komodo_baseid(ASSETCHAINS_SYMBOL)+1; // illegal base -> baseid.-1 -> 0 - //printf("PASSPORT %s refid.%d\n",ASSETCHAINS_SYMBOL,refid); - for (baseid=32; baseid>=0; baseid--) - { ---- 969,997 ---- - { - static long lastpos[34]; static char userpass[33][1024]; - FILE *fp; int32_t baseid,isrealtime,refid,blocks,longest; struct komodo_state *sp,*refsp; char *retstr,fname[512],*base,symbol[16],dest[16]; uint32_t buf[3]; cJSON *infoobj,*result; uint64_t RTmask = 0; -+ //printf("PASSPORT.(%s)\n",ASSETCHAINS_SYMBOL); - while ( KOMODO_INITDONE == 0 ) - { -! fprintf(stderr,"[%s] PASSPORT iteration waiting for KOMODO_INITDONE\n",ASSETCHAINS_SYMBOL); - sleep(3); - } - refsp = komodo_stateptr(symbol,dest); - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - refid = 33; -! else -! { -! refid = komodo_baseid(ASSETCHAINS_SYMBOL)+1; // illegal base -> baseid.-1 -> 0 -! if ( refid == 0 ) -! { -! KOMODO_PASSPORT_INITDONE = 1; -! return; -! } -! } -! if ( KOMODO_PAX == 0 ) -! { -! KOMODO_PASSPORT_INITDONE = 1; -! return; -! } - //printf("PASSPORT %s refid.%d\n",ASSETCHAINS_SYMBOL,refid); - for (baseid=32; baseid>=0; baseid--) - { -*************** -*** 807,813 **** - { - komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"komodostate"); - komodo_nameset(symbol,dest,base); -! if ( (fp= fopen(fname,"rb")) != 0 && (sp= komodo_stateptrget(symbol)) != 0 ) - { - fseek(fp,0,SEEK_END); - if ( ftell(fp) > lastpos[baseid] ) ---- 1002,1009 ---- - { - komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"komodostate"); - komodo_nameset(symbol,dest,base); -! sp = komodo_stateptrget(symbol); -! if ( (fp= fopen(fname,"rb")) != 0 && sp != 0 ) - { - fseek(fp,0,SEEK_END); - if ( ftell(fp) > lastpos[baseid] ) -*************** -*** 822,840 **** - printf("from.(%s) lastpos[%s] %ld\n",ASSETCHAINS_SYMBOL,CURRENCIES[baseid],lastpos[baseid]); - } //else fprintf(stderr,"%s.%ld ",CURRENCIES[baseid],ftell(fp)); - fclose(fp); -! } - komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"realtime"); - if ( (fp= fopen(fname,"rb")) != 0 ) - { - if ( fread(buf,1,sizeof(buf),fp) == sizeof(buf) ) - { - sp->CURRENT_HEIGHT = buf[0]; -! if ( buf[0] != 0 && buf[0] == buf[1] && buf[2] > time(NULL)-60 ) - { - isrealtime = 1; - RTmask |= (1LL << baseid); - memcpy(refsp->RTbufs[baseid+1],buf,sizeof(refsp->RTbufs[baseid+1])); -! } //else fprintf(stderr,"%s not RT\n",base); - } //else fprintf(stderr,"%s size error RT\n",base); - fclose(fp); - } //else fprintf(stderr,"%s open error RT\n",base); ---- 1018,1036 ---- - printf("from.(%s) lastpos[%s] %ld\n",ASSETCHAINS_SYMBOL,CURRENCIES[baseid],lastpos[baseid]); - } //else fprintf(stderr,"%s.%ld ",CURRENCIES[baseid],ftell(fp)); - fclose(fp); -! } else printf("error.(%s) %p\n",fname,sp); - komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"realtime"); - if ( (fp= fopen(fname,"rb")) != 0 ) - { - if ( fread(buf,1,sizeof(buf),fp) == sizeof(buf) ) - { - sp->CURRENT_HEIGHT = buf[0]; -! if ( buf[0] != 0 && buf[0] >= buf[1] && buf[2] > time(NULL)-300 ) - { - isrealtime = 1; - RTmask |= (1LL << baseid); - memcpy(refsp->RTbufs[baseid+1],buf,sizeof(refsp->RTbufs[baseid+1])); -! } else fprintf(stderr,"[%s]: %s not RT %u %u %d\n",ASSETCHAINS_SYMBOL,base,buf[0],buf[1],(int32_t)(time(NULL)-buf[2])); - } //else fprintf(stderr,"%s size error RT\n",base); - fclose(fp); - } //else fprintf(stderr,"%s open error RT\n",base); -*************** -*** 849,855 **** - if ( buf[0] != 0 && buf[0] == buf[1] ) - { - buf[2] = (uint32_t)time(NULL); -! RTmask |= (1LL << baseid) | 1; - memcpy(refsp->RTbufs[baseid+1],buf,sizeof(refsp->RTbufs[baseid+1])); - if ( refid != 0 ) - memcpy(refsp->RTbufs[0],buf,sizeof(refsp->RTbufs[0])); ---- 1045,1051 ---- - if ( buf[0] != 0 && buf[0] == buf[1] ) - { - buf[2] = (uint32_t)time(NULL); -! RTmask |= (1LL << baseid); - memcpy(refsp->RTbufs[baseid+1],buf,sizeof(refsp->RTbufs[baseid+1])); - if ( refid != 0 ) - memcpy(refsp->RTbufs[0],buf,sizeof(refsp->RTbufs[0])); -*************** -*** 865,869 **** ---- 1061,1066 ---- - komodo_paxtotal(); - refsp->RTmask = RTmask; - KOMODO_PASSPORT_INITDONE = 1; -+ //printf("done PASSPORT %s refid.%d\n",ASSETCHAINS_SYMBOL,refid); - } - -diff -crB ./src/komodo_globals.h ../../komodo-jl777/src/komodo_globals.h -*** ./src/komodo_globals.h 2017-01-03 10:40:50.231330177 +0000 ---- ../../komodo-jl777/src/komodo_globals.h 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 36,42 **** - - int COINBASE_MATURITY = 100; - -! int32_t IS_KOMODO_NOTARY,KOMODO_REWIND,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE; - std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES; - uint8_t NOTARY_PUBKEY33[33]; - ---- 36,42 ---- - - int COINBASE_MATURITY = 100; - -! int32_t IS_KOMODO_NOTARY,KOMODO_REWIND,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE,KOMODO_PAX; - std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES; - uint8_t NOTARY_PUBKEY33[33]; - -diff -crB ./src/komodo.h ../../komodo-jl777/src/komodo.h -*** ./src/komodo.h 2017-01-03 10:40:50.231330177 +0000 ---- ../../komodo-jl777/src/komodo.h 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 23,29 **** - // a. automate notarization fee payouts - // b. automated distribution of test REVS snapshot - -! //#define KOMODO_ASSETCHAINS_WAITNOTARIZE - #define KOMODO_PAXMAX (10000 * COIN) - - #include ---- 23,29 ---- - // a. automate notarization fee payouts - // b. automated distribution of test REVS snapshot - -! #define KOMODO_ASSETCHAINS_WAITNOTARIZE - #define KOMODO_PAXMAX (10000 * COIN) - - #include -*************** -*** 194,200 **** ---- 194,203 ---- - static FILE *fp; static int32_t errs; - struct komodo_state *sp; char fname[512],symbol[16],dest[16]; int32_t ht,func; uint8_t num,pubkeys[64][33]; - if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) -+ { -+ KOMODO_INITDONE = (uint32_t)time(NULL); - return; -+ } - if ( fp == 0 ) - { - komodo_statefname(fname,ASSETCHAINS_SYMBOL,(char *)"komodostate"); -*************** -*** 281,287 **** - errs++; - //komodo_eventadd_utxo(sp,symbol,height,notaryid,txhash,voutmask,numvouts); - } -- //#ifdef KOMODO_PAX - else if ( pvals != 0 && numpvals > 0 ) - { - int32_t i,nonz = 0; ---- 284,289 ---- -*************** -*** 301,307 **** - } - //printf("save pvals height.%d numpvals.%d\n",height,numpvals); - } -- //#endif - else if ( height != 0 ) - { - //printf("ht.%d func N ht.%d errs.%d\n",height,NOTARIZED_HEIGHT,errs); ---- 303,308 ---- -diff -crB ./src/komodo_interest.h ../../komodo-jl777/src/komodo_interest.h -*** ./src/komodo_interest.h 2017-01-03 10:40:50.231330177 +0000 ---- ../../komodo-jl777/src/komodo_interest.h 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 21,29 **** - uint64_t total; int32_t ind,incr = 100000; - if ( height >= maxheight ) - { -! interests = (uint64_t *)realloc(interests,(maxheight + incr) * sizeof(*interests) * 2); -! memset(&interests[maxheight << 1],0,incr * sizeof(*interests) * 2); -! maxheight += incr; - } - ind = (height << 1); - if ( paidinterest < 0 ) // request ---- 21,37 ---- - uint64_t total; int32_t ind,incr = 100000; - if ( height >= maxheight ) - { -! if ( interests == 0 ) -! { -! maxheight = height + incr; -! interests = (uint64_t *)calloc(maxheight,sizeof(*interests) * 2); -! } -! else -! { -! interests = (uint64_t *)realloc(interests,(maxheight + incr) * sizeof(*interests) * 2); -! memset(&interests[maxheight << 1],0,incr * sizeof(*interests) * 2); -! maxheight += incr; -! } - } - ind = (height << 1); - if ( paidinterest < 0 ) // request -diff -crB ./src/komodo_pax.h ../../komodo-jl777/src/komodo_pax.h -*** ./src/komodo_pax.h 2017-01-03 10:40:50.231330177 +0000 ---- ../../komodo-jl777/src/komodo_pax.h 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 429,434 **** ---- 429,435 ---- - height -= 10; - if ( (baseid= komodo_baseid(base)) >= 0 && (relid= komodo_baseid(rel)) >= 0 ) - { -+ portable_mutex_lock(&komodo_mutex); - for (i=NUM_PRICES-1; i>=0; i--) - { - ptr = &PVALS[36 * i]; -*************** -*** 439,450 **** - *kmdbtcp = ptr[MAX_CURRENCIES + 1] / 539; - *btcusdp = ptr[MAX_CURRENCIES + 2] / 539; - } - if ( kmdbtc != 0 && btcusd != 0 ) - return(komodo_paxcalc(&ptr[1],baseid,relid,basevolume,kmdbtc,btcusd)); - else return(0); - } - } -! } else printf("paxprice invalid base.%s %d, rel.%s %d\n",base,baseid,rel,relid); - return(0); - } - ---- 440,453 ---- - *kmdbtcp = ptr[MAX_CURRENCIES + 1] / 539; - *btcusdp = ptr[MAX_CURRENCIES + 2] / 539; - } -+ portable_mutex_unlock(&komodo_mutex); - if ( kmdbtc != 0 && btcusd != 0 ) - return(komodo_paxcalc(&ptr[1],baseid,relid,basevolume,kmdbtc,btcusd)); - else return(0); - } - } -! portable_mutex_unlock(&komodo_mutex); -! } //else printf("paxprice invalid base.%s %d, rel.%s %d\n",base,baseid,rel,relid); - return(0); - } - -*************** -*** 473,479 **** - } - kmdbtc = komodo_paxcorrelation(kmdbtcs,numvotes,*seedp) * 539; - btcusd = komodo_paxcorrelation(btcusds,numvotes,*seedp) * 539; -- //printf("kmdbtc %llu btcusd %llu\n",(long long)kmdbtc,(long long)btcusd); - for (i=nonz=0; i> 1) ) -+ { -+ //printf("kmdbtc %llu btcusd %llu\n",(long long)kmdbtc,(long long)btcusd); -+ //printf("komodo_paxprice nonz.%d of numvotes.%d\n",nonz,numvotes); - return(0); -+ } - return(komodo_paxcorrelation(votes,numvotes,*seedp) * basevolume / 100000); - } - -*************** -*** 527,533 **** - if ( fiatoshis < 0 ) - shortflag = 1, fiatoshis = -fiatoshis; - komodoshis = komodo_paxprice(seedp,height,base,(char *)"KMD",(uint64_t)fiatoshis); -! //printf("PAX_fiatdest ht.%d price %s %.8f -> KMD %.8f seed.%llx\n",height,base,(double)fiatoshis/COIN,(double)komodoshis/COIN,(long long)*seedp); - if ( bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr) == 20 ) - { - PAX_pubkey(1,pubkey33,&addrtype,rmd160,base,&shortflag,tokomodo != 0 ? &komodoshis : &fiatoshis); ---- 533,540 ---- - if ( fiatoshis < 0 ) - shortflag = 1, fiatoshis = -fiatoshis; - komodoshis = komodo_paxprice(seedp,height,base,(char *)"KMD",(uint64_t)fiatoshis); -! if ( 0 && strcmp(base,"RUB") == 0 ) -! printf("PAX_fiatdest ht.%d price %s %.8f -> KMD %.8f seed.%llx\n",height,base,(double)fiatoshis/COIN,(double)komodoshis/COIN,(long long)*seedp); - if ( bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr) == 20 ) - { - PAX_pubkey(1,pubkey33,&addrtype,rmd160,base,&shortflag,tokomodo != 0 ? &komodoshis : &fiatoshis); -diff -crB ./src/komodo_structs.h ../../komodo-jl777/src/komodo_structs.h -*** ./src/komodo_structs.h 2017-01-03 10:40:50.231330177 +0000 ---- ../../komodo-jl777/src/komodo_structs.h 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 57,63 **** - UT_hash_handle hh; - uint256 txid; - uint64_t komodoshis,fiatoshis,validated; -! int32_t marked,height,otherheight,approved,didstats; - uint16_t vout; - char symbol[16],source[16],coinaddr[64]; uint8_t rmd160[20],type,buf[35]; - }; ---- 57,63 ---- - UT_hash_handle hh; - uint256 txid; - uint64_t komodoshis,fiatoshis,validated; -! int32_t marked,height,otherheight,approved,didstats,ready; - uint16_t vout; - char symbol[16],source[16],coinaddr[64]; uint8_t rmd160[20],type,buf[35]; - }; -diff -crB ./src/komodo_utils.h ../../komodo-jl777/src/komodo_utils.h -*** ./src/komodo_utils.h 2017-01-03 10:40:50.235330381 +0000 ---- ../../komodo-jl777/src/komodo_utils.h 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 1448,1454 **** ---- 1448,1457 ---- - IS_KOMODO_NOTARY = GetBoolArg("-notary", false); - NOTARY_PUBKEY = GetArg("-pubkey", ""); - if ( strlen(NOTARY_PUBKEY.c_str()) == 66 ) -+ { - USE_EXTERNAL_PUBKEY = 1; -+ KOMODO_PAX = 1; -+ } else KOMODO_PAX = GetArg("-pax",0); - name = GetArg("-ac_name",""); - if ( (KOMODO_REWIND= GetArg("-rewind",0)) != 0 ) - ; -diff -crB ./src/main.cpp ../../komodo-jl777/src/main.cpp -*** ./src/main.cpp 2017-01-03 10:40:50.255331392 +0000 ---- ../../komodo-jl777/src/main.cpp 2017-01-03 09:49:08.864506767 +0000 -*************** -*** 26,31 **** ---- 26,32 ---- - #include "util.h" - #include "utilmoneystr.h" - #include "validationinterface.h" -+ #include "wallet/asyncrpcoperation_sendmany.h" - - #include - -*************** -*** 70,76 **** - bool fAlerts = DEFAULT_ALERTS; - - /** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */ -! CFeeRate minRelayTxFee = CFeeRate(5000); - - CTxMemPool mempool(::minRelayTxFee); - ---- 71,77 ---- - bool fAlerts = DEFAULT_ALERTS; - - /** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */ -! CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE); - - CTxMemPool mempool(::minRelayTxFee); - -*************** -*** 550,556 **** - - // Komodo globals - -- #define KOMODO_PAX - #define KOMODO_ZCASH - #include "komodo.h" - ---- 551,556 ---- -*************** -*** 871,878 **** - return false; - } else { - // Ensure that zk-SNARKs verify - BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { -! if (!joinsplit.Verify(*pzcashParams, tx.joinSplitPubKey)) { - return state.DoS(100, error("CheckTransaction(): joinsplit does not verify"), - REJECT_INVALID, "bad-txns-joinsplit-verification-failed"); - } ---- 871,879 ---- - return false; - } else { - // Ensure that zk-SNARKs verify -+ auto verifier = libzcash::ProofVerifier::Strict(); - BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { -! if (!joinsplit.Verify(*pzcashParams, verifier, tx.joinSplitPubKey)) { - return state.DoS(100, error("CheckTransaction(): joinsplit does not verify"), - REJECT_INVALID, "bad-txns-joinsplit-verification-failed"); - } -*************** -*** 1211,1222 **** - CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), mempool.HasNoInputsOf(tx)); - unsigned int nSize = entry.GetTxSize(); - -! // Don't accept it if it can't get into a block -! CAmount txMinFee = GetMinRelayFee(tx, nSize, true); -! if (fLimitFree && nFees < txMinFee) -! return state.DoS(0, error("AcceptToMemoryPool: not enough fees %s, %d < %d", -! hash.ToString(), nFees, txMinFee), -! REJECT_INSUFFICIENTFEE, "insufficient fee"); - - // Require that free transactions have sufficient priority to be mined in the next block. - if (GetBoolArg("-relaypriority", false) && nFees < ::minRelayTxFee.GetFee(nSize) && !AllowFree(view.GetPriority(tx, chainActive.Height() + 1))) { ---- 1212,1228 ---- - CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), mempool.HasNoInputsOf(tx)); - unsigned int nSize = entry.GetTxSize(); - -! // Accept a tx if it contains joinsplits and has at least the default fee specified by z_sendmany. -! if (tx.vjoinsplit.size() > 0 && nFees >= ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE) { -! // In future we will we have more accurate and dynamic computation of fees for tx with joinsplits. -! } else { -! // Don't accept it if it can't get into a block -! CAmount txMinFee = GetMinRelayFee(tx, nSize, true); -! if (fLimitFree && nFees < txMinFee) -! return state.DoS(0, error("AcceptToMemoryPool: not enough fees %s, %d < %d", -! hash.ToString(), nFees, txMinFee), -! REJECT_INSUFFICIENTFEE, "insufficient fee"); -! } - - // Require that free transactions have sufficient priority to be mined in the next block. - if (GetBoolArg("-relaypriority", false) && nFees < ::minRelayTxFee.GetFee(nSize) && !AllowFree(view.GetPriority(tx, chainActive.Height() + 1))) { -*************** -*** 1566,1572 **** - } - - // We define a condition where we should warn the user about as a fork of at least 7 blocks -! // with a tip within 72 blocks (+/- 12 hours if no one mines it) of ours - // We use 7 blocks rather arbitrarily as it represents just under 10% of sustained network - // hash rate operating on the fork. - // or a chain that is entirely longer than ours and invalid (note that this should be detected by both) ---- 1572,1578 ---- - } - - // We define a condition where we should warn the user about as a fork of at least 7 blocks -! // with a tip within 72 blocks (+/- 3 hours if no one mines it) of ours - // We use 7 blocks rather arbitrarily as it represents just under 10% of sustained network - // hash rate operating on the fork. - // or a chain that is entirely longer than ours and invalid (note that this should be detected by both) -*************** -*** 3213,3219 **** - - // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height - // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet): -! if (block.nVersion >= 2) - { - CScript expect = CScript() << nHeight; - if (block.vtx[0].vin[0].scriptSig.size() < expect.size() || ---- 3219,3228 ---- - - // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height - // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet): -! // Since MIN_BLOCK_VERSION = 4 all blocks with nHeight > 0 should satisfy this. -! // This rule is not applied to the genesis block, which didn't include the height -! // in the coinbase. -! if (nHeight > 0) - { - CScript expect = CScript() << nHeight; - if (block.vtx[0].vin[0].scriptSig.size() < expect.size() || -diff -crB ./src/main.h ../../komodo-jl777/src/main.h -*** ./src/main.h 2017-01-03 10:40:50.255331392 +0000 ---- ../../komodo-jl777/src/main.h 2017-01-03 09:49:08.864506767 +0000 -*************** -*** 48,57 **** - struct CNodeStateStats; - - /** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/ -! static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000; - static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0; - /** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/ -! static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 50000; - /** Default for accepting alerts from the P2P network. */ - static const bool DEFAULT_ALERTS = true; - /** Minimum alert priority for enabling safe mode. */ ---- 48,57 ---- - struct CNodeStateStats; - - /** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/ -! static const unsigned int DEFAULT_BLOCK_MAX_SIZE = MAX_BLOCK_SIZE; - static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0; - /** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/ -! static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = DEFAULT_BLOCK_MAX_SIZE / 2; - /** Default for accepting alerts from the P2P network. */ - static const bool DEFAULT_ALERTS = true; - /** Minimum alert priority for enabling safe mode. */ -*************** -*** 60,65 **** ---- 60,67 ---- - static const unsigned int MAX_P2SH_SIGOPS = 15; - /** The maximum number of sigops we're willing to relay/mine in a single tx */ - static const unsigned int MAX_STANDARD_TX_SIGOPS = MAX_BLOCK_SIGOPS/5; -+ /** Default for -minrelaytxfee, minimum relay fee for transactions */ -+ static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = 1000; - /** Default for -maxorphantx, maximum number of orphan transactions kept in memory */ - static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100; - /** The maximum size of a blk?????.dat file (since 0.8) */ -*************** -*** 91,96 **** ---- 93,102 ---- - /** Maximum length of reject messages. */ - static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111; - -+ // Sanity check the magic numbers when we change them -+ BOOST_STATIC_ASSERT(DEFAULT_BLOCK_MAX_SIZE <= MAX_BLOCK_SIZE); -+ BOOST_STATIC_ASSERT(DEFAULT_BLOCK_PRIORITY_SIZE <= DEFAULT_BLOCK_MAX_SIZE); -+ - #define equihash_parameters_acceptable(N, K) \ - ((CBlockHeader::HEADER_SIZE + equihash_solution_size(N, K))*MAX_HEADERS_RESULTS < \ - MAX_PROTOCOL_MESSAGE_LENGTH-1000) -diff -crB ./src/Makefile.am ../../komodo-jl777/src/Makefile.am -*** ./src/Makefile.am 2017-01-03 10:40:50.211329166 +0000 ---- ../../komodo-jl777/src/Makefile.am 2017-01-03 09:49:08.856506348 +0000 -*************** -*** 232,237 **** ---- 232,239 ---- - # when wallet enabled - libbitcoin_wallet_a_CPPFLAGS = $(BITCOIN_INCLUDES) - libbitcoin_wallet_a_SOURCES = \ -+ utiltest.cpp \ -+ utiltest.h \ - zcbenchmarks.cpp \ - zcbenchmarks.h \ - wallet/asyncrpcoperation_sendmany.cpp \ -*************** -*** 516,525 **** - @test -f $(PROTOC) - $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $( - #include -*************** -*** 15,29 **** ---- 17,65 ---- - #include - #include - -+ CCriticalSection cs_metrics; -+ -+ boost::synchronized_value nNodeStartTime; - AtomicCounter transactionsValidated; - AtomicCounter ehSolverRuns; - AtomicCounter solutionTargetChecks; - AtomicCounter minedBlocks; - -+ boost::synchronized_value> trackedBlocks; -+ - boost::synchronized_value> messageBox; - boost::synchronized_value initMessage; - bool loaded = false; - -+ extern int64_t GetNetworkHashPS(int lookup, int height); -+ -+ void TrackMinedBlock(uint256 hash) -+ { -+ LOCK(cs_metrics); -+ minedBlocks.increment(); -+ trackedBlocks->push_back(hash); -+ } -+ -+ void MarkStartTime() -+ { -+ *nNodeStartTime = GetTime(); -+ } -+ -+ int64_t GetUptime() -+ { -+ return GetTime() - *nNodeStartTime; -+ } -+ -+ double GetLocalSolPS_INTERNAL(int64_t uptime) -+ { -+ return uptime > 0 ? (double)solutionTargetChecks.get() / uptime : 0; -+ } -+ -+ double GetLocalSolPS() -+ { -+ return GetLocalSolPS_INTERNAL(GetUptime()); -+ } -+ - static bool metrics_ThreadSafeMessageBox(const std::string& message, - const std::string& caption, - unsigned int style) -*************** -*** 64,71 **** - uiInterface.InitMessage.connect(metrics_InitMessage); - } - -! void printMiningStatus(bool mining) - { - if (mining) { - int nThreads = GetArg("-genproclimit", 1); - if (nThreads < 0) { ---- 100,122 ---- - uiInterface.InitMessage.connect(metrics_InitMessage); - } - -! int printNetworkStats() -! { -! LOCK2(cs_main, cs_vNodes); -! -! std::cout << " " << _("Block height") << " | " << chainActive.Height() << std::endl; -! std::cout << " " << _("Network solution rate") << " | " << GetNetworkHashPS(120, -1) << " Sol/s" << std::endl; -! std::cout << " " << _("Connections") << " | " << vNodes.size() << std::endl; -! std::cout << std::endl; -! -! return 4; -! } -! -! int printMiningStatus(bool mining) - { -+ // Number of lines that are always displayed -+ int lines = 1; -+ - if (mining) { - int nThreads = GetArg("-genproclimit", 1); - if (nThreads < 0) { -*************** -*** 75,95 **** - else - nThreads = boost::thread::hardware_concurrency(); - } -! std::cout << strprintf(_("You are running %d mining threads."), nThreads) << std::endl; - } else { - std::cout << _("You are currently not mining.") << std::endl; - std::cout << _("To enable mining, add 'gen=1' to your zcash.conf and restart.") << std::endl; - } - std::cout << std::endl; - } - -! int printMetrics(size_t cols, int64_t nStart, bool mining) - { - // Number of lines that are always displayed - int lines = 3; - - // Calculate uptime -! int64_t uptime = GetTime() - nStart; - int days = uptime / (24 * 60 * 60); - int hours = (uptime - (days * 24 * 60 * 60)) / (60 * 60); - int minutes = (uptime - (((days * 24) + hours) * 60 * 60)) / 60; ---- 126,151 ---- - else - nThreads = boost::thread::hardware_concurrency(); - } -! std::cout << strprintf(_("You are mining with the %s solver on %d threads."), -! GetArg("-equihashsolver", "default"), nThreads) << std::endl; -! lines++; - } else { - std::cout << _("You are currently not mining.") << std::endl; - std::cout << _("To enable mining, add 'gen=1' to your zcash.conf and restart.") << std::endl; -+ lines += 2; - } - std::cout << std::endl; -+ -+ return lines; - } - -! int printMetrics(size_t cols, bool mining) - { - // Number of lines that are always displayed - int lines = 3; - - // Calculate uptime -! int64_t uptime = GetUptime(); - int days = uptime / (24 * 60 * 60); - int hours = (uptime - (days * 24 * 60 * 60)) / (60 * 60); - int minutes = (uptime - (((days * 24) + hours) * 60 * 60)) / 60; -*************** -*** 110,128 **** - std::cout << strDuration << std::endl; - lines += (strDuration.size() / cols); - -! std::cout << "- " << strprintf(_("You have validated %d transactions!"), transactionsValidated.get()) << std::endl; - -! if (mining) { -! double solps = uptime > 0 ? (double)solutionTargetChecks.get() / uptime : 0; - std::string strSolps = strprintf("%.4f Sol/s", solps); - std::cout << "- " << strprintf(_("You have contributed %s on average to the network solution rate."), strSolps) << std::endl; - std::cout << "- " << strprintf(_("You have completed %d Equihash solver runs."), ehSolverRuns.get()) << std::endl; - lines += 2; - -! int mined = minedBlocks.get(); - if (mined > 0) { - std::cout << "- " << strprintf(_("You have mined %d blocks!"), mined) << std::endl; -! lines++; - } - } - std::cout << std::endl; ---- 166,233 ---- - std::cout << strDuration << std::endl; - lines += (strDuration.size() / cols); - -! int validatedCount = transactionsValidated.get(); -! if (validatedCount > 1) { -! std::cout << "- " << strprintf(_("You have validated %d transactions!"), validatedCount) << std::endl; -! } else if (validatedCount == 1) { -! std::cout << "- " << _("You have validated a transaction!") << std::endl; -! } else { -! std::cout << "- " << _("You have validated no transactions.") << std::endl; -! } - -! if (mining && loaded) { -! double solps = GetLocalSolPS_INTERNAL(uptime); - std::string strSolps = strprintf("%.4f Sol/s", solps); - std::cout << "- " << strprintf(_("You have contributed %s on average to the network solution rate."), strSolps) << std::endl; - std::cout << "- " << strprintf(_("You have completed %d Equihash solver runs."), ehSolverRuns.get()) << std::endl; - lines += 2; - -! int mined = 0; -! int orphaned = 0; -! CAmount immature {0}; -! CAmount mature {0}; -! { -! LOCK2(cs_main, cs_metrics); -! boost::strict_lock_ptr> u = trackedBlocks.synchronize(); -! auto consensusParams = Params().GetConsensus(); -! auto tipHeight = chainActive.Height(); -! -! // Update orphans and calculate subsidies -! std::list::iterator it = u->begin(); -! while (it != u->end()) { -! auto hash = *it; -! if (mapBlockIndex.count(hash) > 0 && -! chainActive.Contains(mapBlockIndex[hash])) { -! int height = mapBlockIndex[hash]->nHeight; -! CAmount subsidy = GetBlockSubsidy(height, consensusParams); -! if ((height > 0) && (height <= consensusParams.GetLastFoundersRewardBlockHeight())) { -! subsidy -= subsidy/5; -! } -! if (std::max(0, COINBASE_MATURITY - (tipHeight - height)) > 0) { -! immature += subsidy; -! } else { -! mature += subsidy; -! } -! it++; -! } else { -! it = u->erase(it); -! } -! } -! -! mined = minedBlocks.get(); -! orphaned = mined - u->size(); -! } -! - if (mined > 0) { -+ std::string units = Params().CurrencyUnits(); - std::cout << "- " << strprintf(_("You have mined %d blocks!"), mined) << std::endl; -! std::cout << " " -! << strprintf(_("Orphaned: %d blocks, Immature: %u %s, Mature: %u %s"), -! orphaned, -! FormatMoney(immature), units, -! FormatMoney(mature), units) -! << std::endl; -! lines += 2; - } - } - std::cout << std::endl; -*************** -*** 171,194 **** - // Make this thread recognisable as the metrics screen thread - RenameThread("zcash-metrics-screen"); - -! // Clear screen -! std::cout << "\e[2J"; -! -! // Print art -! std::cout << METRICS_ART << std::endl; -! std::cout << std::endl; -! -! // Thank you text -! std::cout << _("Thank you for running a Zcash node!") << std::endl; -! std::cout << _("You're helping to strengthen the network and contributing to a social good :)") << std::endl; -! std::cout << std::endl; -! -! // Miner status -! bool mining = GetBoolArg("-gen", false); -! printMiningStatus(mining); -! -! // Count uptime -! int64_t nStart = GetTime(); - - while (true) { - // Number of lines that are always displayed ---- 276,299 ---- - // Make this thread recognisable as the metrics screen thread - RenameThread("zcash-metrics-screen"); - -! // Determine whether we should render a persistent UI or rolling metrics -! bool isTTY = isatty(STDOUT_FILENO); -! bool isScreen = GetBoolArg("-metricsui", isTTY); -! int64_t nRefresh = GetArg("-metricsrefreshtime", isTTY ? 1 : 600); -! -! if (isScreen) { -! // Clear screen -! std::cout << "\e[2J"; -! -! // Print art -! std::cout << METRICS_ART << std::endl; -! std::cout << std::endl; -! -! // Thank you text -! std::cout << _("Thank you for running a Zcash node!") << std::endl; -! std::cout << _("You're helping to strengthen the network and contributing to a social good :)") << std::endl; -! std::cout << std::endl; -! } - - while (true) { - // Number of lines that are always displayed -*************** -*** 196,202 **** - int cols = 80; - - // Get current window size -! if (isatty(STDOUT_FILENO)) { - struct winsize w; - w.ws_col = 0; - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1 && w.ws_col != 0) { ---- 301,307 ---- - int cols = 80; - - // Get current window size -! if (isTTY) { - struct winsize w; - w.ws_col = 0; - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1 && w.ws_col != 0) { -*************** -*** 204,223 **** - } - } - -! // Erase below current position -! std::cout << "\e[J"; - -! lines += printMetrics(cols, nStart, mining); - lines += printMessageBox(cols); - lines += printInitMessage(); - -! // Explain how to exit -! std::cout << "[" << _("Press Ctrl+C to exit") << "] [" << _("Set 'showmetrics=0' to hide") << "]" << std::endl;; - -! boost::this_thread::interruption_point(); -! MilliSleep(1000); - -! // Return to the top of the updating section -! std::cout << "\e[" << lines << "A"; - } - } ---- 309,347 ---- - } - } - -! if (isScreen) { -! // Erase below current position -! std::cout << "\e[J"; -! } -! -! // Miner status -! bool mining = GetBoolArg("-gen", false); - -! if (loaded) { -! lines += printNetworkStats(); -! } -! lines += printMiningStatus(mining); -! lines += printMetrics(cols, mining); - lines += printMessageBox(cols); - lines += printInitMessage(); - -! if (isScreen) { -! // Explain how to exit -! std::cout << "[" << _("Press Ctrl+C to exit") << "] [" << _("Set 'showmetrics=0' to hide") << "]" << std::endl; -! } else { -! // Print delineator -! std::cout << "----------------------------------------" << std::endl; -! } - -! int64_t nWaitEnd = GetTime() + nRefresh; -! while (GetTime() < nWaitEnd) { -! boost::this_thread::interruption_point(); -! MilliSleep(200); -! } - -! if (isScreen) { -! // Return to the top of the updating section -! std::cout << "\e[" << lines << "A"; -! } - } - } -diff -crB ./src/metrics.h ../../komodo-jl777/src/metrics.h -*** ./src/metrics.h 2017-01-03 10:40:50.255331392 +0000 ---- ../../komodo-jl777/src/metrics.h 2017-01-03 09:49:08.864506767 +0000 -*************** -*** 2,12 **** - // Distributed under the MIT software license, see the accompanying - // file COPYING or http://www.opensource.org/licenses/mit-license.php. - - #include - #include - - struct AtomicCounter { -! std::atomic value; - - AtomicCounter() : value {0} { } - ---- 2,14 ---- - // Distributed under the MIT software license, see the accompanying - // file COPYING or http://www.opensource.org/licenses/mit-license.php. - -+ #include "uint256.h" -+ - #include - #include - - struct AtomicCounter { -! std::atomic value; - - AtomicCounter() : value {0} { } - -*************** -*** 26,32 **** - extern AtomicCounter transactionsValidated; - extern AtomicCounter ehSolverRuns; - extern AtomicCounter solutionTargetChecks; -! extern AtomicCounter minedBlocks; - - void ConnectMetricsScreen(); - void ThreadShowMetricsScreen(); ---- 28,38 ---- - extern AtomicCounter transactionsValidated; - extern AtomicCounter ehSolverRuns; - extern AtomicCounter solutionTargetChecks; -! -! void TrackMinedBlock(uint256 hash); -! -! void MarkStartTime(); -! double GetLocalSolPS(); - - void ConnectMetricsScreen(); - void ThreadShowMetricsScreen(); -diff -crB ./src/miner.cpp ../../komodo-jl777/src/miner.cpp -*** ./src/miner.cpp 2017-01-03 10:40:50.255331392 +0000 ---- ../../komodo-jl777/src/miner.cpp 2017-01-03 09:49:08.864506767 +0000 -*************** -*** 99,105 **** - } - - #define ASSETCHAINS_MINHEIGHT 100 -! #define ROUNDROBIN_DELAY 58 - extern int32_t ASSETCHAINS_SEED,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAIN_INIT,KOMODO_INITDONE,KOMODO_ON_DEMAND,KOMODO_INITDONE; - extern char ASSETCHAINS_SYMBOL[16]; - extern std::string NOTARY_PUBKEY; ---- 99,106 ---- - } - - #define ASSETCHAINS_MINHEIGHT 100 -! #define KOMODO_ELECTION_GAP 2000 -! #define ROUNDROBIN_DELAY 55 - extern int32_t ASSETCHAINS_SEED,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAIN_INIT,KOMODO_INITDONE,KOMODO_ON_DEMAND,KOMODO_INITDONE; - extern char ASSETCHAINS_SYMBOL[16]; - extern std::string NOTARY_PUBKEY; -*************** -*** 109,114 **** ---- 110,116 ---- - int32_t komodo_is_special(int32_t height,uint8_t pubkey33[33]); - int32_t komodo_pax_opreturn(uint8_t *opret,int32_t maxsize); - uint64_t komodo_paxtotal(); -+ int32_t komodo_baseid(char *origbase); - int32_t komodo_is_issuer(); - int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *symbol,int32_t tokomodo); - int32_t komodo_isrealtime(int32_t *kmdheightp); -*************** -*** 121,137 **** - if(!pblocktemplate.get()) - return NULL; - CBlock *pblock = &pblocktemplate->block; // pointer for convenience -! if ( ASSETCHAINS_SYMBOL[0] != 0 && chainActive.Tip()->nHeight > ASSETCHAINS_MINHEIGHT ) - { - isrealtime = komodo_isrealtime(&kmdheight); -! while ( KOMODO_ON_DEMAND == 0 ) - { - deposits = komodo_paxtotal(); -! if ( KOMODO_INITDONE == 0 || (isrealtime= komodo_isrealtime(&kmdheight)) == 0 ) - { - //fprintf(stderr,"INITDONE.%d RT.%d deposits %.8f ht.%d\n",KOMODO_INITDONE,isrealtime,(double)deposits/COIN,kmdheight); - } -! else if ( deposits != 0 ) - { - fprintf(stderr,"start CreateNewBlock %s initdone.%d deposit %.8f mempool.%d RT.%u KOMODO_ON_DEMAND.%d\n",ASSETCHAINS_SYMBOL,KOMODO_INITDONE,(double)komodo_paxtotal()/COIN,(int32_t)mempool.GetTotalTxSize(),isrealtime,KOMODO_ON_DEMAND); - break; ---- 123,140 ---- - if(!pblocktemplate.get()) - return NULL; - CBlock *pblock = &pblocktemplate->block; // pointer for convenience -! if ( ASSETCHAINS_SYMBOL[0] != 0 && chainActive.Tip()->nHeight >= ASSETCHAINS_MINHEIGHT ) - { - isrealtime = komodo_isrealtime(&kmdheight); -! deposits = komodo_paxtotal(); -! while ( KOMODO_ON_DEMAND == 0 && deposits == 0 && (int32_t)mempool.GetTotalTxSize() == 0 ) - { - deposits = komodo_paxtotal(); -! if ( KOMODO_INITDONE == 0 || (komodo_baseid(ASSETCHAINS_SYMBOL) >= 0 && (isrealtime= komodo_isrealtime(&kmdheight)) == 0) ) - { - //fprintf(stderr,"INITDONE.%d RT.%d deposits %.8f ht.%d\n",KOMODO_INITDONE,isrealtime,(double)deposits/COIN,kmdheight); - } -! else if ( deposits != 0 || (int32_t)mempool.GetTotalTxSize() > 0 ) - { - fprintf(stderr,"start CreateNewBlock %s initdone.%d deposit %.8f mempool.%d RT.%u KOMODO_ON_DEMAND.%d\n",ASSETCHAINS_SYMBOL,KOMODO_INITDONE,(double)komodo_paxtotal()/COIN,(int32_t)mempool.GetTotalTxSize(),isrealtime,KOMODO_ON_DEMAND); - break; -*************** -*** 242,247 **** ---- 245,252 ---- - - dPriority += (double)nValueIn * nConf; - } -+ nTotalIn += tx.GetJoinSplitValueIn(); -+ - if (fMissingInputs) continue; - - // Priority is sum(valuein * age) / modified_txsize -*************** -*** 419,425 **** - if ( !TestBlockValidity(state, *pblock, pindexPrev, false, false)) - { - fprintf(stderr,"testblockvalidity failed\n"); -! //throw std::runtime_error("CreateNewBlock(): TestBlockValidity failed"); - } - } - ---- 424,430 ---- - if ( !TestBlockValidity(state, *pblock, pindexPrev, false, false)) - { - fprintf(stderr,"testblockvalidity failed\n"); -! throw std::runtime_error("CreateNewBlock(): TestBlockValidity failed"); - } - } - -*************** -*** 473,479 **** - script[34] = OP_CHECKSIG; - //scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; - } -! if ( 0 && ASSETCHAINS_SYMBOL[0] == 0 ) - { - for (i=0; i<65; i++) - fprintf(stderr,"%d ",komodo_minerid(chainActive.Tip()->nHeight-i)); ---- 478,484 ---- - script[34] = OP_CHECKSIG; - //scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; - } -! if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - { - for (i=0; i<65; i++) - fprintf(stderr,"%d ",komodo_minerid(chainActive.Tip()->nHeight-i)); -*************** -*** 509,515 **** - if (!ProcessNewBlock(chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL)) - return error("KomodoMiner: ProcessNewBlock, block not accepted"); - -! minedBlocks.increment(); - - return true; - } ---- 514,520 ---- - if (!ProcessNewBlock(chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL)) - return error("KomodoMiner: ProcessNewBlock, block not accepted"); - -! TrackMinedBlock(pblock->GetHash()); - - return true; - } -*************** -*** 614,627 **** - arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits); - if ( ASSETCHAINS_SYMBOL[0] == 0 && komodo_is_special(pindexPrev->nHeight+1,NOTARY_PUBKEY33) > 0 ) - { -! hashTarget = arith_uint256().SetCompact(KOMODO_MINDIFF_NBITS); -! fprintf(stderr,"I am the chosen one for %s ht.%d\n",ASSETCHAINS_SYMBOL,pindexPrev->nHeight+1); - } else Mining_start = 0; - while (true) - { -! if ( ASSETCHAINS_SYMBOL[0] != 0 && pblock->vtx[0].vout.size() == 1 && Mining_height > ASSETCHAINS_MINHEIGHT ) - { -! //fprintf(stderr,"skip generating %s on-demand block, no tx avail\n",ASSETCHAINS_SYMBOL); - sleep(10); - break; - } ---- 619,635 ---- - arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits); - if ( ASSETCHAINS_SYMBOL[0] == 0 && komodo_is_special(pindexPrev->nHeight+1,NOTARY_PUBKEY33) > 0 ) - { -! if ( (Mining_height % KOMODO_ELECTION_GAP) > 64 || (Mining_height % KOMODO_ELECTION_GAP) == 0 ) -! { -! hashTarget = arith_uint256().SetCompact(KOMODO_MINDIFF_NBITS); -! fprintf(stderr,"I am the chosen one for %s ht.%d\n",ASSETCHAINS_SYMBOL,pindexPrev->nHeight+1); -! } else Mining_start = 0; - } else Mining_start = 0; - while (true) - { -! if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && pblock->vtx[0].vout.size() == 1 && Mining_height > ASSETCHAINS_MINHEIGHT ) - { -! fprintf(stderr,"skip generating %s on-demand block, no tx avail\n",ASSETCHAINS_SYMBOL); - sleep(10); - break; - } -*************** -*** 784,794 **** ---- 792,804 ---- - } - catch (const boost::thread_interrupted&) - { -+ c.disconnect(); - LogPrintf("KomodoMiner terminated\n"); - throw; - } - catch (const std::runtime_error &e) - { -+ c.disconnect(); - LogPrintf("KomodoMiner runtime error: %s\n", e.what()); - return; - } -diff -crB ./src/pow.cpp ../../komodo-jl777/src/pow.cpp -*** ./src/pow.cpp 2017-01-03 10:40:50.259331594 +0000 ---- ../../komodo-jl777/src/pow.cpp 2017-01-03 09:49:08.864506767 +0000 -*************** -*** 113,119 **** - bool CheckProofOfWork(int32_t height,uint8_t *pubkey33,uint256 hash, unsigned int nBits, const Consensus::Params& params) - { - extern int32_t KOMODO_REWIND; -! bool fNegative,fOverflow; int32_t i,nonz=0,special,special2,notaryid=-1,flag = 0; - arith_uint256 bnTarget; - - bnTarget.SetCompact(nBits, &fNegative, &fOverflow); ---- 113,119 ---- - bool CheckProofOfWork(int32_t height,uint8_t *pubkey33,uint256 hash, unsigned int nBits, const Consensus::Params& params) - { - extern int32_t KOMODO_REWIND; -! bool fNegative,fOverflow; int32_t i,nonz=0,special=0,special2=0,notaryid=-1,flag = 0; - arith_uint256 bnTarget; - - bnTarget.SetCompact(nBits, &fNegative, &fOverflow); -*************** -*** 130,144 **** - if ( nonz == 0 ) - return(true); // will come back via different path with pubkey set - special2 = komodo_is_special(height,pubkey33); -! if ( notaryid >= 0 && ((height >= 64000 && height <= 90065) || (height % KOMODO_ELECTION_GAP) > 64) ) - { -- //if ( special2 == -2 ) -- // printf("height.%d special2.%d special.%d\n",height,special2,special); - if ( (height >= 64000 && height <= 90065) || (height % KOMODO_ELECTION_GAP) == 0 || (height < 80000 && (special != 0 || special2 > 0)) || (height >= 80000 && special2 > 0) ) - { - bnTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); - flag = 1; - } - } - } - if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit)) ---- 130,153 ---- - if ( nonz == 0 ) - return(true); // will come back via different path with pubkey set - special2 = komodo_is_special(height,pubkey33); -! /*if ( notaryid >= 0 && ((height >= 64000 && height <= 90065) || (height % KOMODO_ELECTION_GAP) > 64) ) - { - if ( (height >= 64000 && height <= 90065) || (height % KOMODO_ELECTION_GAP) == 0 || (height < 80000 && (special != 0 || special2 > 0)) || (height >= 80000 && special2 > 0) ) - { - bnTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); - flag = 1; - } -+ }*/ -+ if ( notaryid >= 0 ) -+ { -+ if ( height > 10000 && height < 80000 && (special != 0 || special2 > 0) ) -+ flag = 1; -+ else if ( height >= 80000 && height < 108000 && special2 > 0 ) -+ flag = 1; -+ else if ( height >= 108000 && special2 > 0 ) -+ flag = ((height % KOMODO_ELECTION_GAP) > 64 || (height % KOMODO_ELECTION_GAP) == 0); -+ if ( flag != 0 ) -+ bnTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); - } - } - if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit)) -*************** -*** 146,160 **** - // Check proof of work matches claimed amount - if ( UintToArith256(hash) > bnTarget ) - { -! int32_t i; -! for (i=31; i>=0; i--) -! printf("%02x",((uint8_t *)&hash)[i]); -! printf(" hash vs "); -! for (i=31; i>=0; i--) -! printf("%02x",((uint8_t *)&bnTarget)[i]); -! printf(" ht.%d REWIND.%d special.%d notaryid.%d ht.%d mod.%d error\n",height,KOMODO_REWIND,special,notaryid,height,(height % 35)); -! if ( height <= KOMODO_REWIND ) -! return error("CheckProofOfWork(): hash doesn't match nBits"); - } - return true; - } ---- 155,171 ---- - // Check proof of work matches claimed amount - if ( UintToArith256(hash) > bnTarget ) - { -! { -! int32_t i; -! for (i=31; i>=0; i--) -! printf("%02x",((uint8_t *)&hash)[i]); -! printf(" hash vs "); -! for (i=31; i>=0; i--) -! printf("%02x",((uint8_t *)&bnTarget)[i]); -! printf(" ht.%d REWIND.%d special.%d notaryid.%d ht.%d mod.%d error\n",height,KOMODO_REWIND,special,notaryid,height,(height % 35)); -! if ( height < 90000 || (height > 110000 && KOMODO_REWIND == 0) ) -! return error("CheckProofOfWork(): hash doesn't match nBits"); -! } - } - return true; - } -diff -crB ./src/primitives/block.h ../../komodo-jl777/src/primitives/block.h -*** ./src/primitives/block.h 2017-01-03 10:40:50.259331594 +0000 ---- ../../komodo-jl777/src/primitives/block.h 2017-01-03 09:49:08.864506767 +0000 -*************** -*** 200,205 **** ---- 200,209 ---- - { - return vHave.empty(); - } -+ -+ friend bool operator==(const CBlockLocator& a, const CBlockLocator& b) { -+ return (a.vHave == b.vHave); -+ } - }; - - #endif // BITCOIN_PRIMITIVES_BLOCK_H -diff -crB ./src/primitives/transaction.cpp ../../komodo-jl777/src/primitives/transaction.cpp -*** ./src/primitives/transaction.cpp 2017-01-03 10:40:50.259331594 +0000 ---- ../../komodo-jl777/src/primitives/transaction.cpp 2017-01-03 09:49:08.864506767 +0000 -*************** -*** 62,67 **** ---- 62,70 ---- - // Randomize the order of the inputs and outputs - inputMap = {0, 1}; - outputMap = {0, 1}; -+ -+ assert(gen); -+ - MappedShuffle(inputs.begin(), inputMap.begin(), ZC_NUM_JS_INPUTS, gen); - MappedShuffle(outputs.begin(), outputMap.begin(), ZC_NUM_JS_OUTPUTS, gen); - -*************** -*** 72,81 **** ---- 75,86 ---- - - bool JSDescription::Verify( - ZCJoinSplit& params, -+ libzcash::ProofVerifier& verifier, - const uint256& pubKeyHash - ) const { - return params.verify( - proof, -+ verifier, - pubKeyHash, - randomSeed, - macs, -diff -crB ./src/primitives/transaction.h ../../komodo-jl777/src/primitives/transaction.h -*** ./src/primitives/transaction.h 2017-01-03 10:40:50.259331594 +0000 ---- ../../komodo-jl777/src/primitives/transaction.h 2017-01-03 09:49:08.864506767 +0000 -*************** -*** 101,107 **** - ); - - // Verifies that the JoinSplit proof is correct. -! bool Verify(ZCJoinSplit& params, const uint256& pubKeyHash) const; - - // Returns the calculated h_sig - uint256 h_sig(ZCJoinSplit& params, const uint256& pubKeyHash) const; ---- 101,111 ---- - ); - - // Verifies that the JoinSplit proof is correct. -! bool Verify( -! ZCJoinSplit& params, -! libzcash::ProofVerifier& verifier, -! const uint256& pubKeyHash -! ) const; - - // Returns the calculated h_sig - uint256 h_sig(ZCJoinSplit& params, const uint256& pubKeyHash) const; -diff -crB ./src/random.cpp ../../komodo-jl777/src/random.cpp -*** ./src/random.cpp 2017-01-03 10:40:50.339335643 +0000 ---- ../../komodo-jl777/src/random.cpp 2017-01-03 09:49:08.864506767 +0000 -*************** -*** 137,139 **** ---- 137,144 ---- - insecure_rand_Rw = tmp; - } - } -+ -+ int GenIdentity(int n) -+ { -+ return n-1; -+ } -diff -crB ./src/random.h ../../komodo-jl777/src/random.h -*** ./src/random.h 2017-01-03 10:40:50.339335643 +0000 ---- ../../komodo-jl777/src/random.h 2017-01-03 09:49:08.864506767 +0000 -*************** -*** 26,31 **** ---- 26,36 ---- - uint256 GetRandHash(); - - /** -+ * Identity function for MappedShuffle, so that elements retain their original order. -+ */ -+ int GenIdentity(int n); -+ -+ /** - * Rearranges the elements in the range [first,first+len) randomly, assuming - * that gen is a uniform random number generator. Follows the same algorithm as - * std::shuffle in C++11 (a Durstenfeld shuffle). -diff -crB ./src/rpcclient.cpp ../../komodo-jl777/src/rpcclient.cpp -*** ./src/rpcclient.cpp 2017-01-03 10:40:50.343335845 +0000 ---- ../../komodo-jl777/src/rpcclient.cpp 2017-01-03 09:49:08.864506767 +0000 -*************** -*** 103,108 **** ---- 103,109 ---- - { "z_gettotalbalance", 0}, - { "z_sendmany", 1}, - { "z_sendmany", 2}, -+ { "z_sendmany", 3}, - { "z_getoperationstatus", 0}, - { "z_getoperationresult", 0}, - { "z_importkey", 1 }, -diff -crB ./src/rpcmining.cpp ../../komodo-jl777/src/rpcmining.cpp -*** ./src/rpcmining.cpp 2017-01-03 10:40:50.343335845 +0000 ---- ../../komodo-jl777/src/rpcmining.cpp 2017-01-03 09:49:08.864506767 +0000 -*************** -*** 37,43 **** - * or over the difficulty averaging window if 'lookup' is nonpositive. - * If 'height' is nonnegative, compute the estimate at the time when a given block was found. - */ -! Value GetNetworkHashPS(int lookup, int height) { - CBlockIndex *pb = chainActive.Tip(); - - if (height >= 0 && height < chainActive.Height()) ---- 37,43 ---- - * or over the difficulty averaging window if 'lookup' is nonpositive. - * If 'height' is nonnegative, compute the estimate at the time when a given block was found. - */ -! int64_t GetNetworkHashPS(int lookup, int height) { - CBlockIndex *pb = chainActive.Tip(); - - if (height >= 0 && height < chainActive.Height()) -*************** -*** 74,92 **** - return (int64_t)(workDiff.getdouble() / timeDiff); - } - - Value getnetworkhashps(const Array& params, bool fHelp) - { - if (fHelp || params.size() > 2) - throw runtime_error( - "getnetworkhashps ( blocks height )\n" -! "\nReturns the estimated network hashes per second based on the last n blocks.\n" - "Pass in [blocks] to override # of blocks, -1 specifies over difficulty averaging window.\n" - "Pass in [height] to estimate the network speed at the time when a certain block was found.\n" - "\nArguments:\n" - "1. blocks (numeric, optional, default=120) The number of blocks, or -1 for blocks over difficulty averaging window.\n" - "2. height (numeric, optional, default=-1) To estimate at the time of the given height.\n" - "\nResult:\n" -! "x (numeric) Hashes per second estimated\n" - "\nExamples:\n" - + HelpExampleCli("getnetworkhashps", "") - + HelpExampleRpc("getnetworkhashps", "") ---- 74,133 ---- - return (int64_t)(workDiff.getdouble() / timeDiff); - } - -+ Value getlocalsolps(const Array& params, bool fHelp) -+ { -+ if (fHelp) -+ throw runtime_error( -+ "getlocalsolps\n" -+ "\nReturns the average local solutions per second since this node was started.\n" -+ "This is the same information shown on the metrics screen (if enabled).\n" -+ "\nResult:\n" -+ "xxx.xxxxx (numeric) Solutions per second average\n" -+ "\nExamples:\n" -+ + HelpExampleCli("getlocalsolps", "") -+ + HelpExampleRpc("getlocalsolps", "") -+ ); -+ -+ LOCK(cs_main); -+ return GetLocalSolPS(); -+ } -+ -+ Value getnetworksolps(const Array& params, bool fHelp) -+ { -+ if (fHelp || params.size() > 2) -+ throw runtime_error( -+ "getnetworksolps ( blocks height )\n" -+ "\nReturns the estimated network solutions per second based on the last n blocks.\n" -+ "Pass in [blocks] to override # of blocks, -1 specifies over difficulty averaging window.\n" -+ "Pass in [height] to estimate the network speed at the time when a certain block was found.\n" -+ "\nArguments:\n" -+ "1. blocks (numeric, optional, default=120) The number of blocks, or -1 for blocks over difficulty averaging window.\n" -+ "2. height (numeric, optional, default=-1) To estimate at the time of the given height.\n" -+ "\nResult:\n" -+ "x (numeric) Solutions per second estimated\n" -+ "\nExamples:\n" -+ + HelpExampleCli("getnetworksolps", "") -+ + HelpExampleRpc("getnetworksolps", "") -+ ); -+ -+ LOCK(cs_main); -+ return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1); -+ } -+ - Value getnetworkhashps(const Array& params, bool fHelp) - { - if (fHelp || params.size() > 2) - throw runtime_error( - "getnetworkhashps ( blocks height )\n" -! "\nDEPRECATED - left for backwards-compatibility. Use getnetworksolps instead.\n" -! "\nReturns the estimated network solutions per second based on the last n blocks.\n" - "Pass in [blocks] to override # of blocks, -1 specifies over difficulty averaging window.\n" - "Pass in [height] to estimate the network speed at the time when a certain block was found.\n" - "\nArguments:\n" - "1. blocks (numeric, optional, default=120) The number of blocks, or -1 for blocks over difficulty averaging window.\n" - "2. height (numeric, optional, default=-1) To estimate at the time of the given height.\n" - "\nResult:\n" -! "x (numeric) Solutions per second estimated\n" - "\nExamples:\n" - + HelpExampleCli("getnetworkhashps", "") - + HelpExampleRpc("getnetworkhashps", "") -*************** -*** 209,215 **** - CValidationState state; - if (!ProcessNewBlock(chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); -- minedBlocks.increment(); - ++nHeight; - blockHashes.push_back(pblock->GetHash().GetHex()); - } ---- 250,255 ---- -*************** -*** 280,285 **** ---- 320,327 ---- - " \"errors\": \"...\" (string) Current errors\n" - " \"generate\": true|false (boolean) If the generation is on or off (see getgenerate or setgenerate calls)\n" - " \"genproclimit\": n (numeric) The processor limit for generation. -1 if no generation. (see getgenerate or setgenerate calls)\n" -+ " \"localsolps\": xxx.xxxxx (numeric) The average local solution rate in Sol/s since this node was started\n" -+ " \"networksolps\": x (numeric) The estimated network solution rate in Sol/s\n" - " \"pooledtx\": n (numeric) The size of the mem pool\n" - " \"testnet\": true|false (boolean) If using testnet or not\n" - " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" -*************** -*** 299,305 **** - obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty())); - obj.push_back(Pair("errors", GetWarnings("statusbar"))); - obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1))); -! obj.push_back(Pair("networkhashps", getnetworkhashps(params, false))); - obj.push_back(Pair("pooledtx", (uint64_t)mempool.size())); - obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC())); - obj.push_back(Pair("chain", Params().NetworkIDString())); ---- 341,349 ---- - obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty())); - obj.push_back(Pair("errors", GetWarnings("statusbar"))); - obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1))); -! obj.push_back(Pair("localsolps" , getlocalsolps(params, false))); -! obj.push_back(Pair("networksolps", getnetworksolps(params, false))); -! obj.push_back(Pair("networkhashps", getnetworksolps(params, false))); - obj.push_back(Pair("pooledtx", (uint64_t)mempool.size())); - obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC())); - obj.push_back(Pair("chain", Params().NetworkIDString())); -*************** -*** 483,492 **** - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); - - if (vNodes.empty()) -! throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Bitcoin is not connected!"); - - if (IsInitialBlockDownload()) -! throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Bitcoin is downloading blocks..."); - - static unsigned int nTransactionsUpdatedLast; - ---- 527,536 ---- - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); - - if (vNodes.empty()) -! throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Zcash is not connected!"); - - if (IsInitialBlockDownload()) -! throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Zcash is downloading blocks..."); - - static unsigned int nTransactionsUpdatedLast; - -diff -crB ./src/rpcmisc.cpp ../../komodo-jl777/src/rpcmisc.cpp -*** ./src/rpcmisc.cpp 2017-01-03 10:40:50.343335845 +0000 ---- ../../komodo-jl777/src/rpcmisc.cpp 2017-01-03 09:49:08.864506767 +0000 -*************** -*** 23,28 **** ---- 23,30 ---- - #include "json/json_spirit_utils.h" - #include "json/json_spirit_value.h" - -+ #include "zcash/Address.hpp" -+ - using namespace json_spirit; - using namespace std; - -*************** -*** 236,241 **** ---- 238,306 ---- - return ret; - } - -+ -+ Value z_validateaddress(const Array& params, bool fHelp) -+ { -+ if (fHelp || params.size() != 1) -+ throw runtime_error( -+ "z_validateaddress \"zaddr\"\n" -+ "\nReturn information about the given z address.\n" -+ "\nArguments:\n" -+ "1. \"zaddr\" (string, required) The z address to validate\n" -+ "\nResult:\n" -+ "{\n" -+ " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n" -+ " \"address\" : \"zaddr\", (string) The z address validated\n" -+ " \"ismine\" : true|false, (boolean) If the address is yours or not\n" -+ " \"payingkey\" : \"hex\", (string) The hex value of the paying key, a_pk\n" -+ " \"transmissionkey\" : \"hex\", (string) The hex value of the transmission key, pk_enc\n" -+ -+ "}\n" -+ "\nExamples:\n" -+ + HelpExampleCli("validateaddress", "\"zcWsmqT4X2V4jgxbgiCzyrAfRT1vi1F4sn7M5Pkh66izzw8Uk7LBGAH3DtcSMJeUb2pi3W4SQF8LMKkU2cUuVP68yAGcomL\"") -+ ); -+ -+ -+ #ifdef ENABLE_WALLET -+ LOCK2(cs_main, pwalletMain->cs_wallet); -+ #else -+ LOCK(cs_main); -+ #endif -+ -+ bool isValid = false; -+ bool isMine = false; -+ std::string payingKey, transmissionKey; -+ -+ string strAddress = params[0].get_str(); -+ try { -+ CZCPaymentAddress address(strAddress); -+ libzcash::PaymentAddress addr = address.Get(); -+ -+ #ifdef ENABLE_WALLET -+ isMine = pwalletMain->HaveSpendingKey(addr); -+ #endif -+ payingKey = addr.a_pk.GetHex(); -+ transmissionKey = addr.pk_enc.GetHex(); -+ isValid = true; -+ } catch (std::runtime_error e) { -+ // address is invalid, nop here as isValid is false. -+ } -+ -+ Object ret; -+ ret.push_back(Pair("isvalid", isValid)); -+ if (isValid) -+ { -+ ret.push_back(Pair("address", strAddress)); -+ ret.push_back(Pair("payingkey", payingKey)); -+ ret.push_back(Pair("transmissionkey", transmissionKey)); -+ #ifdef ENABLE_WALLET -+ ret.push_back(Pair("ismine", isMine)); -+ #endif -+ } -+ return ret; -+ } -+ -+ - /** - * Used by addmultisigaddress / createmultisig: - */ -diff -crB ./src/rpcprotocol.cpp ../../komodo-jl777/src/rpcprotocol.cpp -*** ./src/rpcprotocol.cpp 2017-01-03 10:40:50.343335845 +0000 ---- ../../komodo-jl777/src/rpcprotocol.cpp 2017-01-03 09:49:08.864506767 +0000 -*************** -*** 33,39 **** - - /** - * HTTP protocol -! * - * This ain't Apache. We're just using HTTP header for the length field - * and to be compatible with other JSON-RPC implementations. - */ ---- 33,39 ---- - - /** - * HTTP protocol -! * - * This ain't Apache. We're just using HTTP header for the length field - * and to be compatible with other JSON-RPC implementations. - */ -*************** -*** 42,48 **** - { - ostringstream s; - s << "POST / HTTP/1.1\r\n" -! << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n" - << "Host: 127.0.0.1\r\n" - << "Content-Type: application/json\r\n" - << "Content-Length: " << strMsg.size() << "\r\n" ---- 42,48 ---- - { - ostringstream s; - s << "POST / HTTP/1.1\r\n" -! << "User-Agent: zcash-json-rpc/" << FormatFullVersion() << "\r\n" - << "Host: 127.0.0.1\r\n" - << "Content-Type: application/json\r\n" - << "Content-Length: " << strMsg.size() << "\r\n" -*************** -*** 77,83 **** - if (nStatus == HTTP_UNAUTHORIZED) - return strprintf("HTTP/1.0 401 Authorization Required\r\n" - "Date: %s\r\n" -! "Server: bitcoin-json-rpc/%s\r\n" - "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n" - "Content-Type: text/html\r\n" - "Content-Length: 296\r\n" ---- 77,83 ---- - if (nStatus == HTTP_UNAUTHORIZED) - return strprintf("HTTP/1.0 401 Authorization Required\r\n" - "Date: %s\r\n" -! "Server: zcash-json-rpc/%s\r\n" - "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n" - "Content-Type: text/html\r\n" - "Content-Length: 296\r\n" -*************** -*** 104,110 **** - "Connection: %s\r\n" - "Content-Length: %u\r\n" - "Content-Type: %s\r\n" -! "Server: bitcoin-json-rpc/%s\r\n" - "\r\n", - nStatus, - httpStatusDescription(nStatus), ---- 104,110 ---- - "Connection: %s\r\n" - "Content-Length: %u\r\n" - "Content-Type: %s\r\n" -! "Server: zcash-json-rpc/%s\r\n" - "\r\n", - nStatus, - httpStatusDescription(nStatus), -*************** -*** 248,254 **** - * JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility, - * but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were - * unspecified (HTTP errors and contents of 'error'). -! * - * 1.0 spec: http://json-rpc.org/wiki/specification - * 1.2 spec: http://jsonrpc.org/historical/json-rpc-over-http.html - * http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx ---- 248,254 ---- - * JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility, - * but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were - * unspecified (HTTP errors and contents of 'error'). -! * - * 1.0 spec: http://json-rpc.org/wiki/specification - * 1.2 spec: http://jsonrpc.org/historical/json-rpc-over-http.html - * http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx -diff -crB ./src/rpcserver.cpp ../../komodo-jl777/src/rpcserver.cpp -*** ./src/rpcserver.cpp 2017-01-03 10:40:50.343335845 +0000 ---- ../../komodo-jl777/src/rpcserver.cpp 2017-01-03 09:49:08.864506767 +0000 -*************** -*** 309,314 **** ---- 309,316 ---- - /* Mining */ - { "mining", "getblocktemplate", &getblocktemplate, true }, - { "mining", "getmininginfo", &getmininginfo, true }, -+ { "mining", "getlocalsolps", &getlocalsolps, true }, -+ { "mining", "getnetworksolps", &getnetworksolps, true }, - { "mining", "getnetworkhashps", &getnetworkhashps, true }, - { "mining", "prioritisetransaction", &prioritisetransaction, true }, - { "mining", "submitblock", &submitblock, true }, -*************** -*** 335,340 **** ---- 337,343 ---- - { "util", "verifymessage", &verifymessage, true }, - { "util", "estimatefee", &estimatefee, true }, - { "util", "estimatepriority", &estimatepriority, true }, -+ { "util", "z_validateaddress", &z_validateaddress, true }, /* uses wallet if enabled */ - - /* Not shown in help */ - { "hidden", "invalidateblock", &invalidateblock, true }, -*************** -*** 1034,1042 **** ---- 1037,1051 ---- - // Read HTTP message headers and body - ReadHTTPMessage(conn->stream(), mapHeaders, strRequest, nProto, MAX_SIZE); - -+ // TODO #1856: Re-enable support for persistent connections. -+ // We have disabled support for HTTP Keep-Alive until resolution of #1680, upstream rpc deadlock. -+ // Close connection immediately. -+ fRun = false; -+ /* - // HTTP Keep-Alive is false; close connection immediately - if ((mapHeaders["connection"] == "close") || (!GetBoolArg("-rpckeepalive", true))) - fRun = false; -+ */ - - // Process via JSON-RPC API - if (strURI == "/") { -diff -crB ./src/rpcserver.h ../../komodo-jl777/src/rpcserver.h -*** ./src/rpcserver.h 2017-01-03 10:40:50.343335845 +0000 ---- ../../komodo-jl777/src/rpcserver.h 2017-01-03 09:49:08.864506767 +0000 -*************** -*** 169,174 **** ---- 169,176 ---- - extern json_spirit::Value getgenerate(const json_spirit::Array& params, bool fHelp); // in rpcmining.cpp - extern json_spirit::Value setgenerate(const json_spirit::Array& params, bool fHelp); - extern json_spirit::Value generate(const json_spirit::Array& params, bool fHelp); -+ extern json_spirit::Value getlocalsolps(const json_spirit::Array& params, bool fHelp); -+ extern json_spirit::Value getnetworksolps(const json_spirit::Array& params, bool fHelp); - extern json_spirit::Value getnetworkhashps(const json_spirit::Array& params, bool fHelp); - extern json_spirit::Value getmininginfo(const json_spirit::Array& params, bool fHelp); - extern json_spirit::Value prioritisetransaction(const json_spirit::Array& params, bool fHelp); -*************** -*** 270,275 **** ---- 272,278 ---- - extern json_spirit::Value z_getoperationstatus(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp - extern json_spirit::Value z_getoperationresult(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp - extern json_spirit::Value z_listoperationids(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp -+ extern json_spirit::Value z_validateaddress(const json_spirit::Array& params, bool fHelp); // in rpcmisc.cpp - - - // in rest.cpp -diff -crB ./src/test/coins_tests.cpp ../../komodo-jl777/src/test/coins_tests.cpp -*** ./src/test/coins_tests.cpp 2017-01-03 10:40:50.375337465 +0000 ---- ../../komodo-jl777/src/test/coins_tests.cpp 2017-01-03 09:49:08.868506976 +0000 -*************** -*** 166,171 **** ---- 166,414 ---- - - BOOST_FIXTURE_TEST_SUITE(coins_tests, BasicTestingSetup) - -+ BOOST_AUTO_TEST_CASE(nullifier_regression_test) -+ { -+ // Correct behavior: -+ { -+ CCoinsViewTest base; -+ CCoinsViewCacheTest cache1(&base); -+ -+ // Insert a nullifier into the base. -+ uint256 nf = GetRandHash(); -+ cache1.SetNullifier(nf, true); -+ cache1.Flush(); // Flush to base. -+ -+ // Remove the nullifier from cache -+ cache1.SetNullifier(nf, false); -+ -+ // The nullifier now should be `false`. -+ BOOST_CHECK(!cache1.GetNullifier(nf)); -+ } -+ -+ // Also correct behavior: -+ { -+ CCoinsViewTest base; -+ CCoinsViewCacheTest cache1(&base); -+ -+ // Insert a nullifier into the base. -+ uint256 nf = GetRandHash(); -+ cache1.SetNullifier(nf, true); -+ cache1.Flush(); // Flush to base. -+ -+ // Remove the nullifier from cache -+ cache1.SetNullifier(nf, false); -+ cache1.Flush(); // Flush to base. -+ -+ // The nullifier now should be `false`. -+ BOOST_CHECK(!cache1.GetNullifier(nf)); -+ } -+ -+ // Works because we bring it from the parent cache: -+ { -+ CCoinsViewTest base; -+ CCoinsViewCacheTest cache1(&base); -+ -+ // Insert a nullifier into the base. -+ uint256 nf = GetRandHash(); -+ cache1.SetNullifier(nf, true); -+ cache1.Flush(); // Empties cache. -+ -+ // Create cache on top. -+ { -+ // Remove the nullifier. -+ CCoinsViewCacheTest cache2(&cache1); -+ BOOST_CHECK(cache2.GetNullifier(nf)); -+ cache2.SetNullifier(nf, false); -+ cache2.Flush(); // Empties cache, flushes to cache1. -+ } -+ -+ // The nullifier now should be `false`. -+ BOOST_CHECK(!cache1.GetNullifier(nf)); -+ } -+ -+ // Was broken: -+ { -+ CCoinsViewTest base; -+ CCoinsViewCacheTest cache1(&base); -+ -+ // Insert a nullifier into the base. -+ uint256 nf = GetRandHash(); -+ cache1.SetNullifier(nf, true); -+ cache1.Flush(); // Empties cache. -+ -+ // Create cache on top. -+ { -+ // Remove the nullifier. -+ CCoinsViewCacheTest cache2(&cache1); -+ cache2.SetNullifier(nf, false); -+ cache2.Flush(); // Empties cache, flushes to cache1. -+ } -+ -+ // The nullifier now should be `false`. -+ BOOST_CHECK(!cache1.GetNullifier(nf)); -+ } -+ } -+ -+ BOOST_AUTO_TEST_CASE(anchor_pop_regression_test) -+ { -+ // Correct behavior: -+ { -+ CCoinsViewTest base; -+ CCoinsViewCacheTest cache1(&base); -+ -+ // Create dummy anchor/commitment -+ ZCIncrementalMerkleTree tree; -+ uint256 cm = GetRandHash(); -+ tree.append(cm); -+ -+ // Add the anchor -+ cache1.PushAnchor(tree); -+ cache1.Flush(); -+ -+ // Remove the anchor -+ cache1.PopAnchor(ZCIncrementalMerkleTree::empty_root()); -+ cache1.Flush(); -+ -+ // Add the anchor back -+ cache1.PushAnchor(tree); -+ cache1.Flush(); -+ -+ // The base contains the anchor, of course! -+ { -+ ZCIncrementalMerkleTree checktree; -+ BOOST_CHECK(cache1.GetAnchorAt(tree.root(), checktree)); -+ BOOST_CHECK(checktree.root() == tree.root()); -+ } -+ } -+ -+ // Previously incorrect behavior -+ { -+ CCoinsViewTest base; -+ CCoinsViewCacheTest cache1(&base); -+ -+ // Create dummy anchor/commitment -+ ZCIncrementalMerkleTree tree; -+ uint256 cm = GetRandHash(); -+ tree.append(cm); -+ -+ // Add the anchor and flush to disk -+ cache1.PushAnchor(tree); -+ cache1.Flush(); -+ -+ // Remove the anchor, but don't flush yet! -+ cache1.PopAnchor(ZCIncrementalMerkleTree::empty_root()); -+ -+ { -+ CCoinsViewCacheTest cache2(&cache1); // Build cache on top -+ cache2.PushAnchor(tree); // Put the same anchor back! -+ cache2.Flush(); // Flush to cache1 -+ } -+ -+ // cache2's flush kinda worked, i.e. cache1 thinks the -+ // tree is there, but it didn't bring down the correct -+ // treestate... -+ { -+ ZCIncrementalMerkleTree checktree; -+ BOOST_CHECK(cache1.GetAnchorAt(tree.root(), checktree)); -+ BOOST_CHECK(checktree.root() == tree.root()); // Oh, shucks. -+ } -+ -+ // Flushing cache won't help either, just makes the inconsistency -+ // permanent. -+ cache1.Flush(); -+ { -+ ZCIncrementalMerkleTree checktree; -+ BOOST_CHECK(cache1.GetAnchorAt(tree.root(), checktree)); -+ BOOST_CHECK(checktree.root() == tree.root()); // Oh, shucks. -+ } -+ } -+ } -+ -+ BOOST_AUTO_TEST_CASE(anchor_regression_test) -+ { -+ // Correct behavior: -+ { -+ CCoinsViewTest base; -+ CCoinsViewCacheTest cache1(&base); -+ -+ // Insert anchor into base. -+ ZCIncrementalMerkleTree tree; -+ uint256 cm = GetRandHash(); -+ tree.append(cm); -+ cache1.PushAnchor(tree); -+ cache1.Flush(); -+ -+ cache1.PopAnchor(ZCIncrementalMerkleTree::empty_root()); -+ BOOST_CHECK(cache1.GetBestAnchor() == ZCIncrementalMerkleTree::empty_root()); -+ BOOST_CHECK(!cache1.GetAnchorAt(tree.root(), tree)); -+ } -+ -+ // Also correct behavior: -+ { -+ CCoinsViewTest base; -+ CCoinsViewCacheTest cache1(&base); -+ -+ // Insert anchor into base. -+ ZCIncrementalMerkleTree tree; -+ uint256 cm = GetRandHash(); -+ tree.append(cm); -+ cache1.PushAnchor(tree); -+ cache1.Flush(); -+ -+ cache1.PopAnchor(ZCIncrementalMerkleTree::empty_root()); -+ cache1.Flush(); -+ BOOST_CHECK(cache1.GetBestAnchor() == ZCIncrementalMerkleTree::empty_root()); -+ BOOST_CHECK(!cache1.GetAnchorAt(tree.root(), tree)); -+ } -+ -+ // Works because we bring the anchor in from parent cache. -+ { -+ CCoinsViewTest base; -+ CCoinsViewCacheTest cache1(&base); -+ -+ // Insert anchor into base. -+ ZCIncrementalMerkleTree tree; -+ uint256 cm = GetRandHash(); -+ tree.append(cm); -+ cache1.PushAnchor(tree); -+ cache1.Flush(); -+ -+ { -+ // Pop anchor. -+ CCoinsViewCacheTest cache2(&cache1); -+ BOOST_CHECK(cache2.GetAnchorAt(tree.root(), tree)); -+ cache2.PopAnchor(ZCIncrementalMerkleTree::empty_root()); -+ cache2.Flush(); -+ } -+ -+ BOOST_CHECK(cache1.GetBestAnchor() == ZCIncrementalMerkleTree::empty_root()); -+ BOOST_CHECK(!cache1.GetAnchorAt(tree.root(), tree)); -+ } -+ -+ // Was broken: -+ { -+ CCoinsViewTest base; -+ CCoinsViewCacheTest cache1(&base); -+ -+ // Insert anchor into base. -+ ZCIncrementalMerkleTree tree; -+ uint256 cm = GetRandHash(); -+ tree.append(cm); -+ cache1.PushAnchor(tree); -+ cache1.Flush(); -+ -+ { -+ // Pop anchor. -+ CCoinsViewCacheTest cache2(&cache1); -+ cache2.PopAnchor(ZCIncrementalMerkleTree::empty_root()); -+ cache2.Flush(); -+ } -+ -+ BOOST_CHECK(cache1.GetBestAnchor() == ZCIncrementalMerkleTree::empty_root()); -+ BOOST_CHECK(!cache1.GetAnchorAt(tree.root(), tree)); -+ } -+ } -+ - BOOST_AUTO_TEST_CASE(nullifiers_test) - { - CCoinsViewTest base; -Only in ../../komodo-jl777/src/test/data: merkle_commitments.json -diff -crB ./src/test/data/merkle_path.json ../../komodo-jl777/src/test/data/merkle_path.json -*** ./src/test/data/merkle_path.json 2017-01-03 10:40:50.395338477 +0000 ---- ../../komodo-jl777/src/test/data/merkle_path.json 2017-01-03 09:49:08.872507185 +0000 -*************** -*** 1,123 **** - [ -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000101010001010001000001000100010100010000010100000001000101010101000000000100010101010001010100000101000101000100000001010001000001000101000000010000000101000001010001000100010101010000010100000100010101000101010100000101010101010001010101010001010000010001000100000001010000010101000001000101010001000100000100000100000001010100000000000001010001000001000001010000000100000100000000010101000101010001000101010101010100010101010100000101010100010001000000000101000000000001010001010101000100010000010101000101000000fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000100000000000100010001000001010101000000000000000101010001010000000001000000010101010001010001010101010001010001000001000000010000010001000000010101000001000100010100010101010100000001000100000001010001010001000000000100010101000000000100000100010001010101010001000100000001010001010001000100010101010100010000010101010000010001010100000101010100010100000001010101010101000101000001010001000000000100000001010001010101000101000100000001010100010100010101000100010001010001010101010000000001000001000000010000000001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000100000000000100010001000001010101000000000000000101010001010000000001000000010101010001010001010101010001010001000001000000010000010001000000010101000001000100010100010101010100000001000100000001010001010001000000000100010101000000000100000100010001010101010001000100000001010001010001000100010101010100010000010101010000010001010100000101010100010100000001010101010101000101000001010001000000000100000001010001010101000101000100000001010100010100010101000100010001010001010101010000000001000001000000010000000001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100000001000101000101010100000000000001000000000001000100000000010000010001000100010000000100010101010000000000010001010001000001010001010100000001000001010101010100000001010000000000000000000101000000010100000000000001010100010001010100010101000000010000010001010000000001000100000101000100010100000001000001000001000100010000000001000001010000010101000100010000000001010100010101010000010001000000010000000100010100010100010100010100000101010001010101010000010000000100000001000101010000010001000001010000000001fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100000001000101000101010100000000000001000000000001000100000000010000010001000100010000000100010101010000000000010001010001000001010001010100000001000001010101010100000001010000000000000000000101000000010100000000000001010100010001010100010101000000010000010001010000000001000100000101000100010100000001000001000001000100010000000001000001010000010101000100010000000001010100010101010000010001000000010000000100010100010100010100010100000101010001010101010000010000000100000001000101010000010001000001010000000001fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100000001000101000101010100000000000001000000000001000100000000010000010001000100010000000100010101010000000000010001010001000001010001010100000001000001010101010100000001010000000000000000000101000000010100000000000001010100010001010100010101000000010000010001010000000001000100000101000100010100000001000001000001000100010000000001000001010000010101000100010000000001010100010101010000010001000000010000000100010100010100010100010100000101010001010101010000010000000100000001000101010000010001000001010000000001fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100000001000101000101010100000000000001000000000001000100000000010000010001000100010000000100010101010000000000010001010001000001010001010100000001000001010101010100000001010000000000000000000101000000010100000000000001010100010001010100010101000000010000010001010000000001000100000101000100010100000001000001000001000100010000000001000001010000010101000100010000000001010100010101010000010001000000010000000100010100010100010100010100000101010001010101010000010000000100000001000101010000010001000001010000000001fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010000010000010100010101000100010000000001010100000001000100010000010100000000010100000000010000010100000001000100010000000000010001000100000101000101000101010101000001000100000101000000000101000101000101000101000001010101010001010000000101000001000101010000010001010001000000000001000001000100000000010001010100000101000000010001010000000100010000000001000001010001000001000100010001010000010101010001010101010000000100010100010001000000000001000000010101000001010001000001000001010100000101010000010101fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010000010000010100010101000100010000000001010100000001000100010000010100000000010100000000010000010100000001000100010000000000010001000100000101000101000101010101000001000100000101000000000101000101000101000101000001010101010001010000000101000001000101010000010001010001000000000001000001000100000000010001010100000101000000010001010000000100010000000001000001010001000001000100010001010000010101010001010101010000000100010100010001000000000001000000010101000001010001000001000001010100000101010000010101fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010000010000010100010101000100010000000001010100000001000100010000010100000000010100000000010000010100000001000100010000000000010001000100000101000101000101010101000001000100000101000000000101000101000101000101000001010101010001010000000101000001000101010000010001010001000000000001000001000100000000010001010100000101000000010001010000000100010000000001000001010001000001000100010001010000010101010001010101010000000100010100010001000000000001000000010101000001010001000001000001010100000101010000010101fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010000010000010100010101000100010000000001010100000001000100010000010100000000010100000000010000010100000001000100010000000000010001000100000101000101000101010101000001000100000101000000000101000101000101000101000001010101010001010000000101000001000101010000010001010001000000000001000001000100000000010001010100000101000000010001010000000100010000000001000001010001000001000100010001010000010101010001010101010000000100010100010001000000000001000000010101000001010001000001000001010100000101010000010101fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101010001010001000001000100010100010000010100000001000101010101000000000100010101010001010100000101000101000100000001010001000001000101000000010000000101000001010001000100010101010000010100000100010101000101010100000101010101010001010101010001010000010001000100000001010000010101000001000101010001000100000100000100000001010100000000000001010001000001000001010000000100000100000000010101000101010001000101010101010100010101010100000101010100010001000000000101000000000001010001010101000100010000010101000101000000fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100010101010001010000010001000000010100000001010100000000010001000000000101010101000001000100010100010000010001010001010101010000010101000101010100010001000000010100000001010100010001000000000100000101010001000000000100010100000001010000010001000000000000010101000000010101010001000101010101010100010100000000010100010101000101000100010101000000010101000000010101000001000001000101010000000101010000000000000001010101010001010001010100010000000001010100000101000000000101010001010100000101000101010000010000000100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100010101010001010000010001000000010100000001010100000000010001000000000101010101000001000100010100010000010001010001010101010000010101000101010100010001000000010100000001010100010001000000000100000101010001000000000100010100000001010000010001000000000000010101000000010101010001000101010101010100010100000000010100010101000101000100010101000000010101000000010101000001000001000101010000000101010000000000000001010101010001010001010100010000000001010100000101000000000101010001010100000101000101010000010000000100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100010101010001010000010001000000010100000001010100000000010001000000000101010101000001000100010100010000010001010001010101010000010101000101010100010001000000010100000001010100010001000000000100000101010001000000000100010100000001010000010001000000000000010101000000010101010001000101010101010100010100000000010100010101000101000100010101000000010101000000010101000001000001000101010000000101010000000000000001010101010001010001010100010000000001010100000101000000000101010001010100000101000101010000010000000100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100010101010001010000010001000000010100000001010100000000010001000000000101010101000001000100010100010000010001010001010101010000010101000101010100010001000000010100000001010100010001000000000100000101010001000000000100010100000001010000010001000000000000010101000000010101010001000101010101010100010100000000010100010101000101000100010101000000010101000000010101000001000001000101010000000101010000000000000001010101010001010001010100010000000001010100000101000000000101010001010100000101000101010000010000000100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000100000000000100010001000001010101000000000000000101010001010000000001000000010101010001010001010101010001010001000001000000010000010001000000010101000001000100010100010101010100000001000100000001010001010001000000000100010101000000000100000100010001010101010001000100000001010001010001000100010101010100010000010101010000010001010100000101010100010100000001010101010101000101000001010001000000000100000001010001010101000101000100000001010100010100010101000100010001010001010101010000000001000001000000010000000001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000100000000000100010001000001010101000000000000000101010001010000000001000000010101010001010001010101010001010001000001000000010000010001000000010101000001000100010100010101010100000001000100000001010001010001000000000100010101000000000100000100010001010101010001000100000001010001010001000100010101010100010000010101010000010001010100000101010100010100000001010101010101000101000001010001000000000100000001010001010101000101000100000001010100010100010101000100010001010001010101010000000001000001000000010000000001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010001", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010001", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010100", -! "04fd000101010001000100000000010100010000000100000000000100010000010001010000010001010101000000010001010000010101010100010100010101000100000100010101000101000101010100000000010101000101010000010001000000000101010000010001010000000000010001000100000001000100010101010100000001010101010101010100000001000000000000000001000000000000000001000101000001000001010000010000000101000101000000010100000100000001010101000001010101000001000000010101000001000100000100010100010101000000010001000000000100000100000000010100000100000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", -! "04fd000101010001000100000000010100010000000100000000000100010000010001010000010001010101000000010001010000010101010100010100010101000100000100010101000101000101010100000000010101000101010000010001000000000101010000010001010000000000010001000100000001000100010101010100000001010101010101010100000001000000000000000001000000000000000001000101000001000001010000010000000101000101000000010100000100000001010101000001010101000001000000010101000001000100000100010100010101000000010001000000000100000100000000010100000100000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", -! "04fd000101010001000100000000010100010000000100000000000100010000010001010000010001010101000000010001010000010101010100010100010101000100000100010101000101000101010100000000010101000101010000010001000000000101010000010001010000000000010001000100000001000100010101010100000001010101010101010100000001000000000000000001000000000000000001000101000001000001010000010000000101000101000000010100000100000001010101000001010101000001000000010101000001000100000100010100010101000000010001000000000100000100000000010100000100000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", -! "04fd000101010001000100000000010100010000000100000000000100010000010001010000010001010101000000010001010000010101010100010100010101000100000100010101000101000101010100000000010101000101010000010001000000000101010000010001010000000000010001000100000001000100010101010100000001010101010101010100000001000000000000000001000000000000000001000101000001000001010000010000000101000101000000010100000100000001010101000001010101000001000000010101000001000100000100010100010101000000010001000000000100000100000000010100000100000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", -! "04fd000101010001000100000000010100010000000100000000000100010000010001010000010001010101000000010001010000010101010100010100010101000100000100010101000101000101010100000000010101000101010000010001000000000101010000010001010000000000010001000100000001000100010101010100000001010101010101010100000001000000000000000001000000000000000001000101000001000001010000010000000101000101000000010100000100000001010101000001010101000001000000010101000001000100000100010100010101000000010001000000000100000100000000010100000100000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", -! "04fd000101010001000100000000010100010000000100000000000100010000010001010000010001010101000000010001010000010101010100010100010101000100000100010101000101000101010100000000010101000101010000010001000000000101010000010001010000000000010001000100000001000100010101010100000001010101010101010100000001000000000000000001000000000000000001000101000001000001010000010000000101000101000000010100000100000001010101000001010101000001000000010101000001000100000100010100010101000000010001000000000100000100000000010100000100000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010001", -! "04fd000101010001000100000000010100010000000100000000000100010000010001010000010001010101000000010001010000010101010100010100010101000100000100010101000101000101010100000000010101000101010000010001000000000101010000010001010000000000010001000100000001000100010101010100000001010101010101010100000001000000000000000001000000000000000001000101000001000001010000010000000101000101000000010100000100000001010101000001010101000001000000010101000001000100000100010100010101000000010001000000000100000100000000010100000100000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010100", -! "04fd000101010001000100000000010100010000000100000000000100010000010001010000010001010101000000010001010000010101010100010100010101000100000100010101000101000101010100000000010101000101010000010001000000000101010000010001010000000000010001000100000001000100010101010100000001010101010101010100000001000000000000000001000000000000000001000101000001000001010000010000000101000101000000010100000100000001010101000001010101000001000000010101000001000100000100010100010101000000010001000000000100000100000000010100000100000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010101", -! "04fd000101000101010001010100010100010001010101010100000101010000010101000001010001000100000000010101000101000101010001010001000101010001010001010000000100000101010000000000000101000001010001010101000001010000000000000101010101010001010101010000000000010000010000000000000001000101000001010100010100000001010001000000010000000000010101000101010000000001000000000100000000010101000101000001000000000100000000010100000001010101000100010101000001010001010101010001000000000000010001000000010101000100010000010000000001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", -! "04fd000101000101010001010100010100010001010101010100000101010000010101000001010001000100000000010101000101000101010001010001000101010001010001010000000100000101010000000000000101000001010001010101000001010000000000000101010101010001010101010000000000010000010000000000000001000101000001010100010100000001010001000000010000000000010101000101010000000001000000000100000000010101000101000001000000000100000000010100000001010101000100010101000001010001010101010001000000000000010001000000010101000100010000010000000001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", -! "04fd000101000101010001010100010100010001010101010100000101010000010101000001010001000100000000010101000101000101010001010001000101010001010001010000000100000101010000000000000101000001010001010101000001010000000000000101010101010001010101010000000000010000010000000000000001000101000001010100010100000001010001000000010000000000010101000101010000000001000000000100000000010101000101000001000000000100000000010100000001010101000100010101000001010001010101010001000000000000010001000000010101000100010000010000000001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", -! "04fd000101000101010001010100010100010001010101010100000101010000010101000001010001000100000000010101000101000101010001010001000101010001010001010000000100000101010000000000000101000001010001010101000001010000000000000101010101010001010101010000000000010000010000000000000001000101000001010100010100000001010001000000010000000000010101000101010000000001000000000100000000010101000101000001000000000100000000010100000001010101000100010101000001010001010101010001000000000000010001000000010101000100010000010000000001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", -! "04fd000101000101010001010100010100010001010101010100000101010000010101000001010001000100000000010101000101000101010001010001000101010001010001010000000100000101010000000000000101000001010001010101000001010000000000000101010101010001010101010000000000010000010000000000000001000101000001010100010100000001010001000000010000000000010101000101010000000001000000000100000000010101000101000001000000000100000000010100000001010101000100010101000001010001010101010001000000000000010001000000010101000100010000010000000001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", -! "04fd000101000101010001010100010100010001010101010100000101010000010101000001010001000100000000010101000101000101010001010001000101010001010001010000000100000101010000000000000101000001010001010101000001010000000000000101010101010001010101010000000000010000010000000000000001000101000001010100010100000001010001000000010000000000010101000101010000000001000000000100000000010101000101000001000000000100000000010100000001010101000100010101000001010001010101010001000000000000010001000000010101000100010000010000000001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010001", -! "04fd000101000101010001010100010100010001010101010100000101010000010101000001010001000100000000010101000101000101010001010001000101010001010001010000000100000101010000000000000101000001010001010101000001010000000000000101010101010001010101010000000000010000010000000000000001000101000001010100010100000001010001000000010000000000010101000101010000000001000000000100000000010101000101000001000000000100000000010100000001010101000100010101000001010001010101010001000000000000010001000000010101000100010000010000000001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010100", -! "04fd000101000101010001010100010100010001010101010100000101010000010101000001010001000100000000010101000101000101010001010001000101010001010001010000000100000101010000000000000101000001010001010101000001010000000000000101010101010001010101010000000000010000010000000000000001000101000001010100010100000001010001000000010000000000010101000101010000000001000000000100000000010101000101000001000000000100000000010100000001010101000100010101000001010001010101010001000000000000010001000000010101000100010000010000000001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010101", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000101010001010001000001000100010100010000010100000001000101010101000000000100010101010001010100000101000101000100000001010001000001000101000000010000000101000001010001000100010101010000010100000100010101000101010100000101010101010001010101010001010000010001000100000001010000010101000001000101010001000100000100000100000001010100000000000001010001000001000001010000000100000100000000010101000101010001000101010101010100010101010100000101010100010001000000000101000000000001010001010101000100010000010101000101000000fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000000", -! "04fd000100010100000101010000000000010101000000010001010100000001000100010000010101000101010000000101010001010101000000010000010000000100000101010101000100010001010001010001010101010001000000000001010000010000000001010000000000010001010001010000000100010101000101000001010001010101010100010100000101010000010101010000000000010001000000010100000101010101000100010100000001000101000001000101000101010000000100010100000100000101010000000100010000000100010001000101010001000000000001010001010100000000000100010100000000000001fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", -! "04fd000100010100000101010000000000010101000000010001010100000001000100010000010101000101010000000101010001010101000000010000010000000100000101010101000100010001010001010001010101010001000000000001010000010000000001010000000000010001010001010000000100010101000101000001010001010101010100010100000101010000010101010000000000010001000000010100000101010101000100010100000001000101000001000101000101010000000100010100000100000101010000000100010000000100010001000101010001000000000001010001010100000000000100010100000000000001fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", -! "04fd000100010100000101010000000000010101000000010001010100000001000100010000010101000101010000000101010001010101000000010000010000000100000101010101000100010001010001010001010101010001000000000001010000010000000001010000000000010001010001010000000100010101000101000001010001010101010100010100000101010000010101010000000000010001000000010100000101010101000100010100000001000101000001000101000101010000000100010100000100000101010000000100010000000100010001000101010001000000000001010001010100000000000100010100000000000001fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", -! "04fd000100010100000101010000000000010101000000010001010100000001000100010000010101000101010000000101010001010101000000010000010000000100000101010101000100010001010001010001010101010001000000000001010000010000000001010000000000010001010001010000000100010101000101000001010001010101010100010100000101010000010101010000000000010001000000010100000101010101000100010100000001000101000001000101000101010000000100010100000100000101010000000100010000000100010001000101010001000000000001010001010100000000000100010100000000000001fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", -! "04fd000100010100000101010000000000010101000000010001010100000001000100010000010101000101010000000101010001010101000000010000010000000100000101010101000100010001010001010001010101010001000000000001010000010000000001010000000000010001010001010000000100010101000101000001010001010101010100010100000101010000010101010000000000010001000000010100000101010101000100010100000001000101000001000101000101010000000100010100000100000101010000000100010000000100010001000101010001000000000001010001010100000000000100010100000000000001fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", -! "04fd000100010100000101010000000000010101000000010001010100000001000100010000010101000101010000000101010001010101000000010000010000000100000101010101000100010001010001010001010101010001000000000001010000010000000001010000000000010001010001010000000100010101000101000001010001010101010100010100000101010000010101010000000000010001000000010100000101010101000100010100000001000101000001000101000101010000000100010100000100000101010000000100010000000100010001000101010001000000000001010001010100000000000100010100000000000001fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010001", -! "04fd000100010100000101010000000000010101000000010001010100000001000100010000010101000101010000000101010001010101000000010000010000000100000101010101000100010001010001010001010101010001000000000001010000010000000001010000000000010001010001010000000100010101000101000001010001010101010100010100000101010000010101010000000000010001000000010100000101010101000100010100000001000101000001000101000101010000000100010100000100000101010000000100010000000100010001000101010001000000000001010001010100000000000100010100000000000001fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010100", -! "04fd000100010100000101010000000000010101000000010001010100000001000100010000010101000101010000000101010001010101000000010000010000000100000101010101000100010001010001010001010101010001000000000001010000010000000001010000000000010001010001010000000100010101000101000001010001010101010100010100000101010000010101010000000000010001000000010100000101010101000100010100000001000101000001000101000101010000000100010100000100000101010000000100010000000100010001000101010001000000000001010001010100000000000100010100000000000001fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010101", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000100000000000100010001000001010101000000000000000101010001010000000001000000010101010001010001010101010001010001000001000000010000010001000000010101000001000100010100010101010100000001000100000001010001010001000000000100010101000000000100000100010001010101010001000100000001010001010001000100010101010100010000010101010000010001010100000101010100010100000001010101010101000101000001010001000000000100000001010001010101000101000100000001010100010100010101000100010001010001010101010000000001000001000000010000000001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000000", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000100000000000100010001000001010101000000000000000101010001010000000001000000010101010001010001010101010001010001000001000000010000010001000000010101000001000100010100010101010100000001000100000001010001010001000000000100010101000000000100000100010001010101010001000100000001010001010001000100010101010100010000010101010000010001010100000101010100010100000001010101010101000101000001010001000000000100000001010001010101000101000100000001010100010100010101000100010001010001010101010000000001000001000000010000000001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000001", -! "04fd000101010100010100000001010000010101010101000100010101010100010101010101000001010001000101010001010000000100000101000101000101000100010001000100000001010100000101010001000000000000010000010101000000010000000001010001000000010100010000000000010100000000000000010000000000000001010100010100010100010101010100010001010000000001000101010000000001010001000000010000000001010000010101010001000100010001010101000000010100000101010100010000000001000101010001010001000000010000010101000000000000000101010000010101010100000001fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", -! "04fd000101010100010100000001010000010101010101000100010101010100010101010101000001010001000101010001010000000100000101000101000101000100010001000100000001010100000101010001000000000000010000010101000000010000000001010001000000010100010000000000010100000000000000010000000000000001010100010100010100010101010100010001010000000001000101010000000001010001000000010000000001010000010101010001000100010001010101000000010100000101010100010000000001000101010001010001000000010000010101000000000000000101010000010101010100000001fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", -! "04fd000101010100010100000001010000010101010101000100010101010100010101010101000001010001000101010001010000000100000101000101000101000100010001000100000001010100000101010001000000000000010000010101000000010000000001010001000000010100010000000000010100000000000000010000000000000001010100010100010100010101010100010001010000000001000101010000000001010001000000010000000001010000010101010001000100010001010101000000010100000101010100010000000001000101010001010001000000010000010101000000000000000101010000010101010100000001fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", -! "04fd000101010100010100000001010000010101010101000100010101010100010101010101000001010001000101010001010000000100000101000101000101000100010001000100000001010100000101010001000000000000010000010101000000010000000001010001000000010100010000000000010100000000000000010000000000000001010100010100010100010101010100010001010000000001000101010000000001010001000000010000000001010000010101010001000100010001010101000000010100000101010100010000000001000101010001010001000000010000010101000000000000000101010000010101010100000001fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", -! "04fd000101010100010100000001010000010101010101000100010101010100010101010101000001010001000101010001010000000100000101000101000101000100010001000100000001010100000101010001000000000000010000010101000000010000000001010001000000010100010000000000010100000000000000010000000000000001010100010100010100010101010100010001010000000001000101010000000001010001000000010000000001010000010101010001000100010001010101000000010100000101010100010000000001000101010001010001000000010000010101000000000000000101010000010101010100000001fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", -! "04fd000101010100010100000001010000010101010101000100010101010100010101010101000001010001000101010001010000000100000101000101000101000100010001000100000001010100000101010001000000000000010000010101000000010000000001010001000000010100010000000000010100000000000000010000000000000001010100010100010100010101010100010001010000000001000101010000000001010001000000010000000001010000010101010001000100010001010101000000010100000101010100010000000001000101010001010001000000010000010101000000000000000101010000010101010100000001fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010001", -! "04fd000101010100010100000001010000010101010101000100010101010100010101010101000001010001000101010001010000000100000101000101000101000100010001000100000001010100000101010001000000000000010000010101000000010000000001010001000000010100010000000000010100000000000000010000000000000001010100010100010100010101010100010001010000000001000101010000000001010001000000010000000001010000010101010001000100010001010101000000010100000101010100010000000001000101010001010001000000010000010101000000000000000101010000010101010100000001fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010100", -! "04fd000101010100010100000001010000010101010101000100010101010100010101010101000001010001000101010001010000000100000101000101000101000100010001000100000001010100000101010001000000000000010000010101000000010000000001010001000000010100010000000000010100000000000000010000000000000001010100010100010100010101010100010001010000000001000101010000000001010001000000010000000001010000010101010001000100010001010101000000010100000101010100010000000001000101010001010001000000010000010101000000000000000101010000010101010100000001fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010101", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000000", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000001", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000100", -! "04fd000100010000010100000001010100010101010000010000010001010100000000010100010001000100010001010001000000000000010000000001000000000100000101000000000001010101000100000000010101000101000001000001000000010101010100000100010000010101010101010001000100000101010001010001000000010001000000010000010000010100010001010001000101010101010000000100010100000100000101010000010001010100000100000100000101000001000101010100000000000000000000010000000101010000010001010000000101000001010001010001010000010000010101000101000000000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", -! "04fd000100010000010100000001010100010101010000010000010001010100000000010100010001000100010001010001000000000000010000000001000000000100000101000000000001010101000100000000010101000101000001000001000000010101010100000100010000010101010101010001000100000101010001010001000000010001000000010000010000010100010001010001000101010101010000000100010100000100000101010000010001010100000100000100000101000001000101010100000000000000000000010000000101010000010001010000000101000001010001010001010000010000010101000101000000000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", -! "04fd000100010000010100000001010100010101010000010000010001010100000000010100010001000100010001010001000000000000010000000001000000000100000101000000000001010101000100000000010101000101000001000001000000010101010100000100010000010101010101010001000100000101010001010001000000010001000000010000010000010100010001010001000101010101010000000100010100000100000101010000010001010100000100000100000101000001000101010100000000000000000000010000000101010000010001010000000101000001010001010001010000010000010101000101000000000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", -! "04fd000100010000010100000001010100010101010000010000010001010100000000010100010001000100010001010001000000000000010000000001000000000100000101000000000001010101000100000000010101000101000001000001000000010101010100000100010000010101010101010001000100000101010001010001000000010001000000010000010000010100010001010001000101010101010000000100010100000100000101010000010001010100000100000100000101000001000101010100000000000000000000010000000101010000010001010000000101000001010001010001010000010000010101000101000000000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", -! "04fd000100010000010100000001010100010101010000010000010001010100000000010100010001000100010001010001000000000000010000000001000000000100000101000000000001010101000100000000010101000101000001000001000000010101010100000100010000010101010101010001000100000101010001010001000000010001000000010000010000010100010001010001000101010101010000000100010100000100000101010000010001010100000100000100000101000001000101010100000000000000000000010000000101010000010001010000000101000001010001010001010000010000010101000101000000000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", -! "04fd000100010000010100000001010100010101010000010000010001010100000000010100010001000100010001010001000000000000010000000001000000000100000101000000000001010101000100000000010101000101000001000001000000010101010100000100010000010101010101010001000100000101010001010001000000010001000000010000010000010100010001010001000101010101010000000100010100000100000101010000010001010100000100000100000101000001000101010100000000000000000000010000000101010000010001010000000101000001010001010001010000010000010101000101000000000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010001", -! "04fd000100010000010100000001010100010101010000010000010001010100000000010100010001000100010001010001000000000000010000000001000000000100000101000000000001010101000100000000010101000101000001000001000000010101010100000100010000010101010101010001000100000101010001010001000000010001000000010000010000010100010001010001000101010101010000000100010100000100000101010000010001010100000100000100000101000001000101010100000000000000000000010000000101010000010001010000000101000001010001010001010000010000010101000101000000000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010100", -! "04fd000100010000010100000001010100010101010000010000010001010100000000010100010001000100010001010001000000000000010000000001000000000100000101000000000001010101000100000000010101000101000001000001000000010101010100000100010000010101010101010001000100000101010001010001000000010001000000010000010000010100010001010001000101010101010000000100010100000100000101010000010001010100000100000100000101000001000101010100000000000000000000010000000101010000010001010000000101000001010001010001010000010000010101000101000000000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010101", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100000001000101000101010100000000000001000000000001000100000000010000010001000100010000000100010101010000000000010001010001000001010001010100000001000001010101010100000001010000000000000000000101000000010100000000000001010100010001010100010101000000010000010001010000000001000100000101000100010100000001000001000001000100010000000001000001010000010101000100010000000001010100010101010000010001000000010000000100010100010100010100010100000101010001010101010000010000000100000001000101010000010001000001010000000001fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000000", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100000001000101000101010100000000000001000000000001000100000000010000010001000100010000000100010101010000000000010001010001000001010001010100000001000001010101010100000001010000000000000000000101000000010100000000000001010100010001010100010101000000010000010001010000000001000100000101000100010100000001000001000001000100010000000001000001010000010101000100010000000001010100010101010000010001000000010000000100010100010100010100010100000101010001010101010000010000000100000001000101010000010001000001010000000001fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000001", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100000001000101000101010100000000000001000000000001000100000000010000010001000100010000000100010101010000000000010001010001000001010001010100000001000001010101010100000001010000000000000000000101000000010100000000000001010100010001010100010101000000010000010001010000000001000100000101000100010100000001000001000001000100010000000001000001010000010101000100010000000001010100010101010000010001000000010000000100010100010100010100010100000101010001010101010000010000000100000001000101010000010001000001010000000001fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000100", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100000001000101000101010100000000000001000000000001000100000000010000010001000100010000000100010101010000000000010001010001000001010001010100000001000001010101010100000001010000000000000000000101000000010100000000000001010100010001010100010101000000010000010001010000000001000100000101000100010100000001000001000001000100010000000001000001010000010101000100010000000001010100010101010000010001000000010000000100010100010100010100010100000101010001010101010000010000000100000001000101010000010001000001010000000001fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000101", -! "04fd000100010000000001010001010001000000000100000001010100010001000000010101010000010000000000010101010000010101000101010101000101010001000100000001000000000001010101000100000100000101000000010101000100010000000101010101000000000100000000010000000101010000010100000001000000010001000000000000010000010100010101010101000001000100000000010100000101010100010000000000010101010100000001000001000100010001000000010001000000010001010100000101010101010000000001000100000001000100000000000000010100010001000101000001000001010100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", -! "04fd000100010000000001010001010001000000000100000001010100010001000000010101010000010000000000010101010000010101000101010101000101010001000100000001000000000001010101000100000100000101000000010101000100010000000101010101000000000100000000010000000101010000010100000001000000010001000000000000010000010100010101010101000001000100000000010100000101010100010000000000010101010100000001000001000100010001000000010001000000010001010100000101010101010000000001000100000001000100000000000000010100010001000101000001000001010100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", -! "04fd000100010000000001010001010001000000000100000001010100010001000000010101010000010000000000010101010000010101000101010101000101010001000100000001000000000001010101000100000100000101000000010101000100010000000101010101000000000100000000010000000101010000010100000001000000010001000000000000010000010100010101010101000001000100000000010100000101010100010000000000010101010100000001000001000100010001000000010001000000010001010100000101010101010000000001000100000001000100000000000000010100010001000101000001000001010100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", -! "04fd000100010000000001010001010001000000000100000001010100010001000000010101010000010000000000010101010000010101000101010101000101010001000100000001000000000001010101000100000100000101000000010101000100010000000101010101000000000100000000010000000101010000010100000001000000010001000000000000010000010100010101010101000001000100000000010100000101010100010000000000010101010100000001000001000100010001000000010001000000010001010100000101010101010000000001000100000001000100000000000000010100010001000101000001000001010100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", -! "04fd000100010000000001010001010001000000000100000001010100010001000000010101010000010000000000010101010000010101000101010101000101010001000100000001000000000001010101000100000100000101000000010101000100010000000101010101000000000100000000010000000101010000010100000001000000010001000000000000010000010100010101010101000001000100000000010100000101010100010000000000010101010100000001000001000100010001000000010001000000010001010100000101010101010000000001000100000001000100000000000000010100010001000101000001000001010100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", -! "04fd000100010000000001010001010001000000000100000001010100010001000000010101010000010000000000010101010000010101000101010101000101010001000100000001000000000001010101000100000100000101000000010101000100010000000101010101000000000100000000010000000101010000010100000001000000010001000000000000010000010100010101010101000001000100000000010100000101010100010000000000010101010100000001000001000100010001000000010001000000010001010100000101010101010000000001000100000001000100000000000000010100010001000101000001000001010100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010001", -! "04fd000100010000000001010001010001000000000100000001010100010001000000010101010000010000000000010101010000010101000101010101000101010001000100000001000000000001010101000100000100000101000000010101000100010000000101010101000000000100000000010000000101010000010100000001000000010001000000000000010000010100010101010101000001000100000000010100000101010100010000000000010101010100000001000001000100010001000000010001000000010001010100000101010101010000000001000100000001000100000000000000010100010001000101000001000001010100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010100", -! "04fd000100010000000001010001010001000000000100000001010100010001000000010101010000010000000000010101010000010101000101010101000101010001000100000001000000000001010101000100000100000101000000010101000100010000000101010101000000000100000000010000000101010000010100000001000000010001000000000000010000010100010101010101000001000100000000010100000101010100010000000000010101010100000001000001000100010001000000010001000000010001010100000101010101010000000001000100000001000100000000000000010100010001000101000001000001010100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010101", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010000010000010100010101000100010000000001010100000001000100010000010100000000010100000000010000010100000001000100010000000000010001000100000101000101000101010101000001000100000101000000000101000101000101000101000001010101010001010000000101000001000101010000010001010001000000000001000001000100000000010001010100000101000000010001010000000100010000000001000001010001000001000100010001010000010101010001010101010000000100010100010001000000000001000000010101000001010001000001000001010100000101010000010101fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000000", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010000010000010100010101000100010000000001010100000001000100010000010100000000010100000000010000010100000001000100010000000000010001000100000101000101000101010101000001000100000101000000000101000101000101000101000001010101010001010000000101000001000101010000010001010001000000000001000001000100000000010001010100000101000000010001010000000100010000000001000001010001000001000100010001010000010101010001010101010000000100010100010001000000000001000000010101000001010001000001000001010100000101010000010101fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000001", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010000010000010100010101000100010000000001010100000001000100010000010100000000010100000000010000010100000001000100010000000000010001000100000101000101000101010101000001000100000101000000000101000101000101000101000001010101010001010000000101000001000101010000010001010001000000000001000001000100000000010001010100000101000000010001010000000100010000000001000001010001000001000100010001010000010101010001010101010000000100010100010001000000000001000000010101000001010001000001000001010100000101010000010101fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000100", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010000010000010100010101000100010000000001010100000001000100010000010100000000010100000000010000010100000001000100010000000000010001000100000101000101000101010101000001000100000101000000000101000101000101000101000001010101010001010000000101000001000101010000010001010001000000000001000001000100000000010001010100000101000000010001010000000100010000000001000001010001000001000100010001010000010101010001010101010000000100010100010001000000000001000000010101000001010001000001000001010100000101010000010101fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000101", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101010001010001000001000100010100010000010100000001000101010101000000000100010101010001010100000101000101000100000001010001000001000101000000010000000101000001010001000100010101010000010100000100010101000101010100000101010101010001010101010001010000010001000100000001010000010101000001000101010001000100000100000100000001010100000000000001010001000001000001010000000100000100000000010101000101010001000101010101010100010101010100000101010100010001000000000101000000000001010001010101000100010000010101000101000000fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401010000", -! "04fd000101000000000101000100000101010000010000000101010000010100010101010000000101010001010101000101000100000001010000000001010000010001010001000100010000010001000001010000010000010100010101000101010001010101000000010100010000000100000001000000010101000101010101000101000000000001000000000001010100010000010100000101010101000101000100010001000000000000000001000001010101010100000001000100000101000001010101010001010100000001000000010100000101000101010101000001000001000101010100010001010100010000010100010001010001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", -! "04fd000101000000000101000100000101010000010000000101010000010100010101010000000101010001010101000101000100000001010000000001010000010001010001000100010000010001000001010000010000010100010101000101010001010101000000010100010000000100000001000000010101000101010101000101000000000001000000000001010100010000010100000101010101000101000100010001000000000000000001000001010101010100000001000100000101000001010101010001010100000001000000010100000101000101010101000001000001000101010100010001010100010000010100010001010001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", -! "04fd000101000000000101000100000101010000010000000101010000010100010101010000000101010001010101000101000100000001010000000001010000010001010001000100010000010001000001010000010000010100010101000101010001010101000000010100010000000100000001000000010101000101010101000101000000000001000000000001010100010000010100000101010101000101000100010001000000000000000001000001010101010100000001000100000101000001010101010001010100000001000000010100000101000101010101000001000001000101010100010001010100010000010100010001010001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", -! "04fd000101000000000101000100000101010000010000000101010000010100010101010000000101010001010101000101000100000001010000000001010000010001010001000100010000010001000001010000010000010100010101000101010001010101000000010100010000000100000001000000010101000101010101000101000000000001000000000001010100010000010100000101010101000101000100010001000000000000000001000001010101010100000001000100000101000001010101010001010100000001000000010100000101000101010101000001000001000101010100010001010100010000010100010001010001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", -! "04fd000101000000000101000100000101010000010000000101010000010100010101010000000101010001010101000101000100000001010000000001010000010001010001000100010000010001000001010000010000010100010101000101010001010101000000010100010000000100000001000000010101000101010101000101000000000001000000000001010100010000010100000101010101000101000100010001000000000000000001000001010101010100000001000100000101000001010101010001010100000001000000010100000101000101010101000001000001000101010100010001010100010000010100010001010001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", -! "04fd000101000000000101000100000101010000010000000101010000010100010101010000000101010001010101000101000100000001010000000001010000010001010001000100010000010001000001010000010000010100010101000101010001010101000000010100010000000100000001000000010101000101010101000101000000000001000000000001010100010000010100000101010101000101000100010001000000000000000001000001010101010100000001000100000101000001010101010001010100000001000000010100000101000101010101000001000001000101010100010001010100010000010100010001010001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010001", -! "04fd000101000000000101000100000101010000010000000101010000010100010101010000000101010001010101000101000100000001010000000001010000010001010001000100010000010001000001010000010000010100010101000101010001010101000000010100010000000100000001000000010101000101010101000101000000000001000000000001010100010000010100000101010101000101000100010001000000000000000001000001010101010100000001000100000101000001010101010001010100000001000000010100000101000101010101000001000001000101010100010001010100010000010100010001010001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010100", -! "04fd000101000000000101000100000101010000010000000101010000010100010101010000000101010001010101000101000100000001010000000001010000010001010001000100010000010001000001010000010000010100010101000101010001010101000000010100010000000100000001000000010101000101010101000101000000000001000000000001010100010000010100000101010101000101000100010001000000000000000001000001010101010100000001000100000101000001010101010001010100000001000000010100000101000101010101000001000001000101010100010001010100010000010100010001010001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010101", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100010101010001010000010001000000010100000001010100000000010001000000000101010101000001000100010100010000010001010001010101010000010101000101010100010001000000010100000001010100010001000000000100000101010001000000000100010100000001010000010001000000000000010101000000010101010001000101010101010100010100000000010100010101000101000100010101000000010101000000010101000001000001000101010000000101010000000000000001010101010001010001010100010000000001010100000101000000000101010001010100000101000101010000010000000100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000000", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100010101010001010000010001000000010100000001010100000000010001000000000101010101000001000100010100010000010001010001010101010000010101000101010100010001000000010100000001010100010001000000000100000101010001000000000100010100000001010000010001000000000000010101000000010101010001000101010101010100010100000000010100010101000101000100010101000000010101000000010101000001000001000101010000000101010000000000000001010101010001010001010100010000000001010100000101000000000101010001010100000101000101010000010000000100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000001", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100010101010001010000010001000000010100000001010100000000010001000000000101010101000001000100010100010000010001010001010101010000010101000101010100010001000000010100000001010100010001000000000100000101010001000000000100010100000001010000010001000000000000010101000000010101010001000101010101010100010100000000010100010101000101000100010101000000010101000000010101000001000001000101010000000101010000000000000001010101010001010001010100010000000001010100000101000000000101010001010100000101000101010000010000000100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000100", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100010101010001010000010001000000010100000001010100000000010001000000000101010101000001000100010100010000010001010001010101010000010101000101010100010001000000010100000001010100010001000000000100000101010001000000000100010100000001010000010001000000000000010101000000010101010001000101010101010100010100000000010100010101000101000100010101000000010101000000010101000001000001000101010000000101010000000000000001010101010001010001010100010000000001010100000101000000000101010001010100000101000101010000010000000100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000101", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000100000000000100010001000001010101000000000000000101010001010000000001000000010101010001010001010101010001010001000001000000010000010001000000010101000001000100010100010101010100000001000100000001010001010001000000000100010101000000000100000100010001010101010001000100000001010001010001000100010101010100010000010101010000010001010100000101010100010100000001010101010101000101000001010001000000000100000001010001010101000101000100000001010100010100010101000100010001010001010101010000000001000001000000010000000001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401010000", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000100000000000100010001000001010101000000000000000101010001010000000001000000010101010001010001010101010001010001000001000000010000010001000000010101000001000100010100010101010100000001000100000001010001010001000000000100010101000000000100000100010001010101010001000100000001010001010001000100010101010100010000010101010000010001010100000101010100010100000001010101010101000101000001010001000000000100000001010001010101000101000100000001010100010100010101000100010001010001010101010000000001000001000000010000000001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401010001", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010001", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010100", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010101", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000000", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000001", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000100", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000101", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401010000", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401010001", -! "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401010100" -! - ] ---- 1,122 ---- - [ -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000101010001010001000001000100010100010000010100000001000101010101000000000100010101010001010100000101000101000100000001010001000001000101000000010000000101000001010001000100010101010000010100000100010101000101010100000101010101010001010101010001010000010001000100000001010000010101000001000101010001000100000100000100000001010100000000000001010001000001000001010000000100000100000000010101000101010001000101010101010100010101010100000101010100010001000000000101000000000001010001010101000100010000010101000101000000fd0001000101000100000001010100010001010000010100010001010001010101000000010001010101000000000101010001010100010100010101000000000000000100010000010101000101000000000100010101000000010100000001010100000101000000010101000100000000010101010001010000010101010001000001010001000100000100000100010101000101010100010001010100000001000000010001010000010100000000000101000001010101010100010000010101000001010000010001000101010000000001000100010001000000010001000101000101000001000100010000010000010100000100000100010000000001010400000000", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000100000100010000010101010000010001000001000001000100000001010101010001000001000100000001000001000100010100010101000100000001000000010001000100000001000001010000010001000001010101010101010100000100000101010000000101000100010100000100000101010001000100010101000000010001000001010000010001000101010101000001010101000001010101000001000100000101000101010000000000010001010000010101010000010000000100010000010101000000000001000001000001010001010101010001010001000101010001000000000101000000000100010100000000010000000000fd0001000101000100000001010100010001010000010100010001010001010101000000010001010101000000000101010001010100010100010101000000000000000100010000010101000101000000000100010101000000010100000001010100000101000000010101000100000000010101010001010000010101010001000001010001000100000100000100010101000101010100010001010100000001000000010001010000010100000000000101000001010101010100010000010101000001010000010001000101010000000001000100010001000000010001000101000101000001000100010000010000010100000100000100010000000001010400000000", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000100000100010000010101010000010001000001000001000100000001010101010001000001000100000001000001000100010100010101000100000001000000010001000100000001000001010000010001000001010101010101010100000100000101010000000101000100010100000100000101010001000100010101000000010001000001010000010001000101010101000001010101000001010101000001000100000101000101010000000000010001010000010101010000010000000100010000010101000000000001000001000001010001010101010001010001000101010001000000000101000000000100010100000000010000000000fd0001000101000000010001010101010100010100010001010001010000010100010101010101010001010101010100000001000101010101000000000101010000000101010001000100000101000000010000010100010001000100000101010000010000010100010101000000010001000101010101000000010001000001010100010000010000000101010000010100010001010001000000000101000101000001010101010000010000000001000001000001000100000101000001000100010101010000000001010000010001000001000101000001000001000100000101000001010000010101010001000000010001010001010001000101010001000400000001", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000100000001010100010001010000010100010001010001010101000000010001010101000000000101010001010100010100010101000000000000000100010000010101000101000000000100010101000000010100000001010100000101000000010101000100000000010101010001010000010101010001000001010001000100000100000100010101000101010100010001010100000001000000010001010000010100000000000101000001010101010100010000010101000001010000010001000101010000000001000100010001000000010001000101000101000001000100010000010000010100000100000100010000000001010400000000", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000000010001010101010100010100010001010001010000010100010101010101010001010101010100000001000101010101000000000101010000000101010001000100000101000000010000010100010001000100000101010000010000010100010101000000010001000101010101000000010001000001010100010000010000000101010000010100010001010001000000000101000101000001010101010000010000000001000001000001000100000101000001000100010101010000000001010000010001000001000101000001000001000100000101000001010000010101010001000000010001010001010001000101010001000400000001", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000010000010000010000010000010100000001000100010000000000010001000001000100010101010001000100000001010001010001010001000100010100000100000101010101000100010001010100010101000001010101010000010001010100000001000101000100010001000101000101010101000000010101000100000001010101010000000101000101010100010101000000000000010100000000010001010100010000010101000000000000000001010100010100010000010000010100000001010000000001000000000000000100010001000001010000010100010001000100010101000100000100010001010100000100000400000100", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010000000000010100000001000100000100010100010000010001010000000101010101010101010100000000000000010101010100010001000101000001000001010001000101010100000000010000010001010001010101010100010001000100010001010001000100010101000000000000010001000100000100000000000001000100000101000100000101010101010000010100000001010100000001000000010100010100010000010100010100000001010001000100010000000101010000010101010000010101000100010000010001010101000001010101000100000001010000010101000001010101000100000001000100010000fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000100000001010100010001010000010100010001010001010101000000010001010101000000000101010001010100010100010101000000000000000100010000010101000101000000000100010101000000010100000001010100000101000000010101000100000000010101010001010000010101010001000001010001000100000100000100010101000101010100010001010100000001000000010001010000010100000000000101000001010101010100010000010101000001010000010001000101010000000001000100010001000000010001000101000101000001000100010000010000010100000100000100010000000001010400000000", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010000000000010100000001000100000100010100010000010001010000000101010101010101010100000000000000010101010100010001000101000001000001010001000101010100000000010000010001010001010101010100010001000100010001010001000100010101000000000000010001000100000100000000000001000100000101000100000101010101010000010100000001010100000001000000010100010100010000010100010100000001010001000100010000000101010000010101010000010101000100010000010001010101000001010101000100000001010000010101000001010101000100000001000100010000fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000000010001010101010100010100010001010001010000010100010101010101010001010101010100000001000101010101000000000101010000000101010001000100000101000000010000010100010001000100000101010000010000010100010101000000010001000101010101000000010001000001010100010000010000000101010000010100010001010001000000000101000101000001010101010000010000000001000001000001000100000101000001000100010101010000000001010000010001000001000101000001000001000100000101000001010000010101010001000000010001010001010001000101010001000400000001", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010000000000010100000001000100000100010100010000010001010000000101010101010101010100000000000000010101010100010001000101000001000001010001000101010100000000010000010001010001010101010100010001000100010001010001000100010101000000000000010001000100000100000000000001000100000101000100000101010101010000010100000001010100000001000000010100010100010000010100010100000001010001000100010000000101010000010101010000010101000100010000010001010101000001010101000100000001010000010101000001010101000100000001000100010000fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000010000010000010000010000010100000001000100010000000000010001000001000100010101010001000100000001010001010001010001000100010100000100000101010101000100010001010100010101000001010101010000010001010100000001000101000100010001000101000101010101000000010101000100000001010101010000000101000101010100010101000000000000010100000000010001010100010000010101000000000000000001010100010100010000010000010100000001010000000001000000000000000100010001000001010000010100010001000100010101000100000100010001010100000100000400000100", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101010000000000010100000001000100000100010100010000010001010000000101010101010101010100000000000000010101010100010001000101000001000001010001000101010100000000010000010001010001010101010100010001000100010001010001000100010101000000000000010001000100000100000000000001000100000101000100000101010101010000010100000001010100000001000000010100010100010000010100010100000001010001000100010000000101010000010101010000010101000100010000010001010101000001010101000100000001010000010101000001010101000100000001000100010000fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000000000010100010100000000000001000000010001000100000100000000010000000000000001010100010101010100000101010100010100000001010100000100000000000000010100000000010000010101000100010000010101010100000101000100010000010000000100010100010000000101000000000001010100000001000101000100000000010101010000010000000100010001010000010000000100010000010000010101000101000101000100000100010100000001010000010101000101010001010000000100010001000001000000010100000001000100000100010000010100010000010000010001010101010001010400000101", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101000001000100010101010100000001000101000001000001010100000001010100010001000001000101000001010100010001010000010000010100010101010001000000000001010101000101010001010000010001010101010101000001000001010101000101010100010001000000010001010100010000010001010101010001000000000000000101000101000101000101010001010000010101000101010100010100000001010001000000000101010000010000010101000000010100010101000101000001000001000001000000000100000000000001000001000100000100000000010100000100010000010101010000010001010101fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000100000001010100010001010000010100010001010001010101000000010001010101000000000101010001010100010100010101000000000000000100010000010101000101000000000100010101000000010100000001010100000101000000010101000100000000010101010001010000010101010001000001010001000100000100000100010101000101010100010001010100000001000000010001010000010100000000000101000001010101010100010000010101000001010000010001000101010000000001000100010001000000010001000101000101000001000100010000010000010100000100000100010000000001010400000000", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101000001000100010101010100000001000101000001000001010100000001010100010001000001000101000001010100010001010000010000010100010101010001000000000001010101000101010001010000010001010101010101000001000001010101000101010100010001000000010001010100010000010001010101010001000000000000000101000101000101000101010001010000010101000101010100010100000001010001000000000101010000010000010101000000010100010101000101000001000001000001000000000100000000000001000001000100000100000000010100000100010000010101010000010001010101fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000000010001010101010100010100010001010001010000010100010101010101010001010101010100000001000101010101000000000101010000000101010001000100000101000000010000010100010001000100000101010000010000010100010101000000010001000101010101000000010001000001010100010000010000000101010000010100010001010001000000000101000101000001010101010000010000000001000001000001000100000101000001000100010101010000000001010000010001000001000101000001000001000100000101000001010000010101010001000000010001010001010001000101010001000400000001", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101000001000100010101010100000001000101000001000001010100000001010100010001000001000101000001010100010001010000010000010100010101010001000000000001010101000101010001010000010001010101010101000001000001010101000101010100010001000000010001010100010000010001010101010001000000000000000101000101000101000101010001010000010101000101010100010100000001010001000000000101010000010000010101000000010100010101000101000001000001000001000000000100000000000001000001000100000100000000010100000100010000010101010000010001010101fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000010000010000010000010000010100000001000100010000000000010001000001000100010101010001000100000001010001010001010001000100010100000100000101010101000100010001010100010101000001010101010000010001010100000001000101000100010001000101000101010101000000010101000100000001010101010000000101000101010100010101000000000000010100000000010001010100010000010101000000000000000001010100010100010000010000010100000001010000000001000000000000000100010001000001010000010100010001000100010101000100000100010001010100000100000400000100", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000101000001000100010101010100000001000101000001000001010100000001010100010001000001000101000001010100010001010000010000010100010101010001000000000001010101000101010001010000010001010101010101000001000001010101000101010100010001000000010001010100010000010001010101010001000000000000000101000101000101000101010001010000010101000101010100010100000001010001000000000101010000010000010101000000010100010101000101000001000001000001000000000100000000000001000001000100000100000000010100000100010000010101010000010001010101fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000000000010100010100000000000001000000010001000100000100000000010000000000000001010100010101010100000101010100010100000001010100000100000000000000010100000000010000010101000100010000010101010100000101000100010000010000000100010100010000000101000000000001010100000001000101000100000000010101010000010000000100010001010000010000000100010000010000010101000101000101000100000100010100000001010000010101000101010001010000000100010001000001000000010100000001000100000100010000010100010000010000010001010101010001010400000101", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000101010001010001000001000100010100010000010100000001000101010101000000000100010101010001010100000101000101000100000001010001000001000101000000010000000101000001010001000100010101010000010100000100010101000101010100000101010101010001010101010001010000010001000100000001010000010101000001000101010001000100000100000100000001010100000000000001010001000001000001010000000100000100000000010101000101010001000101010101010100010101010100000101010100010001000000000101000000000001010001010101000100010000010101000101000000fd0001000101000100000001010000000100000101000100000000010101010001010001000001010100010000000101010101000000010100000001000101000101010001000100010100010100000000010001010100010101000100000000010101000100010101000000000001000100000101010100000001010100000001010001010000010100010000010101000000000101000100000000000100010101000001010100000001000100010101000101010100010100010000000100010000010001010101010100010101010101000000010101010000000000010101000000010001000101000000000100000000010101000100000101010101010100000400010000", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100000100010100010000010001000001010100000000010100010000000001000000010100010101010101000000010001010000000100000001000001010101000101000101000001010000010101000000010001000100000101000100000100010100010101010101010001010000010001010100010100000101000001010001000101000000000100010000000000000000000001010000000000010000000001010000000000010000000001010101010100010101010001000101010000010000000000010000010100000100010100010001010100000101000001000001000101000101010001000000000100010000000100000000010001010100fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000100000001010100010001010000010100010001010001010101000000010001010101000000000101010001010100010100010101000000000000000100010000010101000101000000000100010101000000010100000001010100000101000000010101000100000000010101010001010000010101010001000001010001000100000100000100010101000101010100010001010100000001000000010001010000010100000000000101000001010101010100010000010101000001010000010001000101010000000001000100010001000000010001000101000101000001000100010000010000010100000100000100010000000001010400000000", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100000100010100010000010001000001010100000000010100010000000001000000010100010101010101000000010001010000000100000001000001010101000101000101000001010000010101000000010001000100000101000100000100010100010101010101010001010000010001010100010100000101000001010001000101000000000100010000000000000000000001010000000000010000000001010000000000010000000001010101010100010101010001000101010000010000000000010000010100000100010100010001010100000101000001000001000101000101010001000000000100010000000100000000010001010100fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000000010001010101010100010100010001010001010000010100010101010101010001010101010100000001000101010101000000000101010000000101010001000100000101000000010000010100010001000100000101010000010000010100010101000000010001000101010101000000010001000001010100010000010000000101010000010100010001010001000000000101000101000001010101010000010000000001000001000001000100000101000001000100010101010000000001010000010001000001000101000001000001000100000101000001010000010101010001000000010001010001010001000101010001000400000001", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100000100010100010000010001000001010100000000010100010000000001000000010100010101010101000000010001010000000100000001000001010101000101000101000001010000010101000000010001000100000101000100000100010100010101010101010001010000010001010100010100000101000001010001000101000000000100010000000000000000000001010000000000010000000001010000000000010000000001010101010100010101010001000101010000010000000000010000010100000100010100010001010100000101000001000001000101000101010001000000000100010000000100000000010001010100fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000010000010000010000010000010100000001000100010000000000010001000001000100010101010001000100000001010001010001010001000100010100000100000101010101000100010001010100010101000001010101010000010001010100000001000101000100010001000101000101010101000000010101000100000001010101010000000101000101010100010101000000000000010100000000010001010100010000010101000000000000000001010100010100010000010000010100000001010000000001000000000000000100010001000001010000010100010001000100010101000100000100010001010100000100000400000100", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100000100010100010000010001000001010100000000010100010000000001000000010100010101010101000000010001010000000100000001000001010101000101000101000001010000010101000000010001000100000101000100000100010100010101010101010001010000010001010100010100000101000001010001000101000000000100010000000000000000000001010000000000010000000001010000000000010000000001010101010100010101010001000101010000010000000000010000010100000100010100010001010100000101000001000001000101000101010001000000000100010000000100000000010001010100fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000000000010100010100000000000001000000010001000100000100000000010000000000000001010100010101010100000101010100010100000001010100000100000000000000010100000000010000010101000100010000010101010100000101000100010000010000000100010100010000000101000000000001010100000001000101000100000000010101010000010000000100010001010000010000000100010000010000010101000101000101000100000100010100000001010000010101000101010001010000000100010001000001000000010100000001000100000100010000010100010000010000010001010101010001010400000101", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000101010001010001000101000100000101000000010101000100010101010001000101000000000000010100000000010001010100000000010001010101010100010101010101010101010001000001000000010100000101010100010001010000010000010001010001010101000101000101010000010000010100000100000001010101000100010000000101010000000100000000000000000101010101010100000100010100000101000001000101000101000101010000010100010101010000010101010101010000010100000101000001010001000101010101000101010001010101000101010001000000010100000100010001010000010001fd0001000101000100000001010000000100000101000100000000010101010001010001000001010100010000000101010101000000010100000001000101000101010001000100010100010100000000010001010100010101000100000000010101000100010101000000000001000100000101010100000001010100000001010001010000010100010000010101000000000101000100000000000100010101000001010100000001000100010101000101010100010100010000000100010000010001010101010100010101010101000000010101010000000000010101000000010001000101000000000100000000010101000100000101010101010100000400010000", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000101010001010001000101000100000101000000010101000100010101010001000101000000000000010100000000010001010100000000010001010101010100010101010101010101010001000001000000010100000101010100010001010000010000010001010001010101000101000101010000010000010100000100000001010101000100010000000101010000000100000000000000000101010101010100000100010100000101000001000101000101000101010000010100010101010000010101010101010000010100000101000001010001000101010101000101010001010101000101010001000000010100000100010001010000010001fd0001010101010101010100010101010100000000010100010100000000000000010100010101000100000100010000010100000100010000000001000000010001000101010000000000010000010000000000010000010100000001010101000000000001000000000100000100000101010101010101010101000100010101000101010000010101000100000100000000010000010000000101000000010101010000010101010100010101000100000000000001010100000101010101000001000001000101010001010101000000010100010100010100010000010100010001010101010001010100000001000101010101010001000000010000000001010400010001", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000100000001010100010001010000010100010001010001010101000000010001010101000000000101010001010100010100010101000000000000000100010000010101000101000000000100010101000000010100000001010100000101000000010101000100000000010101010001010000010101010001000001010001000100000100000100010101000101010100010001010100000001000000010001010000010100000000000101000001010101010100010000010101000001010000010001000101010000000001000100010001000000010001000101000101000001000100010000010000010100000100000100010000000001010400000000", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000000010001010101010100010100010001010001010000010100010101010101010001010101010100000001000101010101000000000101010000000101010001000100000101000000010000010100010001000100000101010000010000010100010101000000010001000101010101000000010001000001010100010000010000000101010000010100010001010001000000000101000101000001010101010000010000000001000001000001000100000101000001000100010101010000000001010000010001000001000101000001000001000100000101000001010000010101010001000000010001010001010001000101010001000400000001", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000010000010000010000010000010100000001000100010000000000010001000001000100010101010001000100000001010001010001010001000100010100000100000101010101000100010001010100010101000001010101010000010001010100000001000101000100010001000101000101010101000000010101000100000001010101010000000101000101010100010101000000000000010100000000010001010100010000010101000000000000000001010100010100010000010000010100000001010000000001000000000000000100010001000001010000010100010001000100010101000100000100010001010100000100000400000100", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000000000010100010100000000000001000000010001000100000100000000010000000000000001010100010101010100000101010100010100000001010100000100000000000000010100000000010000010101000100010000010101010100000101000100010000010000000100010100010000000101000000000001010100000001000101000100000000010101010000010000000100010001010000010000000100010000010000010101000101000101000100000100010100000001010000010101000101010001010000000100010001000001000000010100000001000100000100010000010100010000010000010001010101010001010400000101", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000100000000000100010000000001000100000101010001000100000101010001010100010100010000000000010100000100010101000001000000010101000100010001010100010100010101010101010000010000000100000100000100000000010100010100000000010001000100000101010000000101000000000001000101010000000101010000010000000001010101000100000001010101000001000001000001010100010000000001010001000101000101010100000000010001010000000001000101010100010101010101010101000101000100010000010000010101000100010100010000000100000000000100000001010100010000fd0001000101000100000001010000000100000101000100000000010101010001010001000001010100010000000101010101000000010100000001000101000101010001000100010100010100000000010001010100010101000100000000010101000100010101000000000001000100000101010100000001010100000001010001010000010100010000010101000000000101000100000000000100010101000001010100000001000100010101000101010100010100010000000100010000010001010101010100010101010101000000010101010000000000010101000000010001000101000000000100000000010101000100000101010101010100000400010000", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000100000000000100010000000001000100000101010001000100000101010001010100010100010000000000010100000100010101000001000000010101000100010001010100010100010101010101010000010000000100000100000100000000010100010100000000010001000100000101010000000101000000000001000101010000000101010000010000000001010101000100000001010101000001000001000001010100010000000001010001000101000101010100000000010001010000000001000101010100010101010101010101000101000100010000010000010101000100010100010000000100000000000100000001010100010000fd0001010101010101010100010101010100000000010100010100000000000000010100010101000100000100010000010100000100010000000001000000010001000101010000000000010000010000000000010000010100000001010101000000000001000000000100000100000101010101010101010101000100010101000101010000010101000100000100000000010000010000000101000000010101010000010101010100010101000100000000000001010100000101010101000001000001000101010001010101000000010100010100010100010000010100010001010101010001010100000001000101010101010001000000010000000001010400010001", -! "04fd000100000101010101010000000001000100000100000000000000010100000000010100000000000001000000010000000000010001010000010001010001000000010101010101000101000100010101000101010000000101000000000001010000010101010000010101010000000101000001000001010100000101010100000001010000010100010001010001010100000100010001010101010101000001010001000001010101010101000100010101000101010100010001010100010101010101000001010100010100010001010001000000000001000100000001000001010001010100000001010001000101000001010101010100000100000100fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000101000100010101000101000100010001000000010100010001010100000001010000000101010101000100010100000100010101010101010100000100010101000101000100010101000100010100000000000001010101000101000000010001010000010100010001000101010100000100010001010000000101000001000000000000000101010101000100010001010001000100000100010100010001000001000000000000000100010100010001010000010000000100010100000101010000000100010101000100010000000100010001000000010100000101000101000101010001000101010000010100010101010001000101010100000100fd0001000100010000000001010000000000000100010100010000000001010000000000010100000000010101000000000101010000010000000101000001000000010101000000000101010101000101000000010001000001000100000100010101000001010001000000000101000001000100000001000101000101010101010101000001010100000100010001010101010101000100010100010100010101010101000100000001000101000000010001010000010100000001000001000001010001000001000000010000010000010001000100010000000100000000010001010001010000010001000001000001010000010100010000000100010100010400010100", -! "04fd000101000001000101000001000001010101010100010101000001000000010000010101010001000000010000000001010101000001010101010000000100000001010101000100010000000000010000000001010101000000010101010000000101000001010001000001000000010001010000010101010101010000000100010000010101000000010101000000010001010001010101010101000000000101010100000000010100000000000000010000000101010100010000010001000101010101000000010000010001010100000001010101010001000100010000010100010100010100000001000101000001010100000101010101000000010000fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000100000001010100010001010000010100010001010001010101000000010001010101000000000101010001010100010100010101000000000000000100010000010101000101000000000100010101000000010100000001010100000101000000010101000100000000010101010001010000010101010001000001010001000100000100000100010101000101010100010001010100000001000000010001010000010100000000000101000001010101010100010000010101000001010000010001000101010000000001000100010001000000010001000101000101000001000100010000010000010100000100000100010000000001010400000000", -! "04fd000101000001000101000001000001010101010100010101000001000000010000010101010001000000010000000001010101000001010101010000000100000001010101000100010000000000010000000001010101000000010101010000000101000001010001000001000000010001010000010101010101010000000100010000010101000000010101000000010001010001010101010101000000000101010100000000010100000000000000010000000101010100010000010001000101010101000000010000010001010100000001010101010001000100010000010100010100010100000001000101000001010100000101010101000000010000fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000000010001010101010100010100010001010001010000010100010101010101010001010101010100000001000101010101000000000101010000000101010001000100000101000000010000010100010001000100000101010000010000010100010101000000010001000101010101000000010001000001010100010000010000000101010000010100010001010001000000000101000101000001010101010000010000000001000001000001000100000101000001000100010101010000000001010000010001000001000101000001000001000100000101000001010000010101010001000000010001010001010001000101010001000400000001", -! "04fd000101000001000101000001000001010101010100010101000001000000010000010101010001000000010000000001010101000001010101010000000100000001010101000100010000000000010000000001010101000000010101010000000101000001010001000001000000010001010000010101010101010000000100010000010101000000010101000000010001010001010101010101000000000101010100000000010100000000000000010000000101010100010000010001000101010101000000010000010001010100000001010101010001000100010000010100010100010100000001000101000001010100000101010101000000010000fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000010000010000010000010000010100000001000100010000000000010001000001000100010101010001000100000001010001010001010001000100010100000100000101010101000100010001010100010101000001010101010000010001010100000001000101000100010001000101000101010101000000010101000100000001010101010000000101000101010100010101000000000000010100000000010001010100010000010101000000000000000001010100010100010000010000010100000001010000000001000000000000000100010001000001010000010100010001000100010101000100000100010001010100000100000400000100", -! "04fd000101000001000101000001000001010101010100010101000001000000010000010101010001000000010000000001010101000001010101010000000100000001010101000100010000000000010000000001010101000000010101010000000101000001010001000001000000010001010000010101010101010000000100010000010101000000010101000000010001010001010101010101000000000101010100000000010100000000000000010000000101010100010000010001000101010101000000010000010001010100000001010101010001000100010000010100010100010100000001000101000001010100000101010101000000010000fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000000000010100010100000000000001000000010001000100000100000000010000000000000001010100010101010100000101010100010100000001010100000100000000000000010100000000010000010101000100010000010101010100000101000100010000010000000100010100010000000101000000000001010100000001000101000100000000010101010000010000000100010001010000010000000100010000010000010101000101000101000100000100010100000001010000010101000101010001010000000100010001000001000000010100000001000100000100010000010100010000010000010001010101010001010400000101", -! "04fd000101000001000101000001000001010101010100010101000001000000010000010101010001000000010000000001010101000001010101010000000100000001010101000100010000000000010000000001010101000000010101010000000101000001010001000001000000010001010000010101010101010000000100010000010101000000010101000000010001010001010101010101000000000101010100000000010100000000000000010000000101010100010000010001000101010101000000010000010001010100000001010101010001000100010000010100010100010100000001000101000001010100000101010101000000010000fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000100000000000100010000000001000100000101010001000100000101010001010100010100010000000000010100000100010101000001000000010101000100010001010100010100010101010101010000010000000100000100000100000000010100010100000000010001000100000101010000000101000000000001000101010000000101010000010000000001010101000100000001010101000001000001000001010100010000000001010001000101000101010100000000010001010000000001000101010100010101010101010101000101000100010000010000010101000100010100010000000100000000000100000001010100010000fd0001000101000100000001010000000100000101000100000000010101010001010001000001010100010000000101010101000000010100000001000101000101010001000100010100010100000000010001010100010101000100000000010101000100010101000000000001000100000101010100000001010100000001010001010000010100010000010101000000000101000100000000000100010101000001010100000001000100010101000101010100010100010000000100010000010001010101010100010101010101000000010101010000000000010101000000010001000101000000000100000000010101000100000101010101010100000400010000", -! "04fd000101000001000101000001000001010101010100010101000001000000010000010101010001000000010000000001010101000001010101010000000100000001010101000100010000000000010000000001010101000000010101010000000101000001010001000001000000010001010000010101010101010000000100010000010101000000010101000000010001010001010101010101000000000101010100000000010100000000000000010000000101010100010000010001000101010101000000010000010001010100000001010101010001000100010000010100010100010100000001000101000001010100000101010101000000010000fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000100000000000100010000000001000100000101010001000100000101010001010100010100010000000000010100000100010101000001000000010101000100010001010100010100010101010101010000010000000100000100000100000000010100010100000000010001000100000101010000000101000000000001000101010000000101010000010000000001010101000100000001010101000001000001000001010100010000000001010001000101000101010100000000010001010000000001000101010100010101010101010101000101000100010000010000010101000100010100010000000100000000000100000001010100010000fd0001010101010101010100010101010100000000010100010100000000000000010100010101000100000100010000010100000100010000000001000000010001000101010000000000010000010000000000010000010100000001010101000000000001000000000100000100000101010101010101010101000100010101000101010000010101000100000100000000010000010000000101000000010101010000010101010100010101000100000000000001010100000101010101000001000001000101010001010101000000010100010100010100010000010100010001010101010001010100000001000101010101010001000000010000000001010400010001", -! "04fd000101000001000101000001000001010101010100010101000001000000010000010101010001000000010000000001010101000001010101010000000100000001010101000100010000000000010000000001010101000000010101010000000101000001010001000001000000010001010000010101010101010000000100010000010101000000010101000000010001010001010101010101000000000101010100000000010100000000000000010000000101010100010000010001000101010101000000010000010001010100000001010101010001000100010000010100010100010100000001000101000001010100000101010101000000010000fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000101000100010101000101000100010001000000010100010001010100000001010000000101010101000100010100000100010101010101010100000100010101000101000100010101000100010100000000000001010101000101000000010001010000010100010001000101010100000100010001010000000101000001000000000000000101010101000100010001010001000100000100010100010001000001000000000000000100010100010001010000010000000100010100000101010000000100010101000100010000000100010001000000010100000101000101000101010001000101010000010100010101010001000101010100000100fd0001000100010000000001010000000000000100010100010000000001010000000000010100000000010101000000000101010000010000000101000001000000010101000000000101010101000101000000010001000001000100000100010101000001010001000000000101000001000100000001000101000101010101010101000001010100000100010001010101010101000100010100010100010101010101000100000001000101000000010001010000010100000001000001000001010001000001000000010000010000010001000100010000000100000000010001010001010000010001000001000001010000010100010000000100010100010400010100", -! "04fd000101000001000101000001000001010101010100010101000001000000010000010101010001000000010000000001010101000001010101010000000100000001010101000100010000000000010000000001010101000000010101010000000101000001010001000001000000010001010000010101010101010000000100010000010101000000010101000000010001010001010101010101000000000101010100000000010100000000000000010000000101010100010000010001000101010101000000010000010001010100000001010101010001000100010000010100010100010100000001000101000001010100000101010101000000010000fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000101000100010101000101000100010001000000010100010001010100000001010000000101010101000100010100000100010101010101010100000100010101000101000100010101000100010100000000000001010101000101000000010001010000010100010001000101010100000100010001010000000101000001000000000000000101010101000100010001010001000100000100010100010001000001000000000000000100010100010001010000010000000100010100000101010000000100010101000100010000000100010001000000010100000101000101000101010001000101010000010100010101010001000101010100000100fd0001010000000100010100000001000101000101000001010001000001010101010001010000000100000001000001000000000101010001000101010100000100000100000000010001000101000101010000000101000000000000010100010000000100000101000000000000010001010001000001000100000101000100000001000100000101000101010101000001000001000100000101000100000101000100000001000101010101000001000100000001000000010001010101000101000001000000010000010001010001010100000000000000010000010000010000010100000001010000000000000001010101000001010101000101000000010400010101", -! "04fd000100010001000100000101010000010101010001000001000101010001010101000000000000010100010101000001010001010000000001000001010000000101000001000101000100000000000001010001010001000100000001010101000100010101000000000100000101000001010100000101010101010101010101000101010101010000010001010000010001010100000001000101010001010001000001010001010001000101010100010100010100000001010000000000010100010101010000000100010101010100000001000001000101010001000101010000000000010001010000000101000100000100010100000100000001010001fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000100000001010100010001010000010100010001010001010101000000010001010101000000000101010001010100010100010101000000000000000100010000010101000101000000000100010101000000010100000001010100000101000000010101000100000000010101010001010000010101010001000001010001000100000100000100010101000101010100010001010100000001000000010001010000010100000000000101000001010101010100010000010101000001010000010001000101010000000001000100010001000000010001000101000101000001000100010000010000010100000100000100010000000001010400000000", -! "04fd000100010001000100000101010000010101010001000001000101010001010101000000000000010100010101000001010001010000000001000001010000000101000001000101000100000000000001010001010001000100000001010101000100010101000000000100000101000001010100000101010101010101010101000101010101010000010001010000010001010100000001000101010001010001000001010001010001000101010100010100010100000001010000000000010100010101010000000100010101010100000001000001000101010001000101010000000000010001010000000101000100000100010100000100000001010001fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000000010001010101010100010100010001010001010000010100010101010101010001010101010100000001000101010101000000000101010000000101010001000100000101000000010000010100010001000100000101010000010000010100010101000000010001000101010101000000010001000001010100010000010000000101010000010100010001010001000000000101000101000001010101010000010000000001000001000001000100000101000001000100010101010000000001010000010001000001000101000001000001000100000101000001010000010101010001000000010001010001010001000101010001000400000001", -! "04fd000100010001000100000101010000010101010001000001000101010001010101000000000000010100010101000001010001010000000001000001010000000101000001000101000100000000000001010001010001000100000001010101000100010101000000000100000101000001010100000101010101010101010101000101010101010000010001010000010001010100000001000101010001010001000001010001010001000101010100010100010100000001010000000000010100010101010000000100010101010100000001000001000101010001000101010000000000010001010000000101000100000100010100000100000001010001fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000010000010000010000010000010100000001000100010000000000010001000001000100010101010001000100000001010001010001010001000100010100000100000101010101000100010001010100010101000001010101010000010001010100000001000101000100010001000101000101010101000000010101000100000001010101010000000101000101010100010101000000000000010100000000010001010100010000010101000000000000000001010100010100010000010000010100000001010000000001000000000000000100010001000001010000010100010001000100010101000100000100010001010100000100000400000100", -! "04fd000100010001000100000101010000010101010001000001000101010001010101000000000000010100010101000001010001010000000001000001010000000101000001000101000100000000000001010001010001000100000001010101000100010101000000000100000101000001010100000101010101010101010101000101010101010000010001010000010001010100000001000101010001010001000001010001010001000101010100010100010100000001010000000000010100010101010000000100010101010100000001000001000101010001000101010000000000010001010000000101000100000100010100000100000001010001fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000000000010100010100000000000001000000010001000100000100000000010000000000000001010100010101010100000101010100010100000001010100000100000000000000010100000000010000010101000100010000010101010100000101000100010000010000000100010100010000000101000000000001010100000001000101000100000000010101010000010000000100010001010000010000000100010000010000010101000101000101000100000100010100000001010000010101000101010001010000000100010001000001000000010100000001000100000100010000010100010000010000010001010101010001010400000101", -! "04fd000100010001000100000101010000010101010001000001000101010001010101000000000000010100010101000001010001010000000001000001010000000101000001000101000100000000000001010001010001000100000001010101000100010101000000000100000101000001010100000101010101010101010101000101010101010000010001010000010001010100000001000101010001010001000001010001010001000101010100010100010100000001010000000000010100010101010000000100010101010100000001000001000101010001000101010000000000010001010000000101000100000100010100000100000001010001fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000100000000000100010000000001000100000101010001000100000101010001010100010100010000000000010100000100010101000001000000010101000100010001010100010100010101010101010000010000000100000100000100000000010100010100000000010001000100000101010000000101000000000001000101010000000101010000010000000001010101000100000001010101000001000001000001010100010000000001010001000101000101010100000000010001010000000001000101010100010101010101010101000101000100010000010000010101000100010100010000000100000000000100000001010100010000fd0001000101000100000001010000000100000101000100000000010101010001010001000001010100010000000101010101000000010100000001000101000101010001000100010100010100000000010001010100010101000100000000010101000100010101000000000001000100000101010100000001010100000001010001010000010100010000010101000000000101000100000000000100010101000001010100000001000100010101000101010100010100010000000100010000010001010101010100010101010101000000010101010000000000010101000000010001000101000000000100000000010101000100000101010101010100000400010000", -! "04fd000100010001000100000101010000010101010001000001000101010001010101000000000000010100010101000001010001010000000001000001010000000101000001000101000100000000000001010001010001000100000001010101000100010101000000000100000101000001010100000101010101010101010101000101010101010000010001010000010001010100000001000101010001010001000001010001010001000101010100010100010100000001010000000000010100010101010000000100010101010100000001000001000101010001000101010000000000010001010000000101000100000100010100000100000001010001fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000100000000000100010000000001000100000101010001000100000101010001010100010100010000000000010100000100010101000001000000010101000100010001010100010100010101010101010000010000000100000100000100000000010100010100000000010001000100000101010000000101000000000001000101010000000101010000010000000001010101000100000001010101000001000001000001010100010000000001010001000101000101010100000000010001010000000001000101010100010101010101010101000101000100010000010000010101000100010100010000000100000000000100000001010100010000fd0001010101010101010100010101010100000000010100010100000000000000010100010101000100000100010000010100000100010000000001000000010001000101010000000000010000010000000000010000010100000001010101000000000001000000000100000100000101010101010101010101000100010101000101010000010101000100000100000000010000010000000101000000010101010000010101010100010101000100000000000001010100000101010101000001000001000101010001010101000000010100010100010100010000010100010001010101010001010100000001000101010101010001000000010000000001010400010001", -! "04fd000100010001000100000101010000010101010001000001000101010001010101000000000000010100010101000001010001010000000001000001010000000101000001000101000100000000000001010001010001000100000001010101000100010101000000000100000101000001010100000101010101010101010101000101010101010000010001010000010001010100000001000101010001010001000001010001010001000101010100010100010100000001010000000000010100010101010000000100010101010100000001000001000101010001000101010000000000010001010000000101000100000100010100000100000001010001fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000101000100010101000101000100010001000000010100010001010100000001010000000101010101000100010100000100010101010101010100000100010101000101000100010101000100010100000000000001010101000101000000010001010000010100010001000101010100000100010001010000000101000001000000000000000101010101000100010001010001000100000100010100010001000001000000000000000100010100010001010000010000000100010100000101010000000100010101000100010000000100010001000000010100000101000101000101010001000101010000010100010101010001000101010100000100fd0001000100010000000001010000000000000100010100010000000001010000000000010100000000010101000000000101010000010000000101000001000000010101000000000101010101000101000000010001000001000100000100010101000001010001000000000101000001000100000001000101000101010101010101000001010100000100010001010101010101000100010100010100010101010101000100000001000101000000010001010000010100000001000001000001010001000001000000010000010000010001000100010000000100000000010001010001010000010001000001000001010000010100010000000100010100010400010100", -! "04fd000100010001000100000101010000010101010001000001000101010001010101000000000000010100010101000001010001010000000001000001010000000101000001000101000100000000000001010001010001000100000001010101000100010101000000000100000101000001010100000101010101010101010101000101010101010000010001010000010001010100000001000101010001010001000001010001010001000101010100010100010100000001010000000000010100010101010000000100010101010100000001000001000101010001000101010000000000010001010000000101000100000100010100000100000001010001fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000101000100010101000101000100010001000000010100010001010100000001010000000101010101000100010100000100010101010101010100000100010101000101000100010101000100010100000000000001010101000101000000010001010000010100010001000101010100000100010001010000000101000001000000000000000101010101000100010001010001000100000100010100010001000001000000000000000100010100010001010000010000000100010100000101010000000100010101000100010000000100010001000000010100000101000101000101010001000101010000010100010101010001000101010100000100fd0001010000000100010100000001000101000101000001010001000001010101010001010000000100000001000001000000000101010001000101010100000100000100000000010001000101000101010000000101000000000000010100010000000100000101000000000000010001010001000001000100000101000100000001000100000101000101010101000001000001000100000101000100000101000100000001000101010101000001000100000001000000010001010101000101000001000000010000010001010001010100000000000000010000010000010000010100000001010000000000000001010101000001010101000101000000010400010101", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000101010001010001000001000100010100010000010100000001000101010101000000000100010101010001010100000101000101000100000001010001000001000101000000010000000101000001010001000100010101010000010100000100010101000101010100000101010101010001010101010001010000010001000100000001010000010101000001000101010001000100000100000100000001010100000000000001010001000001000001010000000100000100000000010101000101010001000101010101010100010101010100000101010100010001000000000101000000000001010001010101000100010000010101000101000000fd0001010100010100000000000001010101000101010100010100000100000100010000000000000000000001010000000101000100010001010100000101010100010100000000000000010100000101000100000101000001000000010000000100000001000101000101000000010100010000000000010000010100010101010001000101010001010101010001000000000000000001010100000101000100000001000101000100010100010001010101000100010101010000010001010100010000010101010001010001010101010000000001010101000100000001000001000101010100010101010101000100010101010100000000000001000101010401000000", -! "04fd000101000100010100010000010001010100010101010000000001010000000100000001010001010000000000000101000101000000000000000101010001000101010101000100010000010101000100010001010101000000000000000101000100010001010001000101010100000000000101010001010100000101010100010100010101000000000001010000010100000000010001010101000001010000000100000101010101000101010000000100000100000101010100010000010000010101010001000001010000010100010001000101010001000000010000000000000000010101010101010100010100000101010000000000000001010000fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000100000001010100010001010000010100010001010001010101000000010001010101000000000101010001010100010100010101000000000000000100010000010101000101000000000100010101000000010100000001010100000101000000010101000100000000010101010001010000010101010001000001010001000100000100000100010101000101010100010001010100000001000000010001010000010100000000000101000001010101010100010000010101000001010000010001000101010000000001000100010001000000010001000101000101000001000100010000010000010100000100000100010000000001010400000000", -! "04fd000101000100010100010000010001010100010101010000000001010000000100000001010001010000000000000101000101000000000000000101010001000101010101000100010000010101000100010001010101000000000000000101000100010001010001000101010100000000000101010001010100000101010100010100010101000000000001010000010100000000010001010101000001010000000100000101010101000101010000000100000100000101010100010000010000010101010001000001010000010100010001000101010001000000010000000000000000010101010101010100010100000101010000000000000001010000fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000000010001010101010100010100010001010001010000010100010101010101010001010101010100000001000101010101000000000101010000000101010001000100000101000000010000010100010001000100000101010000010000010100010101000000010001000101010101000000010001000001010100010000010000000101010000010100010001010001000000000101000101000001010101010000010000000001000001000001000100000101000001000100010101010000000001010000010001000001000101000001000001000100000101000001010000010101010001000000010001010001010001000101010001000400000001", -! "04fd000101000100010100010000010001010100010101010000000001010000000100000001010001010000000000000101000101000000000000000101010001000101010101000100010000010101000100010001010101000000000000000101000100010001010001000101010100000000000101010001010100000101010100010100010101000000000001010000010100000000010001010101000001010000000100000101010101000101010000000100000100000101010100010000010000010101010001000001010000010100010001000101010001000000010000000000000000010101010101010100010100000101010000000000000001010000fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000010000010000010000010000010100000001000100010000000000010001000001000100010101010001000100000001010001010001010001000100010100000100000101010101000100010001010100010101000001010101010000010001010100000001000101000100010001000101000101010101000000010101000100000001010101010000000101000101010100010101000000000000010100000000010001010100010000010101000000000000000001010100010100010000010000010100000001010000000001000000000000000100010001000001010000010100010001000100010101000100000100010001010100000100000400000100", -! "04fd000101000100010100010000010001010100010101010000000001010000000100000001010001010000000000000101000101000000000000000101010001000101010101000100010000010101000100010001010101000000000000000101000100010001010001000101010100000000000101010001010100000101010100010100010101000000000001010000010100000000010001010101000001010000000100000101010101000101010000000100000100000101010100010000010000010101010001000001010000010100010001000101010001000000010000000000000000010101010101010100010100000101010000000000000001010000fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000000000010100010100000000000001000000010001000100000100000000010000000000000001010100010101010100000101010100010100000001010100000100000000000000010100000000010000010101000100010000010101010100000101000100010000010000000100010100010000000101000000000001010100000001000101000100000000010101010000010000000100010001010000010000000100010000010000010101000101000101000100000100010100000001010000010101000101010001010000000100010001000001000000010100000001000100000100010000010100010000010000010001010101010001010400000101", -! "04fd000101000100010100010000010001010100010101010000000001010000000100000001010001010000000000000101000101000000000000000101010001000101010101000100010000010101000100010001010101000000000000000101000100010001010001000101010100000000000101010001010100000101010100010100010101000000000001010000010100000000010001010101000001010000000100000101010101000101010000000100000100000101010100010000010000010101010001000001010000010100010001000101010001000000010000000000000000010101010101010100010100000101010000000000000001010000fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000100000000000100010000000001000100000101010001000100000101010001010100010100010000000000010100000100010101000001000000010101000100010001010100010100010101010101010000010000000100000100000100000000010100010100000000010001000100000101010000000101000000000001000101010000000101010000010000000001010101000100000001010101000001000001000001010100010000000001010001000101000101010100000000010001010000000001000101010100010101010101010101000101000100010000010000010101000100010100010000000100000000000100000001010100010000fd0001000101000100000001010000000100000101000100000000010101010001010001000001010100010000000101010101000000010100000001000101000101010001000100010100010100000000010001010100010101000100000000010101000100010101000000000001000100000101010100000001010100000001010001010000010100010000010101000000000101000100000000000100010101000001010100000001000100010101000101010100010100010000000100010000010001010101010100010101010101000000010101010000000000010101000000010001000101000000000100000000010101000100000101010101010100000400010000", -! "04fd000101000100010100010000010001010100010101010000000001010000000100000001010001010000000000000101000101000000000000000101010001000101010101000100010000010101000100010001010101000000000000000101000100010001010001000101010100000000000101010001010100000101010100010100010101000000000001010000010100000000010001010101000001010000000100000101010101000101010000000100000100000101010100010000010000010101010001000001010000010100010001000101010001000000010000000000000000010101010101010100010100000101010000000000000001010000fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000100000000000100010000000001000100000101010001000100000101010001010100010100010000000000010100000100010101000001000000010101000100010001010100010100010101010101010000010000000100000100000100000000010100010100000000010001000100000101010000000101000000000001000101010000000101010000010000000001010101000100000001010101000001000001000001010100010000000001010001000101000101010100000000010001010000000001000101010100010101010101010101000101000100010000010000010101000100010100010000000100000000000100000001010100010000fd0001010101010101010100010101010100000000010100010100000000000000010100010101000100000100010000010100000100010000000001000000010001000101010000000000010000010000000000010000010100000001010101000000000001000000000100000100000101010101010101010101000100010101000101010000010101000100000100000000010000010000000101000000010101010000010101010100010101000100000000000001010100000101010101000001000001000101010001010101000000010100010100010100010000010100010001010101010001010100000001000101010101010001000000010000000001010400010001", -! "04fd000101000100010100010000010001010100010101010000000001010000000100000001010001010000000000000101000101000000000000000101010001000101010101000100010000010101000100010001010101000000000000000101000100010001010001000101010100000000000101010001010100000101010100010100010101000000000001010000010100000000010001010101000001010000000100000101010101000101010000000100000100000101010100010000010000010101010001000001010000010100010001000101010001000000010000000000000000010101010101010100010100000101010000000000000001010000fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000101000100010101000101000100010001000000010100010001010100000001010000000101010101000100010100000100010101010101010100000100010101000101000100010101000100010100000000000001010101000101000000010001010000010100010001000101010100000100010001010000000101000001000000000000000101010101000100010001010001000100000100010100010001000001000000000000000100010100010001010000010000000100010100000101010000000100010101000100010000000100010001000000010100000101000101000101010001000101010000010100010101010001000101010100000100fd0001000100010000000001010000000000000100010100010000000001010000000000010100000000010101000000000101010000010000000101000001000000010101000000000101010101000101000000010001000001000100000100010101000001010001000000000101000001000100000001000101000101010101010101000001010100000100010001010101010101000100010100010100010101010101000100000001000101000000010001010000010100000001000001000001010001000001000000010000010000010001000100010000000100000000010001010001010000010001000001000001010000010100010000000100010100010400010100", -! "04fd000101000100010100010000010001010100010101010000000001010000000100000001010001010000000000000101000101000000000000000101010001000101010101000100010000010101000100010001010101000000000000000101000100010001010001000101010100000000000101010001010100000101010100010100010101000000000001010000010100000000010001010101000001010000000100000101010101000101010000000100000100000101010100010000010000010101010001000001010000010100010001000101010001000000010000000000000000010101010101010100010100000101010000000000000001010000fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000101000100010101000101000100010001000000010100010001010100000001010000000101010101000100010100000100010101010101010100000100010101000101000100010101000100010100000000000001010101000101000000010001010000010100010001000101010100000100010001010000000101000001000000000000000101010101000100010001010001000100000100010100010001000001000000000000000100010100010001010000010000000100010100000101010000000100010101000100010000000100010001000000010100000101000101000101010001000101010000010100010101010001000101010100000100fd0001010000000100010100000001000101000101000001010001000001010101010001010000000100000001000001000000000101010001000101010100000100000100000000010001000101000101010000000101000000000000010100010000000100000101000000000000010001010001000001000100000101000100000001000100000101000101010101000001000001000100000101000100000101000100000001000101010101000001000100000001000000010001010101000101000001000000010000010001010001010100000000000000010000010000010000010100000001010000000000000001010101000001010101000101000000010400010101", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000100010101000100000100000000010100010100010000010001010101010100010100010100000000010100000001010101010101000001000001010001010101010000010000000001010101010001000101000000000001010000000001010000010001000100010101000101000100000100010101010000000100000100000100010100000100000001000001000001000101000100000101000101000101000101010000000000000100000100000100000101010000010000000001000001000001000001010101000000010100000101000101010001000101010100000100000001000100010100000101000001010000000100000101010000000001fd0001010100010100000000000001010101000101010100010100000100000100010000000000000000000001010000000101000100010001010100000101010100010100000000000000010100000101000100000101000001000000010000000100000001000101000101000000010100010000000000010000010100010101010001000101010001010101010001000000000000000001010100000101000100000001000101000100010100010001010101000100010101010000010001010100010000010101010001010001010101010000000001010101000100000001000001000101010100010101010101000100010101010100000000000001000101010401000000", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000100010101000100000100000000010100010100010000010001010101010100010100010100000000010100000001010101010101000001000001010001010101010000010000000001010101010001000101000000000001010000000001010000010001000100010101000101000100000100010101010000000100000100000100010100000100000001000001000001000101000100000101000101000101000101010000000000000100000100000100000101010000010000000001000001000001000001010101000000010100000101000101010001000101010100000100000001000100010100000101000001010000000100000101010000000001fd0001000101010000000001010101010101010101000101010001000100010101010101000100000000000101010100000101010001000101010001000100000000010100000001000101010100010001000000010101000000000000000001010101000000010100010001010000000001000101010000000100010101000000000000000101010100000101010100010001010100010001000001000101000101010100010101000000000100010001010101010100010000000101000101010001010000010000010101000101010000000001010000000100010001000100000000000101000000010100000101000101010000010001010000010001000001010401000001", -! "04fd000100010000010101000101000001000001000000000101010101000100000001000001000100010000000100010100000100000100000000010101000000010100010000010101000100000001000100010100000101000100010101010101000001010001000100010100010000000101000101000100000101010001010101010101010000010100010000000000010100010101000000000001000100000000000001010000000000010000000101010001000100000101010100010001000100010100000100000101000101010000000101010000000100010001000101000101010100010000000001010100010000000101000101010101010100000101fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000100000001010100010001010000010100010001010001010101000000010001010101000000000101010001010100010100010101000000000000000100010000010101000101000000000100010101000000010100000001010100000101000000010101000100000000010101010001010000010101010001000001010001000100000100000100010101000101010100010001010100000001000000010001010000010100000000000101000001010101010100010000010101000001010000010001000101010000000001000100010001000000010001000101000101000001000100010000010000010100000100000100010000000001010400000000", -! "04fd000100010000010101000101000001000001000000000101010101000100000001000001000100010000000100010100000100000100000000010101000000010100010000010101000100000001000100010100000101000100010101010101000001010001000100010100010000000101000101000100000101010001010101010101010000010100010000000000010100010101000000000001000100000000000001010000000000010000000101010001000100000101010100010001000100010100000100000101000101010000000101010000000100010001000101000101010100010000000001010100010000000101000101010101010100000101fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000000010001010101010100010100010001010001010000010100010101010101010001010101010100000001000101010101000000000101010000000101010001000100000101000000010000010100010001000100000101010000010000010100010101000000010001000101010101000000010001000001010100010000010000000101010000010100010001010001000000000101000101000001010101010000010000000001000001000001000100000101000001000100010101010000000001010000010001000001000101000001000001000100000101000001010000010101010001000000010001010001010001000101010001000400000001", -! "04fd000100010000010101000101000001000001000000000101010101000100000001000001000100010000000100010100000100000100000000010101000000010100010000010101000100000001000100010100000101000100010101010101000001010001000100010100010000000101000101000100000101010001010101010101010000010100010000000000010100010101000000000001000100000000000001010000000000010000000101010001000100000101010100010001000100010100000100000101000101010000000101010000000100010001000101000101010100010000000001010100010000000101000101010101010100000101fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000010000010000010000010000010100000001000100010000000000010001000001000100010101010001000100000001010001010001010001000100010100000100000101010101000100010001010100010101000001010101010000010001010100000001000101000100010001000101000101010101000000010101000100000001010101010000000101000101010100010101000000000000010100000000010001010100010000010101000000000000000001010100010100010000010000010100000001010000000001000000000000000100010001000001010000010100010001000100010101000100000100010001010100000100000400000100", -! "04fd000100010000010101000101000001000001000000000101010101000100000001000001000100010000000100010100000100000100000000010101000000010100010000010101000100000001000100010100000101000100010101010101000001010001000100010100010000000101000101000100000101010001010101010101010000010100010000000000010100010101000000000001000100000000000001010000000000010000000101010001000100000101010100010001000100010100000100000101000101010000000101010000000100010001000101000101010100010000000001010100010000000101000101010101010100000101fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000000000010100010100000000000001000000010001000100000100000000010000000000000001010100010101010100000101010100010100000001010100000100000000000000010100000000010000010101000100010000010101010100000101000100010000010000000100010100010000000101000000000001010100000001000101000100000000010101010000010000000100010001010000010000000100010000010000010101000101000101000100000100010100000001010000010101000101010001010000000100010001000001000000010100000001000100000100010000010100010000010000010001010101010001010400000101", -! "04fd000100010000010101000101000001000001000000000101010101000100000001000001000100010000000100010100000100000100000000010101000000010100010000010101000100000001000100010100000101000100010101010101000001010001000100010100010000000101000101000100000101010001010101010101010000010100010000000000010100010101000000000001000100000000000001010000000000010000000101010001000100000101010100010001000100010100000100000101000101010000000101010000000100010001000101000101010100010000000001010100010000000101000101010101010100000101fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000100000000000100010000000001000100000101010001000100000101010001010100010100010000000000010100000100010101000001000000010101000100010001010100010100010101010101010000010000000100000100000100000000010100010100000000010001000100000101010000000101000000000001000101010000000101010000010000000001010101000100000001010101000001000001000001010100010000000001010001000101000101010100000000010001010000000001000101010100010101010101010101000101000100010000010000010101000100010100010000000100000000000100000001010100010000fd0001000101000100000001010000000100000101000100000000010101010001010001000001010100010000000101010101000000010100000001000101000101010001000100010100010100000000010001010100010101000100000000010101000100010101000000000001000100000101010100000001010100000001010001010000010100010000010101000000000101000100000000000100010101000001010100000001000100010101000101010100010100010000000100010000010001010101010100010101010101000000010101010000000000010101000000010001000101000000000100000000010101000100000101010101010100000400010000", -! "04fd000100010000010101000101000001000001000000000101010101000100000001000001000100010000000100010100000100000100000000010101000000010100010000010101000100000001000100010100000101000100010101010101000001010001000100010100010000000101000101000100000101010001010101010101010000010100010000000000010100010101000000000001000100000000000001010000000000010000000101010001000100000101010100010001000100010100000100000101000101010000000101010000000100010001000101000101010100010000000001010100010000000101000101010101010100000101fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000100000000000100010000000001000100000101010001000100000101010001010100010100010000000000010100000100010101000001000000010101000100010001010100010100010101010101010000010000000100000100000100000000010100010100000000010001000100000101010000000101000000000001000101010000000101010000010000000001010101000100000001010101000001000001000001010100010000000001010001000101000101010100000000010001010000000001000101010100010101010101010101000101000100010000010000010101000100010100010000000100000000000100000001010100010000fd0001010101010101010100010101010100000000010100010100000000000000010100010101000100000100010000010100000100010000000001000000010001000101010000000000010000010000000000010000010100000001010101000000000001000000000100000100000101010101010101010101000100010101000101010000010101000100000100000000010000010000000101000000010101010000010101010100010101000100000000000001010100000101010101000001000001000101010001010101000000010100010100010100010000010100010001010101010001010100000001000101010101010001000000010000000001010400010001", -! "04fd000100010000010101000101000001000001000000000101010101000100000001000001000100010000000100010100000100000100000000010101000000010100010000010101000100000001000100010100000101000100010101010101000001010001000100010100010000000101000101000100000101010001010101010101010000010100010000000000010100010101000000000001000100000000000001010000000000010000000101010001000100000101010100010001000100010100000100000101000101010000000101010000000100010001000101000101010100010000000001010100010000000101000101010101010100000101fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000101000100010101000101000100010001000000010100010001010100000001010000000101010101000100010100000100010101010101010100000100010101000101000100010101000100010100000000000001010101000101000000010001010000010100010001000101010100000100010001010000000101000001000000000000000101010101000100010001010001000100000100010100010001000001000000000000000100010100010001010000010000000100010100000101010000000100010101000100010000000100010001000000010100000101000101000101010001000101010000010100010101010001000101010100000100fd0001000100010000000001010000000000000100010100010000000001010000000000010100000000010101000000000101010000010000000101000001000000010101000000000101010101000101000000010001000001000100000100010101000001010001000000000101000001000100000001000101000101010101010101000001010100000100010001010101010101000100010100010100010101010101000100000001000101000000010001010000010100000001000001000001010001000001000000010000010000010001000100010000000100000000010001010001010000010001000001000001010000010100010000000100010100010400010100", -! "04fd000100010000010101000101000001000001000000000101010101000100000001000001000100010000000100010100000100000100000000010101000000010100010000010101000100000001000100010100000101000100010101010101000001010001000100010100010000000101000101000100000101010001010101010101010000010100010000000000010100010101000000000001000100000000000001010000000000010000000101010001000100000101010100010001000100010100000100000101000101010000000101010000000100010001000101000101010100010000000001010100010000000101000101010101010100000101fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000101000100010101000101000100010001000000010100010001010100000001010000000101010101000100010100000100010101010101010100000100010101000101000100010101000100010100000000000001010101000101000000010001010000010100010001000101010100000100010001010000000101000001000000000000000101010101000100010001010001000100000100010100010001000001000000000000000100010100010001010000010000000100010100000101010000000100010101000100010000000100010001000000010100000101000101000101010001000101010000010100010101010001000101010100000100fd0001010000000100010100000001000101000101000001010001000001010101010001010000000100000001000001000000000101010001000101010100000100000100000000010001000101000101010000000101000000000000010100010000000100000101000000000000010001010001000001000100000101000100000001000100000101000101010101000001000001000100000101000100000101000100000001000101010101000001000100000001000000010001010101000101000001000000010000010001010001010100000000000000010000010000010000010100000001010000000000000001010101000001010101000101000000010400010101", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000101000100000000010101010000000001000001000101000001010001000101010100010101000101010000000101000100010001000001010000000000000001000101000101000001000101010101010000000000010101000001000100000101010000010101010101000000000001010001010101010001000100010100010100000000010101000100010100000101000100010000010101010001000001000101010100010000010101010101000100010100010001000000000100010000010000000000010001010001000100000001000001010101010000010101000101000100000000000101010101010000010101000100010001000100000000fd0001010100010100000000000001010101000101010100010100000100000100010000000000000000000001010000000101000100010001010100000101010100010100000000000000010100000101000100000101000001000000010000000100000001000101000101000000010100010000000000010000010100010101010001000101010001010101010001000000000000000001010100000101000100000001000101000100010100010001010101000100010101010000010001010100010000010101010001010001010101010000000001010101000100000001000001000101010100010101010101000100010101010100000000000001000101010401000000", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000101000100000000010101010000000001000001000101000001010001000101010100010101000101010000000101000100010001000001010000000000000001000101000101000001000101010101010000000000010101000001000100000101010000010101010101000000000001010001010101010001000100010100010100000000010101000100010100000101000100010000010101010001000001000101010100010000010101010101000100010100010001000000000100010000010000000000010001010001000100000001000001010101010000010101000101000100000000000101010101010000010101000100010001000100000000fd0001000101010000000001010101010101010101000101010001000100010101010101000100000000000101010100000101010001000101010001000100000000010100000001000101010100010001000000010101000000000000000001010101000000010100010001010000000001000101010000000100010101000000000000000101010100000101010100010001010100010001000001000101000101010100010101000000000100010001010101010100010000000101000101010001010000010000010101000101010000000001010000000100010001000100000000000101000000010100000101000101010000010001010000010001000001010401000001", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000101010001010100000001010100010100000101000101010101000100010001010001000001000001000001000101000001010000010101010000010101010001000000010101010000010000010000010101000100010000010101010000010100010101000100000100010100010001000001000000010100010001010101010100010000010001000101000001000100000000000101000100010001000100010100000000010000000100000001000001000001010001000001010100000101010101010000010001000000000101010101010101000001010001000100000100000100000100000000000000010001000001000101010001000001010000fd000101010101010101000000000101000001000000000101000100010001010101000000010101000101010101000100010001010101000000010000000001000000000100000101000000000001010001010000000101010000010001010001010000010100000001000000000101010001000001000001010000000100010100000000000001010000010100010100000001010000010100010000000100010100000100000001000100010000010101000101010100000000000000010100000001000000000100000001000000000001010001000100010101010101000000000001000101010001000001010001000100010100010001000001000000000001fd0001000000000001000001010100010000010001010000000101010001000100010100010101000001010000000101010100000100000100010001000100010001000100010001000100010101010100000100000101000000010101000000000101010100000000000000000101010000010101010001000100010000000101000001000001010100010001010101000001000000000001000000000001000101000000010101000001000001010001010001010100000000010100000101000100010000000100000100000100010000010001000000000101000100000101000101000100010000010100010001010001010101000100010101000100000001010401000100", -! "04fd000101000100010101010000010001010100000001010000010101000101000001000100000001010100010000000101010101000001010101010101010101000101010100010000000000000001000001000101010000000100010001010100000100010101000000000001010001010101000100010100000001010000000100010001000101010100010000000001010000010100010000010000000100010001000001010100010101000000000100000101000001000101000101000101000100010000000101010000000001000101010000010101010001000101010000010100010001010101000001000100000100010001000101010101000100010101fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000100000001010100010001010000010100010001010001010101000000010001010101000000000101010001010100010100010101000000000000000100010000010101000101000000000100010101000000010100000001010100000101000000010101000100000000010101010001010000010101010001000001010001000100000100000100010101000101010100010001010100000001000000010001010000010100000000000101000001010101010100010000010101000001010000010001000101010000000001000100010001000000010001000101000101000001000100010000010000010100000100000100010000000001010400000000", -! "04fd000101000100010101010000010001010100000001010000010101000101000001000100000001010100010000000101010101000001010101010101010101000101010100010000000000000001000001000101010000000100010001010100000100010101000000000001010001010101000100010100000001010000000100010001000101010100010000000001010000010100010000010000000100010001000001010100010101000000000100000101000001000101000101000101000100010000000101010000000001000101010000010101010001000101010000010100010001010101000001000100000100010001000101010101000100010101fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000000010001010101010100010100010001010001010000010100010101010101010001010101010100000001000101010101000000000101010000000101010001000100000101000000010000010100010001000100000101010000010000010100010101000000010001000101010101000000010001000001010100010000010000000101010000010100010001010001000000000101000101000001010101010000010000000001000001000001000100000101000001000100010101010000000001010000010001000001000101000001000001000100000101000001010000010101010001000000010001010001010001000101010001000400000001", -! "04fd000101000100010101010000010001010100000001010000010101000101000001000100000001010100010000000101010101000001010101010101010101000101010100010000000000000001000001000101010000000100010001010100000100010101000000000001010001010101000100010100000001010000000100010001000101010100010000000001010000010100010000010000000100010001000001010100010101000000000100000101000001000101000101000101000100010000000101010000000001000101010000010101010001000101010000010100010001010101000001000100000100010001000101010101000100010101fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000010000010000010000010000010100000001000100010000000000010001000001000100010101010001000100000001010001010001010001000100010100000100000101010101000100010001010100010101000001010101010000010001010100000001000101000100010001000101000101010101000000010101000100000001010101010000000101000101010100010101000000000000010100000000010001010100010000010101000000000000000001010100010100010000010000010100000001010000000001000000000000000100010001000001010000010100010001000100010101000100000100010001010100000100000400000100", -! "04fd000101000100010101010000010001010100000001010000010101000101000001000100000001010100010000000101010101000001010101010101010101000101010100010000000000000001000001000101010000000100010001010100000100010101000000000001010001010101000100010100000001010000000100010001000101010100010000000001010000010100010000010000000100010001000001010100010101000000000100000101000001000101000101000101000100010000000101010000000001000101010000010101010001000101010000010100010001010101000001000100000100010001000101010101000100010101fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000000000010100010100000000000001000000010001000100000100000000010000000000000001010100010101010100000101010100010100000001010100000100000000000000010100000000010000010101000100010000010101010100000101000100010000010000000100010100010000000101000000000001010100000001000101000100000000010101010000010000000100010001010000010000000100010000010000010101000101000101000100000100010100000001010000010101000101010001010000000100010001000001000000010100000001000100000100010000010100010000010000010001010101010001010400000101", -! "04fd000101000100010101010000010001010100000001010000010101000101000001000100000001010100010000000101010101000001010101010101010101000101010100010000000000000001000001000101010000000100010001010100000100010101000000000001010001010101000100010100000001010000000100010001000101010100010000000001010000010100010000010000000100010001000001010100010101000000000100000101000001000101000101000101000100010000000101010000000001000101010000010101010001000101010000010100010001010101000001000100000100010001000101010101000100010101fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000100000000000100010000000001000100000101010001000100000101010001010100010100010000000000010100000100010101000001000000010101000100010001010100010100010101010101010000010000000100000100000100000000010100010100000000010001000100000101010000000101000000000001000101010000000101010000010000000001010101000100000001010101000001000001000001010100010000000001010001000101000101010100000000010001010000000001000101010100010101010101010101000101000100010000010000010101000100010100010000000100000000000100000001010100010000fd0001000101000100000001010000000100000101000100000000010101010001010001000001010100010000000101010101000000010100000001000101000101010001000100010100010100000000010001010100010101000100000000010101000100010101000000000001000100000101010100000001010100000001010001010000010100010000010101000000000101000100000000000100010101000001010100000001000100010101000101010100010100010000000100010000010001010101010100010101010101000000010101010000000000010101000000010001000101000000000100000000010101000100000101010101010100000400010000", -! "04fd000101000100010101010000010001010100000001010000010101000101000001000100000001010100010000000101010101000001010101010101010101000101010100010000000000000001000001000101010000000100010001010100000100010101000000000001010001010101000100010100000001010000000100010001000101010100010000000001010000010100010000010000000100010001000001010100010101000000000100000101000001000101000101000101000100010000000101010000000001000101010000010101010001000101010000010100010001010101000001000100000100010001000101010101000100010101fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000100000000000100010000000001000100000101010001000100000101010001010100010100010000000000010100000100010101000001000000010101000100010001010100010100010101010101010000010000000100000100000100000000010100010100000000010001000100000101010000000101000000000001000101010000000101010000010000000001010101000100000001010101000001000001000001010100010000000001010001000101000101010100000000010001010000000001000101010100010101010101010101000101000100010000010000010101000100010100010000000100000000000100000001010100010000fd0001010101010101010100010101010100000000010100010100000000000000010100010101000100000100010000010100000100010000000001000000010001000101010000000000010000010000000000010000010100000001010101000000000001000000000100000100000101010101010101010101000100010101000101010000010101000100000100000000010000010000000101000000010101010000010101010100010101000100000000000001010100000101010101000001000001000101010001010101000000010100010100010100010000010100010001010101010001010100000001000101010101010001000000010000000001010400010001", -! "04fd000101000100010101010000010001010100000001010000010101000101000001000100000001010100010000000101010101000001010101010101010101000101010100010000000000000001000001000101010000000100010001010100000100010101000000000001010001010101000100010100000001010000000100010001000101010100010000000001010000010100010000010000000100010001000001010100010101000000000100000101000001000101000101000101000100010000000101010000000001000101010000010101010001000101010000010100010001010101000001000100000100010001000101010101000100010101fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000101000100010101000101000100010001000000010100010001010100000001010000000101010101000100010100000100010101010101010100000100010101000101000100010101000100010100000000000001010101000101000000010001010000010100010001000101010100000100010001010000000101000001000000000000000101010101000100010001010001000100000100010100010001000001000000000000000100010100010001010000010000000100010100000101010000000100010101000100010000000100010001000000010100000101000101000101010001000101010000010100010101010001000101010100000100fd0001000100010000000001010000000000000100010100010000000001010000000000010100000000010101000000000101010000010000000101000001000000010101000000000101010101000101000000010001000001000100000100010101000001010001000000000101000001000100000001000101000101010101010101000001010100000100010001010101010101000100010100010100010101010101000100000001000101000000010001010000010100000001000001000001010001000001000000010000010000010001000100010000000100000000010001010001010000010001000001000001010000010100010000000100010100010400010100", -! "04fd000101000100010101010000010001010100000001010000010101000101000001000100000001010100010000000101010101000001010101010101010101000101010100010000000000000001000001000101010000000100010001010100000100010101000000000001010001010101000100010100000001010000000100010001000101010100010000000001010000010100010000010000000100010001000001010100010101000000000100000101000001000101000101000101000100010000000101010000000001000101010000010101010001000101010000010100010001010101000001000100000100010001000101010101000100010101fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000101000100010101000101000100010001000000010100010001010100000001010000000101010101000100010100000100010101010101010100000100010101000101000100010101000100010100000000000001010101000101000000010001010000010100010001000101010100000100010001010000000101000001000000000000000101010101000100010001010001000100000100010100010001000001000000000000000100010100010001010000010000000100010100000101010000000100010101000100010000000100010001000000010100000101000101000101010001000101010000010100010101010001000101010100000100fd0001010000000100010100000001000101000101000001010001000001010101010001010000000100000001000001000000000101010001000101010100000100000100000000010001000101000101010000000101000000000000010100010000000100000101000000000000010001010001000001000100000101000100000001000100000101000101010101000001000001000100000101000100000101000100000001000101010101000001000100000001000000010001010101000101000001000000010000010001010001010100000000000000010000010000010000010100000001010000000000000001010101000001010101000101000000010400010101", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000100000100010000000001000101000100010001010100010001000101010000010100010101010101010001000101010100000100000000010101010000010101010100010000000000010100000100010101010000010100010100000101010001000000000001010000010000000001010100000000000000010100000000010100000100000000010001010000010101010101010001000100010001010100000101010000000101000101010100000101010100010101000100000001000000010100000101000001000100010000000001010101000001010100010001000000010100000001000001010001000100010000010101010101000101000000fd000101000100000000010101010000000001000001000101000001010001000101010100010101000101010000000101000100010001000001010000000000000001000101000101000001000101010101010000000000010101000001000100000101010000010101010101000000000001010001010101010001000100010100010100000000010101000100010100000101000100010000010101010001000001000101010100010000010101010101000100010100010001000000000100010000010000000000010001010001000100000001000001010101010000010101000101000100000000000101010101010000010101000100010001000100000000fd0001010100010100000000000001010101000101010100010100000100000100010000000000000000000001010000000101000100010001010100000101010100010100000000000000010100000101000100000101000001000000010000000100000001000101000101000000010100010000000000010000010100010101010001000101010001010101010001000000000000000001010100000101000100000001000101000100010100010001010101000100010101010000010001010100010000010101010001010001010101010000000001010101000100000001000001000101010100010101010101000100010101010100000000000001000101010401000000", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000100000100010000000001000101000100010001010100010001000101010000010100010101010101010001000101010100000100000000010101010000010101010100010000000000010100000100010101010000010100010100000101010001000000000001010000010000000001010100000000000000010100000000010100000100000000010001010000010101010101010001000100010001010100000101010000000101000101010100000101010100010101000100000001000000010100000101000001000100010000000001010101000001010100010001000000010100000001000001010001000100010000010101010101000101000000fd000101000100000000010101010000000001000001000101000001010001000101010100010101000101010000000101000100010001000001010000000000000001000101000101000001000101010101010000000000010101000001000100000101010000010101010101000000000001010001010101010001000100010100010100000000010101000100010100000101000100010000010101010001000001000101010100010000010101010101000100010100010001000000000100010000010000000000010001010001000100000001000001010101010000010101000101000100000000000101010101010000010101000100010001000100000000fd0001000101010000000001010101010101010101000101010001000100010101010101000100000000000101010100000101010001000101010001000100000000010100000001000101010100010001000000010101000000000000000001010101000000010100010001010000000001000101010000000100010101000000000000000101010100000101010100010001010100010001000001000101000101010100010101000000000100010001010101010100010000000101000101010001010000010000010101000101010000000001010000000100010001000100000000000101000000010100000101000101010000010001010000010001000001010401000001", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000100000100010000000001000101000100010001010100010001000101010000010100010101010101010001000101010100000100000000010101010000010101010100010000000000010100000100010101010000010100010100000101010001000000000001010000010000000001010100000000000000010100000000010100000100000000010001010000010101010101010001000100010001010100000101010000000101000101010100000101010100010101000100000001000000010100000101000001000100010000000001010101000001010100010001000000010100000001000001010001000100010000010101010101000101000000fd000101010101010101000000000101000001000000000101000100010001010101000000010101000101010101000100010001010101000000010000000001000000000100000101000000000001010001010000000101010000010001010001010000010100000001000000000101010001000001000001010000000100010100000000000001010000010100010100000001010000010100010000000100010100000100000001000100010000010101000101010100000000000000010100000001000000000100000001000000000001010001000100010101010101000000000001000101010001000001010001000100010100010001000001000000000001fd0001000000000001000001010100010000010001010000000101010001000100010100010101000001010000000101010100000100000100010001000100010001000100010001000100010101010100000100000101000000010101000000000101010100000000000000000101010000010101010001000100010000000101000001000001010100010001010101000001000000000001000000000001000101000000010101000001000001010001010001010100000000010100000101000100010000000100000100000100010000010001000000000101000100000101000101000100010000010100010001010001010101000100010101000100000001010401000100", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000100000100010000000001000101000100010001010100010001000101010000010100010101010101010001000101010100000100000000010101010000010101010100010000000000010100000100010101010000010100010100000101010001000000000001010000010000000001010100000000000000010100000000010100000100000000010001010000010101010101010001000100010001010100000101010000000101000101010100000101010100010101000100000001000000010100000101000001000100010000000001010101000001010100010001000000010100000001000001010001000100010000010101010101000101000000fd000101010101010101000000000101000001000000000101000100010001010101000000010101000101010101000100010001010101000000010000000001000000000100000101000000000001010001010000000101010000010001010001010000010100000001000000000101010001000001000001010000000100010100000000000001010000010100010100000001010000010100010000000100010100000100000001000100010000010101000101010100000000000000010100000001000000000100000001000000000001010001000100010101010101000000000001000101010001000001010001000100010100010001000001000000000001fd0001010000000100010101000001000001000100010000010000010101000101000000010100010000010001000000000100000101010000000101010101010101000000000101000101000000010001010001010000010100000000000001010100010001000100000001000100000100000000010100000101010001010101010100000001010000010101010000010101010000000101010001000101000100010101000001000100000101010000010100000101010100000101000000000001000001010001010101010101000001010100000001010100000100010101010001010000010001010000000000010001000101010100000001000001010001010401000101", -! "04fd000100000101010001000000010100000101010000000101000101000000010001010000000000010000000001010101000001010000010101000000000000000001010001000101010101010000000001000100000001010001000000010001000001000101000000000101000101000101000101010000000100000000010100010000000101010000010001010001010000010001010101010100000000010001010000010100000100010001010100010001000000000101010101000001000101010000010101000101000101000101000001000101000001010000010101000100000000000100000001010101010100010001000100000000000001010001fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000100000001010100010001010000010100010001010001010101000000010001010101000000000101010001010100010100010101000000000000000100010000010101000101000000000100010101000000010100000001010100000101000000010101000100000000010101010001010000010101010001000001010001000100000100000100010101000101010100010001010100000001000000010001010000010100000000000101000001010101010100010000010101000001010000010001000101010000000001000100010001000000010001000101000101000001000100010000010000010100000100000100010000000001010400000000", -! "04fd000100000101010001000000010100000101010000000101000101000000010001010000000000010000000001010101000001010000010101000000000000000001010001000101010101010000000001000100000001010001000000010001000001000101000000000101000101000101000101010000000100000000010100010000000101010000010001010001010000010001010101010100000000010001010000010100000100010001010100010001000000000101010101000001000101010000010101000101000101000101000001000101000001010000010101000100000000000100000001010101010100010001000100000000000001010001fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000000010001010101010100010100010001010001010000010100010101010101010001010101010100000001000101010101000000000101010000000101010001000100000101000000010000010100010001000100000101010000010000010100010101000000010001000101010101000000010001000001010100010000010000000101010000010100010001010001000000000101000101000001010101010000010000000001000001000001000100000101000001000100010101010000000001010000010001000001000101000001000001000100000101000001010000010101010001000000010001010001010001000101010001000400000001", -! "04fd000100000101010001000000010100000101010000000101000101000000010001010000000000010000000001010101000001010000010101000000000000000001010001000101010101010000000001000100000001010001000000010001000001000101000000000101000101000101000101010000000100000000010100010000000101010000010001010001010000010001010101010100000000010001010000010100000100010001010100010001000000000101010101000001000101010000010101000101000101000101000001000101000001010000010101000100000000000100000001010101010100010001000100000000000001010001fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000010000010000010000010000010100000001000100010000000000010001000001000100010101010001000100000001010001010001010001000100010100000100000101010101000100010001010100010101000001010101010000010001010100000001000101000100010001000101000101010101000000010101000100000001010101010000000101000101010100010101000000000000010100000000010001010100010000010101000000000000000001010100010100010000010000010100000001010000000001000000000000000100010001000001010000010100010001000100010101000100000100010001010100000100000400000100", -! "04fd000100000101010001000000010100000101010000000101000101000000010001010000000000010000000001010101000001010000010101000000000000000001010001000101010101010000000001000100000001010001000000010001000001000101000000000101000101000101000101010000000100000000010100010000000101010000010001010001010000010001010101010100000000010001010000010100000100010001010100010001000000000101010101000001000101010000010101000101000101000101000001000101000001010000010101000100000000000100000001010101010100010001000100000000000001010001fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000000000010100010100000000000001000000010001000100000100000000010000000000000001010100010101010100000101010100010100000001010100000100000000000000010100000000010000010101000100010000010101010100000101000100010000010000000100010100010000000101000000000001010100000001000101000100000000010101010000010000000100010001010000010000000100010000010000010101000101000101000100000100010100000001010000010101000101010001010000000100010001000001000000010100000001000100000100010000010100010000010000010001010101010001010400000101", -! "04fd000100000101010001000000010100000101010000000101000101000000010001010000000000010000000001010101000001010000010101000000000000000001010001000101010101010000000001000100000001010001000000010001000001000101000000000101000101000101000101010000000100000000010100010000000101010000010001010001010000010001010101010100000000010001010000010100000100010001010100010001000000000101010101000001000101010000010101000101000101000101000001000101000001010000010101000100000000000100000001010101010100010001000100000000000001010001fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000100000000000100010000000001000100000101010001000100000101010001010100010100010000000000010100000100010101000001000000010101000100010001010100010100010101010101010000010000000100000100000100000000010100010100000000010001000100000101010000000101000000000001000101010000000101010000010000000001010101000100000001010101000001000001000001010100010000000001010001000101000101010100000000010001010000000001000101010100010101010101010101000101000100010000010000010101000100010100010000000100000000000100000001010100010000fd0001000101000100000001010000000100000101000100000000010101010001010001000001010100010000000101010101000000010100000001000101000101010001000100010100010100000000010001010100010101000100000000010101000100010101000000000001000100000101010100000001010100000001010001010000010100010000010101000000000101000100000000000100010101000001010100000001000100010101000101010100010100010000000100010000010001010101010100010101010101000000010101010000000000010101000000010001000101000000000100000000010101000100000101010101010100000400010000", -! "04fd000100000101010001000000010100000101010000000101000101000000010001010000000000010000000001010101000001010000010101000000000000000001010001000101010101010000000001000100000001010001000000010001000001000101000000000101000101000101000101010000000100000000010100010000000101010000010001010001010000010001010101010100000000010001010000010100000100010001010100010001000000000101010101000001000101010000010101000101000101000101000001000101000001010000010101000100000000000100000001010101010100010001000100000000000001010001fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000100000000000100010000000001000100000101010001000100000101010001010100010100010000000000010100000100010101000001000000010101000100010001010100010100010101010101010000010000000100000100000100000000010100010100000000010001000100000101010000000101000000000001000101010000000101010000010000000001010101000100000001010101000001000001000001010100010000000001010001000101000101010100000000010001010000000001000101010100010101010101010101000101000100010000010000010101000100010100010000000100000000000100000001010100010000fd0001010101010101010100010101010100000000010100010100000000000000010100010101000100000100010000010100000100010000000001000000010001000101010000000000010000010000000000010000010100000001010101000000000001000000000100000100000101010101010101010101000100010101000101010000010101000100000100000000010000010000000101000000010101010000010101010100010101000100000000000001010100000101010101000001000001000101010001010101000000010100010100010100010000010100010001010101010001010100000001000101010101010001000000010000000001010400010001", -! "04fd000100000101010001000000010100000101010000000101000101000000010001010000000000010000000001010101000001010000010101000000000000000001010001000101010101010000000001000100000001010001000000010001000001000101000000000101000101000101000101010000000100000000010100010000000101010000010001010001010000010001010101010100000000010001010000010100000100010001010100010001000000000101010101000001000101010000010101000101000101000101000001000101000001010000010101000100000000000100000001010101010100010001000100000000000001010001fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000101000100010101000101000100010001000000010100010001010100000001010000000101010101000100010100000100010101010101010100000100010101000101000100010101000100010100000000000001010101000101000000010001010000010100010001000101010100000100010001010000000101000001000000000000000101010101000100010001010001000100000100010100010001000001000000000000000100010100010001010000010000000100010100000101010000000100010101000100010000000100010001000000010100000101000101000101010001000101010000010100010101010001000101010100000100fd0001000100010000000001010000000000000100010100010000000001010000000000010100000000010101000000000101010000010000000101000001000000010101000000000101010101000101000000010001000001000100000100010101000001010001000000000101000001000100000001000101000101010101010101000001010100000100010001010101010101000100010100010100010101010101000100000001000101000000010001010000010100000001000001000001010001000001000000010000010000010001000100010000000100000000010001010001010000010001000001000001010000010100010000000100010100010400010100", -! "04fd000100000101010001000000010100000101010000000101000101000000010001010000000000010000000001010101000001010000010101000000000000000001010001000101010101010000000001000100000001010001000000010001000001000101000000000101000101000101000101010000000100000000010100010000000101010000010001010001010000010001010101010100000000010001010000010100000100010001010100010001000000000101010101000001000101010000010101000101000101000101000001000101000001010000010101000100000000000100000001010101010100010001000100000000000001010001fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000101000100010101000101000100010001000000010100010001010100000001010000000101010101000100010100000100010101010101010100000100010101000101000100010101000100010100000000000001010101000101000000010001010000010100010001000101010100000100010001010000000101000001000000000000000101010101000100010001010001000100000100010100010001000001000000000000000100010100010001010000010000000100010100000101010000000100010101000100010000000100010001000000010100000101000101000101010001000101010000010100010101010001000101010100000100fd0001010000000100010100000001000101000101000001010001000001010101010001010000000100000001000001000000000101010001000101010100000100000100000000010001000101000101010000000101000000000000010100010000000100000101000000000000010001010001000001000100000101000100000001000100000101000101010101000001000001000100000101000100000101000100000001000101010101000001000100000001000000010001010101000101000001000000010000010001010001010100000000000000010000010000010000010100000001010000000000000001010101000001010101000101000000010400010101", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000101000100000101010000000101000101000101010001010000000001010101010001010101000001010000000101010000000000000001010100000001010101000000010101010101010001010000000001010100010000010101010001000000010100010000010000000101000101010000000101000100000000000000010000010100010000010101010001000101010100010101010100000101000000000000010001010001010100010101010101010000010101010001010101010000000000010001010100000100010101000101010100010001000000010001000001010000010001010001000000000101000100010100010100010100010000fd000101000100000000010101010000000001000001000101000001010001000101010100010101000101010000000101000100010001000001010000000000000001000101000101000001000101010101010000000000010101000001000100000101010000010101010101000000000001010001010101010001000100010100010100000000010101000100010100000101000100010000010101010001000001000101010100010000010101010101000100010100010001000000000100010000010000000000010001010001000100000001000001010101010000010101000101000100000000000101010101010000010101000100010001000100000000fd0001010100010100000000000001010101000101010100010100000100000100010000000000000000000001010000000101000100010001010100000101010100010100000000000000010100000101000100000101000001000000010000000100000001000101000101000000010100010000000000010000010100010101010001000101010001010101010001000000000000000001010100000101000100000001000101000100010100010001010101000100010101010000010001010100010000010101010001010001010101010000000001010101000100000001000001000101010100010101010101000100010101010100000000000001000101010401000000", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000101000100000101010000000101000101000101010001010000000001010101010001010101000001010000000101010000000000000001010100000001010101000000010101010101010001010000000001010100010000010101010001000000010100010000010000000101000101010000000101000100000000000000010000010100010000010101010001000101010100010101010100000101000000000000010001010001010100010101010101010000010101010001010101010000000000010001010100000100010101000101010100010001000000010001000001010000010001010001000000000101000100010100010100010100010000fd000101000100000000010101010000000001000001000101000001010001000101010100010101000101010000000101000100010001000001010000000000000001000101000101000001000101010101010000000000010101000001000100000101010000010101010101000000000001010001010101010001000100010100010100000000010101000100010100000101000100010000010101010001000001000101010100010000010101010101000100010100010001000000000100010000010000000000010001010001000100000001000001010101010000010101000101000100000000000101010101010000010101000100010001000100000000fd0001000101010000000001010101010101010101000101010001000100010101010101000100000000000101010100000101010001000101010001000100000000010100000001000101010100010001000000010101000000000000000001010101000000010100010001010000000001000101010000000100010101000000000000000101010100000101010100010001010100010001000001000101000101010100010101000000000100010001010101010100010000000101000101010001010000010000010101000101010000000001010000000100010001000100000000000101000000010100000101000101010000010001010000010001000001010401000001", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000101000100000101010000000101000101000101010001010000000001010101010001010101000001010000000101010000000000000001010100000001010101000000010101010101010001010000000001010100010000010101010001000000010100010000010000000101000101010000000101000100000000000000010000010100010000010101010001000101010100010101010100000101000000000000010001010001010100010101010101010000010101010001010101010000000000010001010100000100010101000101010100010001000000010001000001010000010001010001000000000101000100010100010100010100010000fd000101010101010101000000000101000001000000000101000100010001010101000000010101000101010101000100010001010101000000010000000001000000000100000101000000000001010001010000000101010000010001010001010000010100000001000000000101010001000001000001010000000100010100000000000001010000010100010100000001010000010100010000000100010100000100000001000100010000010101000101010100000000000000010100000001000000000100000001000000000001010001000100010101010101000000000001000101010001000001010001000100010100010001000001000000000001fd0001000000000001000001010100010000010001010000000101010001000100010100010101000001010000000101010100000100000100010001000100010001000100010001000100010101010100000100000101000000010101000000000101010100000000000000000101010000010101010001000100010000000101000001000001010100010001010101000001000000000001000000000001000101000000010101000001000001010001010001010100000000010100000101000100010000000100000100000100010000010001000000000101000100000101000101000100010000010100010001010001010101000100010101000100000001010401000100", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000101000100000101010000000101000101000101010001010000000001010101010001010101000001010000000101010000000000000001010100000001010101000000010101010101010001010000000001010100010000010101010001000000010100010000010000000101000101010000000101000100000000000000010000010100010000010101010001000101010100010101010100000101000000000000010001010001010100010101010101010000010101010001010101010000000000010001010100000100010101000101010100010001000000010001000001010000010001010001000000000101000100010100010100010100010000fd000101010101010101000000000101000001000000000101000100010001010101000000010101000101010101000100010001010101000000010000000001000000000100000101000000000001010001010000000101010000010001010001010000010100000001000000000101010001000001000001010000000100010100000000000001010000010100010100000001010000010100010000000100010100000100000001000100010000010101000101010100000000000000010100000001000000000100000001000000000001010001000100010101010101000000000001000101010001000001010001000100010100010001000001000000000001fd0001010000000100010101000001000001000100010000010000010101000101000000010100010000010001000000000100000101010000000101010101010101000000000101000101000000010001010001010000010100000000000001010100010001000100000001000100000100000000010100000101010001010101010100000001010000010101010000010101010000000101010001000101000100010101000001000100000101010000010100000101010100000101000000000001000001010001010101010101000001010100000001010100000100010101010001010000010001010000000000010001000101010100000001000001010001010401000101", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000101010100010100000001000001000101000000010001000000010001010000000100010000000101010100000101010101000000000000000001000100000001010000010100000101000000000000000000010101000100000000010000010000000101000000010101010001000001000000000001010001000101010001000000000001000001000100010101010101000001000101000100000101000100000100010001010100010101000100010101000001000100000100000100010001010000000101010000010100000101000100000100000000010000000101010000010101010100000101010000000001010101000101000000010000010001fd000101010001010001000001000100010100010000010100000001000101010101000000000100010101010001010100000101000101000100000001010001000001000101000000010000000101000001010001000100010101010000010100000100010101000101010100000101010101010001010101010001010000010001000100000001010000010101000001000101010001000100000100000100000001010100000000000001010001000001000001010000000100000100000000010101000101010001000101010101010100010101010100000101010100010001000000000101000000000001010001010101000100010000010101000101000000fd0001000000010100000001000000000000000100000100010100000101010101010101010000010000000000010000000100000101000000010101000000000000000100010001000000000100000100000101010000000101000000010100010001000001010000010001000101010001010100010000010100000101010100000101000001000000000101010100010101010100010000000001000100000000010000000001010100010000010101000001000001000000000100010101000000000100000100000001010101000100010100000001010001000101000000010100010000010000010001000100010101010100000001010001010100010000010401010000", -! "04fd000100000101010000010001000101000101000101010100010101010000010000000001000100000100000101010101010100000000000100010101000001010100000101000000000101000000000100010101010000000100010001000001000001010100010100010101000001000001010001010001010000000001010101010001010100000100010101010100010001000000000101000001000000000001000001000101010001010001010100010101010001000101010100010001000000000000000001010001010101000001000100000001010001000101000100000101010100010001000100010101000000010001000101000000000101000000fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000100000001010100010001010000010100010001010001010101000000010001010101000000000101010001010100010100010101000000000000000100010000010101000101000000000100010101000000010100000001010100000101000000010101000100000000010101010001010000010101010001000001010001000100000100000100010101000101010100010001010100000001000000010001010000010100000000000101000001010101010100010000010101000001010000010001000101010000000001000100010001000000010001000101000101000001000100010000010000010100000100000100010000000001010400000000", -! "04fd000100000101010000010001000101000101000101010100010101010000010000000001000100000100000101010101010100000000000100010101000001010100000101000000000101000000000100010101010000000100010001000001000001010100010100010101000001000001010001010001010000000001010101010001010100000100010101010100010001000000000101000001000000000001000001000101010001010001010100010101010001000101010100010001000000000000000001010001010101000001000100000001010001000101000100000101010100010001000100010101000000010001000101000000000101000000fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000000010001010101010100010100010001010001010000010100010101010101010001010101010100000001000101010101000000000101010000000101010001000100000101000000010000010100010001000100000101010000010000010100010101000000010001000101010101000000010001000001010100010000010000000101010000010100010001010001000000000101000101000001010101010000010000000001000001000001000100000101000001000100010101010000000001010000010001000001000101000001000001000100000101000001010000010101010001000000010001010001010001000101010001000400000001", -! "04fd000100000101010000010001000101000101000101010100010101010000010000000001000100000100000101010101010100000000000100010101000001010100000101000000000101000000000100010101010000000100010001000001000001010100010100010101000001000001010001010001010000000001010101010001010100000100010101010100010001000000000101000001000000000001000001000101010001010001010100010101010001000101010100010001000000000000000001010001010101000001000100000001010001000101000100000101010100010001000100010101000000010001000101000000000101000000fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000010000010000010000010000010100000001000100010000000000010001000001000100010101010001000100000001010001010001010001000100010100000100000101010101000100010001010100010101000001010101010000010001010100000001000101000100010001000101000101010101000000010101000100000001010101010000000101000101010100010101000000000000010100000000010001010100010000010101000000000000000001010100010100010000010000010100000001010000000001000000000000000100010001000001010000010100010001000100010101000100000100010001010100000100000400000100", -! "04fd000100000101010000010001000101000101000101010100010101010000010000000001000100000100000101010101010100000000000100010101000001010100000101000000000101000000000100010101010000000100010001000001000001010100010100010101000001000001010001010001010000000001010101010001010100000100010101010100010001000000000101000001000000000001000001000101010001010001010100010101010001000101010100010001000000000000000001010001010101000001000100000001010001000101000100000101010100010001000100010101000000010001000101000000000101000000fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000000000010100010100000000000001000000010001000100000100000000010000000000000001010100010101010100000101010100010100000001010100000100000000000000010100000000010000010101000100010000010101010100000101000100010000010000000100010100010000000101000000000001010100000001000101000100000000010101010000010000000100010001010000010000000100010000010000010101000101000101000100000100010100000001010000010101000101010001010000000100010001000001000000010100000001000100000100010000010100010000010000010001010101010001010400000101", -! "04fd000100000101010000010001000101000101000101010100010101010000010000000001000100000100000101010101010100000000000100010101000001010100000101000000000101000000000100010101010000000100010001000001000001010100010100010101000001000001010001010001010000000001010101010001010100000100010101010100010001000000000101000001000000000001000001000101010001010001010100010101010001000101010100010001000000000000000001010001010101000001000100000001010001000101000100000101010100010001000100010101000000010001000101000000000101000000fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000100000000000100010000000001000100000101010001000100000101010001010100010100010000000000010100000100010101000001000000010101000100010001010100010100010101010101010000010000000100000100000100000000010100010100000000010001000100000101010000000101000000000001000101010000000101010000010000000001010101000100000001010101000001000001000001010100010000000001010001000101000101010100000000010001010000000001000101010100010101010101010101000101000100010000010000010101000100010100010000000100000000000100000001010100010000fd0001000101000100000001010000000100000101000100000000010101010001010001000001010100010000000101010101000000010100000001000101000101010001000100010100010100000000010001010100010101000100000000010101000100010101000000000001000100000101010100000001010100000001010001010000010100010000010101000000000101000100000000000100010101000001010100000001000100010101000101010100010100010000000100010000010001010101010100010101010101000000010101010000000000010101000000010001000101000000000100000000010101000100000101010101010100000400010000", -! "04fd000100000101010000010001000101000101000101010100010101010000010000000001000100000100000101010101010100000000000100010101000001010100000101000000000101000000000100010101010000000100010001000001000001010100010100010101000001000001010001010001010000000001010101010001010100000100010101010100010001000000000101000001000000000001000001000101010001010001010100010101010001000101010100010001000000000000000001010001010101000001000100000001010001000101000100000101010100010001000100010101000000010001000101000000000101000000fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000100000000000100010000000001000100000101010001000100000101010001010100010100010000000000010100000100010101000001000000010101000100010001010100010100010101010101010000010000000100000100000100000000010100010100000000010001000100000101010000000101000000000001000101010000000101010000010000000001010101000100000001010101000001000001000001010100010000000001010001000101000101010100000000010001010000000001000101010100010101010101010101000101000100010000010000010101000100010100010000000100000000000100000001010100010000fd0001010101010101010100010101010100000000010100010100000000000000010100010101000100000100010000010100000100010000000001000000010001000101010000000000010000010000000000010000010100000001010101000000000001000000000100000100000101010101010101010101000100010101000101010000010101000100000100000000010000010000000101000000010101010000010101010100010101000100000000000001010100000101010101000001000001000101010001010101000000010100010100010100010000010100010001010101010001010100000001000101010101010001000000010000000001010400010001", -! "04fd000100000101010000010001000101000101000101010100010101010000010000000001000100000100000101010101010100000000000100010101000001010100000101000000000101000000000100010101010000000100010001000001000001010100010100010101000001000001010001010001010000000001010101010001010100000100010101010100010001000000000101000001000000000001000001000101010001010001010100010101010001000101010100010001000000000000000001010001010101000001000100000001010001000101000100000101010100010001000100010101000000010001000101000000000101000000fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000101000100010101000101000100010001000000010100010001010100000001010000000101010101000100010100000100010101010101010100000100010101000101000100010101000100010100000000000001010101000101000000010001010000010100010001000101010100000100010001010000000101000001000000000000000101010101000100010001010001000100000100010100010001000001000000000000000100010100010001010000010000000100010100000101010000000100010101000100010000000100010001000000010100000101000101000101010001000101010000010100010101010001000101010100000100fd0001000100010000000001010000000000000100010100010000000001010000000000010100000000010101000000000101010000010000000101000001000000010101000000000101010101000101000000010001000001000100000100010101000001010001000000000101000001000100000001000101000101010101010101000001010100000100010001010101010101000100010100010100010101010101000100000001000101000000010001010000010100000001000001000001010001000001000000010000010000010001000100010000000100000000010001010001010000010001000001000001010000010100010000000100010100010400010100", -! "04fd000100000101010000010001000101000101000101010100010101010000010000000001000100000100000101010101010100000000000100010101000001010100000101000000000101000000000100010101010000000100010001000001000001010100010100010101000001000001010001010001010000000001010101010001010100000100010101010100010001000000000101000001000000000001000001000101010001010001010100010101010001000101010100010001000000000000000001010001010101000001000100000001010001000101000100000101010100010001000100010101000000010001000101000000000101000000fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000101000100010101000101000100010001000000010100010001010100000001010000000101010101000100010100000100010101010101010100000100010101000101000100010101000100010100000000000001010101000101000000010001010000010100010001000101010100000100010001010000000101000001000000000000000101010101000100010001010001000100000100010100010001000001000000000000000100010100010001010000010000000100010100000101010000000100010101000100010000000100010001000000010100000101000101000101010001000101010000010100010101010001000101010100000100fd0001010000000100010100000001000101000101000001010001000001010101010001010000000100000001000001000000000101010001000101010100000100000100000000010001000101000101010000000101000000000000010100010000000100000101000000000000010001010001000001000100000101000100000001000100000101000101010101000001000001000100000101000100000101000100000001000101010101000001000100000001000000010001010101000101000001000000010000010001010001010100000000000000010000010000010000010100000001010000000000000001010101000001010101000101000000010400010101", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000100010101000101000100000001000100000100010100000100010000000001000100010000000000010100000101000100010001000101010100010101000000010000000001010100010001010000010001000101000001010101010001000000000000000000000000000100000101010100000100000101000000000001000001010100000001000001000000000101010100010100010000010100010001010100000000000000010101000101000001000101000001000101000000000001000100010101000001010101010100000101010000010101010000010000000101010001010100010101000001010001010001000100000001000100010000fd000101000100000000010101010000000001000001000101000001010001000101010100010101000101010000000101000100010001000001010000000000000001000101000101000001000101010101010000000000010101000001000100000101010000010101010101000000000001010001010101010001000100010100010100000000010101000100010100000101000100010000010101010001000001000101010100010000010101010101000100010100010001000000000100010000010000000000010001010001000100000001000001010101010000010101000101000100000000000101010101010000010101000100010001000100000000fd0001010100010100000000000001010101000101010100010100000100000100010000000000000000000001010000000101000100010001010100000101010100010100000000000000010100000101000100000101000001000000010000000100000001000101000101000000010100010000000000010000010100010101010001000101010001010101010001000000000000000001010100000101000100000001000101000100010100010001010101000100010101010000010001010100010000010101010001010001010101010000000001010101000100000001000001000101010100010101010101000100010101010100000000000001000101010401000000", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000100010101000101000100000001000100000100010100000100010000000001000100010000000000010100000101000100010001000101010100010101000000010000000001010100010001010000010001000101000001010101010001000000000000000000000000000100000101010100000100000101000000000001000001010100000001000001000000000101010100010100010000010100010001010100000000000000010101000101000001000101000001000101000000000001000100010101000001010101010100000101010000010101010000010000000101010001010100010101000001010001010001000100000001000100010000fd000101000100000000010101010000000001000001000101000001010001000101010100010101000101010000000101000100010001000001010000000000000001000101000101000001000101010101010000000000010101000001000100000101010000010101010101000000000001010001010101010001000100010100010100000000010101000100010100000101000100010000010101010001000001000101010100010000010101010101000100010100010001000000000100010000010000000000010001010001000100000001000001010101010000010101000101000100000000000101010101010000010101000100010001000100000000fd0001000101010000000001010101010101010101000101010001000100010101010101000100000000000101010100000101010001000101010001000100000000010100000001000101010100010001000000010101000000000000000001010101000000010100010001010000000001000101010000000100010101000000000000000101010100000101010100010001010100010001000001000101000101010100010101000000000100010001010101010100010000000101000101010001010000010000010101000101010000000001010000000100010001000100000000000101000000010100000101000101010000010001010000010001000001010401000001", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000100010101000101000100000001000100000100010100000100010000000001000100010000000000010100000101000100010001000101010100010101000000010000000001010100010001010000010001000101000001010101010001000000000000000000000000000100000101010100000100000101000000000001000001010100000001000001000000000101010100010100010000010100010001010100000000000000010101000101000001000101000001000101000000000001000100010101000001010101010100000101010000010101010000010000000101010001010100010101000001010001010001000100000001000100010000fd000101010101010101000000000101000001000000000101000100010001010101000000010101000101010101000100010001010101000000010000000001000000000100000101000000000001010001010000000101010000010001010001010000010100000001000000000101010001000001000001010000000100010100000000000001010000010100010100000001010000010100010000000100010100000100000001000100010000010101000101010100000000000000010100000001000000000100000001000000000001010001000100010101010101000000000001000101010001000001010001000100010100010001000001000000000001fd0001000000000001000001010100010000010001010000000101010001000100010100010101000001010000000101010100000100000100010001000100010001000100010001000100010101010100000100000101000000010101000000000101010100000000000000000101010000010101010001000100010000000101000001000001010100010001010101000001000000000001000000000001000101000000010101000001000001010001010001010100000000010100000101000100010000000100000100000100010000010001000000000101000100000101000101000100010000010100010001010001010101000100010101000100000001010401000100", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000100010101000101000100000001000100000100010100000100010000000001000100010000000000010100000101000100010001000101010100010101000000010000000001010100010001010000010001000101000001010101010001000000000000000000000000000100000101010100000100000101000000000001000001010100000001000001000000000101010100010100010000010100010001010100000000000000010101000101000001000101000001000101000000000001000100010101000001010101010100000101010000010101010000010000000101010001010100010101000001010001010001000100000001000100010000fd000101010101010101000000000101000001000000000101000100010001010101000000010101000101010101000100010001010101000000010000000001000000000100000101000000000001010001010000000101010000010001010001010000010100000001000000000101010001000001000001010000000100010100000000000001010000010100010100000001010000010100010000000100010100000100000001000100010000010101000101010100000000000000010100000001000000000100000001000000000001010001000100010101010101000000000001000101010001000001010001000100010100010001000001000000000001fd0001010000000100010101000001000001000100010000010000010101000101000000010100010000010001000000000100000101010000000101010101010101000000000101000101000000010001010001010000010100000000000001010100010001000100000001000100000100000000010100000101010001010101010100000001010000010101010000010101010000000101010001000101000100010101000001000100000101010000010100000101010100000101000000000001000001010001010101010101000001010100000001010100000100010101010001010000010001010000000000010001000101010100000001000001010001010401000101", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000101010100010100000001000001000101000000010001000000010001010000000100010000000101010100000101010101000000000000000001000100000001010000010100000101000000000000000000010101000100000000010000010000000101000000010101010001000001000000000001010001000101010001000000000001000001000100010101010101000001000101000100000101000100000100010001010100010101000100010101000001000100000100000100010001010000000101010000010100000101000100000100000000010000000101010000010101010100000101010000000001010101000101000000010000010001fd000100000001010000000000000001010000000001010101000100000001010100000100010000000000000001010100010100010001000100010000000101000001010001000001010000010001000100010000000101010100010101000101000001000000010001010101010100000001000101000000010100000100000000000000000000000100010101010001010100010000010000000000010100000000000001010000000100000101000001000101010100000101000000000000000000000101000101000100010001000000000100000001000000000000000001000100000001010001000100000101010100000101010101000100000100010100fd0001000000010100000001000000000000000100000100010100000101010101010101010000010000000000010000000100000101000000010101000000000000000100010001000000000100000100000101010000000101000000010100010001000001010000010001000101010001010100010000010100000101010100000101000001000000000101010100010101010100010000000001000100000000010000000001010100010000010101000001000001000000000100010101000000000100000100000001010101000100010100000001010001000101000000010100010000010000010001000100010101010100000001010001010100010000010401010000", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000101010100010100000001000001000101000000010001000000010001010000000100010000000101010100000101010101000000000000000001000100000001010000010100000101000000000000000000010101000100000000010000010000000101000000010101010001000001000000000001010001000101010001000000000001000001000100010101010101000001000101000100000101000100000100010001010100010101000100010101000001000100000100000100010001010000000101010000010100000101000100000100000000010000000101010000010101010100000101010000000001010101000101000000010000010001fd000100000001010000000000000001010000000001010101000100000001010100000100010000000000000001010100010100010001000100010000000101000001010001000001010000010001000100010000000101010100010101000101000001000000010001010101010100000001000101000000010100000100000000000000000000000100010101010001010100010000010000000000010100000000000001010000000100000101000001000101010100000101000000000000000000000101000101000100010001000000000100000001000000000000000001000100000001010001000100000101010100000101010101000100000100010100fd0001010001010101010000000101010101010001010001010000000000010100000000000001010101010000000100010100000001000100000000000100000100000000000101000001000000010101010001010000010101010000000101010101000101010100000001010000010001000101010000000101010101010101010101000101000000000101000101010001010101010101000101000100000101000001010100000001010001010100010101000001000001010000010000010101000101010101000001010100000101000101010001000101010100000100000100000100000000000000000101000100000000000100000100000001000001000401010001", -! "04fd000100010000000100010100000001010000010001000100010100010000000100000100000100000100010100000101010001000000010000010101000000010100010001010001000100000000000000010001010000000001010101000000000000010001010000000000010101010000000001000000000100000001000100010101010000010101010000010000000000000000010100010100010101000001000101000001000001000100000100010000010101000101000100000100000101010100000000010001000100000100010000000000010001000000010100010001010001000100000001010100000101000001000000010100010001010101fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000100000001010100010001010000010100010001010001010101000000010001010101000000000101010001010100010100010101000000000000000100010000010101000101000000000100010101000000010100000001010100000101000000010101000100000000010101010001010000010101010001000001010001000100000100000100010101000101010100010001010100000001000000010001010000010100000000000101000001010101010100010000010101000001010000010001000101010000000001000100010001000000010001000101000101000001000100010000010000010100000100000100010000000001010400000000", -! "04fd000100010000000100010100000001010000010001000100010100010000000100000100000100000100010100000101010001000000010000010101000000010100010001010001000100000000000000010001010000000001010101000000000000010001010000000000010101010000000001000000000100000001000100010101010000010101010000010000000000000000010100010100010101000001000101000001000001000100000100010000010101000101000100000100000101010100000000010001000100000100010000000000010001000000010100010001010001000100000001010100000101000001000000010100010001010101fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000100000101000001010000000101000101010101000000000101000001010000000001000000010001010001010101000101010000000101010000010100010101000100010001000101010100000000010101010000010000010101000000000101010001010101000100010100000101010000010001000101000100010001010001000000010100010001010100000101010100000100000001010001010101000001000001010000010101010000000100010000010100000100010000000100010001000000000000000000000100000101010101010101000001000000000001010000010000000001010001010000000101010100010001010100fd0001000101000000010001010101010100010100010001010001010000010100010101010101010001010101010100000001000101010101000000000101010000000101010001000100000101000000010000010100010001000100000101010000010000010100010101000000010001000101010101000000010001000001010100010000010000000101010000010100010001010001000000000101000101000001010101010000010000000001000001000001000100000101000001000100010101010000000001010000010001000001000101000001000001000100000101000001010000010101010001000000010001010001010001000101010001000400000001", -! "04fd000100010000000100010100000001010000010001000100010100010000000100000100000100000100010100000101010001000000010000010101000000010100010001010001000100000000000000010001010000000001010101000000000000010001010000000000010101010000000001000000000100000001000100010101010000010101010000010000000000000000010100010100010101000001000101000001000001000100000100010000010101000101000100000100000101010100000000010001000100000100010000000000010001000000010100010001010001000100000001010100000101000001000000010100010001010101fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000010000010000010000010000010100000001000100010000000000010001000001000100010101010001000100000001010001010001010001000100010100000100000101010101000100010001010100010101000001010101010000010001010100000001000101000100010001000101000101010101000000010101000100000001010101010000000101000101010100010101000000000000010100000000010001010100010000010101000000000000000001010100010100010000010000010100000001010000000001000000000000000100010001000001010000010100010001000100010101000100000100010001010100000100000400000100", -! "04fd000100010000000100010100000001010000010001000100010100010000000100000100000100000100010100000101010001000000010000010101000000010100010001010001000100000000000000010001010000000001010101000000000000010001010000000000010101010000000001000000000100000001000100010101010000010101010000010000000000000000010100010100010101000001000101000001000001000100000100010000010101000101000100000100000101010100000000010001000100000100010000000000010001000000010100010001010001000100000001010100000101000001000000010100010001010101fd000100000001000000010000010001010100000101010100000101000100010101010001010000000000000000010100010001000100010001000000010101010000000000000100010000010000010000000101010000010100010100000000010100010101010000010000010100000000010100000101000001000100010100010001000001000101000100010100010000000101000001010001000000000000010001000000010100010101000001010100010000000001000100000101000100010101010001010001010101000001000101000100000100010101010101000001000101010100010101000001010100000101000000000101000101010001fd000101000001010101010001000101000101000001000100010100000001010101000001000001000101010101010001010101010100000101010000010100000001010000000101000100000000010001000000000101010101000100000000000100010101010100000100010000010100010001010101000001000100000001010001010000000000000101010001010100000000000001000001000101000101000001010101000100000001000000010101010000000000000101010001000001000101010000010001000001010000010100010001000100010001010100000101010001000001010101010000010101000000000101000000000101000000fd0001010000000000010100010100000000000001000000010001000100000100000000010000000000000001010100010101010100000101010100010100000001010100000100000000000000010100000000010000010101000100010000010101010100000101000100010000010000000100010100010000000101000000000001010100000001000101000100000000010101010000010000000100010001010000010000000100010000010000010101000101000101000100000100010100000001010000010101000101010001010000000100010001000001000000010100000001000100000100010000010100010000010000010001010101010001010400000101", -! "04fd000100010000000100010100000001010000010001000100010100010000000100000100000100000100010100000101010001000000010000010101000000010100010001010001000100000000000000010001010000000001010101000000000000010001010000000000010101010000000001000000000100000001000100010101010000010101010000010000000000000000010100010100010101000001000101000001000001000100000100010000010101000101000100000100000101010100000000010001000100000100010000000000010001000000010100010001010001000100000001010100000101000001000000010100010001010101fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000100000000000100010000000001000100000101010001000100000101010001010100010100010000000000010100000100010101000001000000010101000100010001010100010100010101010101010000010000000100000100000100000000010100010100000000010001000100000101010000000101000000000001000101010000000101010000010000000001010101000100000001010101000001000001000001010100010000000001010001000101000101010100000000010001010000000001000101010100010101010101010101000101000100010000010000010101000100010100010000000100000000000100000001010100010000fd0001000101000100000001010000000100000101000100000000010101010001010001000001010100010000000101010101000000010100000001000101000101010001000100010100010100000000010001010100010101000100000000010101000100010101000000000001000100000101010100000001010100000001010001010000010100010000010101000000000101000100000000000100010101000001010100000001000100010101000101010100010100010000000100010000010001010101010100010101010101000000010101010000000000010101000000010001000101000000000100000000010101000100000101010101010100000400010000", -! "04fd000100010000000100010100000001010000010001000100010100010000000100000100000100000100010100000101010001000000010000010101000000010100010001010001000100000000000000010001010000000001010101000000000000010001010000000000010101010000000001000000000100000001000100010101010000010101010000010000000000000000010100010100010101000001000101000001000001000100000100010000010101000101000100000100000101010100000000010001000100000100010000000000010001000000010100010001010001000100000001010100000101000001000000010100010001010101fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000100000000000100010000000001000100000101010001000100000101010001010100010100010000000000010100000100010101000001000000010101000100010001010100010100010101010101010000010000000100000100000100000000010100010100000000010001000100000101010000000101000000000001000101010000000101010000010000000001010101000100000001010101000001000001000001010100010000000001010001000101000101010100000000010001010000000001000101010100010101010101010101000101000100010000010000010101000100010100010000000100000000000100000001010100010000fd0001010101010101010100010101010100000000010100010100000000000000010100010101000100000100010000010100000100010000000001000000010001000101010000000000010000010000000000010000010100000001010101000000000001000000000100000100000101010101010101010101000100010101000101010000010101000100000100000000010000010000000101000000010101010000010101010100010101000100000000000001010100000101010101000001000001000101010001010101000000010100010100010100010000010100010001010101010001010100000001000101010101010001000000010000000001010400010001", -! "04fd000100010000000100010100000001010000010001000100010100010000000100000100000100000100010100000101010001000000010000010101000000010100010001010001000100000000000000010001010000000001010101000000000000010001010000000000010101010000000001000000000100000001000100010101010000010101010000010000000000000000010100010100010101000001000101000001000001000100000100010000010101000101000100000100000101010100000000010001000100000100010000000000010001000000010100010001010001000100000001010100000101000001000000010100010001010101fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000101000100010101000101000100010001000000010100010001010100000001010000000101010101000100010100000100010101010101010100000100010101000101000100010101000100010100000000000001010101000101000000010001010000010100010001000101010100000100010001010000000101000001000000000000000101010101000100010001010001000100000100010100010001000001000000000000000100010100010001010000010000000100010100000101010000000100010101000100010000000100010001000000010100000101000101000101010001000101010000010100010101010001000101010100000100fd0001000100010000000001010000000000000100010100010000000001010000000000010100000000010101000000000101010000010000000101000001000000010101000000000101010101000101000000010001000001000100000100010101000001010001000000000101000001000100000001000101000101010101010101000001010100000100010001010101010101000100010100010100010101010101000100000001000101000000010001010000010100000001000001000001010001000001000000010000010000010001000100010000000100000000010001010001010000010001000001000001010000010100010000000100010100010400010100", -! "04fd000100010000000100010100000001010000010001000100010100010000000100000100000100000100010100000101010001000000010000010101000000010100010001010001000100000000000000010001010000000001010101000000000000010001010000000000010101010000000001000000000100000001000100010101010000010101010000010000000000000000010100010100010101000001000101000001000001000100000100010000010101000101000100000100000101010100000000010001000100000100010000000000010001000000010100010001010001000100000001010100000101000001000000010100010001010101fd000100010000000101000101000000000100010101010101010000010001000000000101010001000000010100000001010000010100010001000100000001000101000100000000000000000100010001010101000101010101000000000001010100000001010101010001000100000100010100000001010101010101000100010000000001000001010101010001010101000100000000000001000000010001010000010001010101010101000001010000000101000000010000000001010001000101000001000100000000000100000001010101010000000100010000000100000001000100010000010000010100010100010100010100000101010101fd000101000100010101000101000100010001000000010100010001010100000001010000000101010101000100010100000100010101010101010100000100010101000101000100010101000100010100000000000001010101000101000000010001010000010100010001000101010100000100010001010000000101000001000000000000000101010101000100010001010001000100000100010100010001000001000000000000000100010100010001010000010000000100010100000101010000000100010101000100010000000100010001000000010100000101000101000101010001000101010000010100010101010001000101010100000100fd0001010000000100010100000001000101000101000001010001000001010101010001010000000100000001000001000000000101010001000101010100000100000100000000010001000101000101010000000101000000000000010100010000000100000101000000000000010001010001000001000100000101000100000001000100000101000101010101000001000001000100000101000100000101000100000001000101010101000001000100000001000000010001010101000101000001000000010000010001010001010100000000000000010000010000010000010100000001010000000000000001010101000001010101000101000000010400010101", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000100000101000000000001000100000100000000000001000101010001010001010100010101010100010100000100010001000101000101010100010100000000000000010101010001010000000001000001000100000101010000000001000000010100000101010101000000000100010101010101010000010000000000010101010100010101010000000001000000010001010101000100010100010000000100010001000001000000000101010100010101010000010101010000010001010101000101010101000100010101010001010101000100010001000001000000010000000000000101010101010100010100000100000001000000000001fd000101000100000000010101010000000001000001000101000001010001000101010100010101000101010000000101000100010001000001010000000000000001000101000101000001000101010101010000000000010101000001000100000101010000010101010101000000000001010001010101010001000100010100010100000000010101000100010100000101000100010000010101010001000001000101010100010000010101010101000100010100010001000000000100010000010000000000010001010001000100000001000001010101010000010101000101000100000000000101010101010000010101000100010001000100000000fd0001010100010100000000000001010101000101010100010100000100000100010000000000000000000001010000000101000100010001010100000101010100010100000000000000010100000101000100000101000001000000010000000100000001000101000101000000010100010000000000010000010100010101010001000101010001010101010001000000000000000001010100000101000100000001000101000100010100010001010101000100010101010000010001010100010000010101010001010001010101010000000001010101000100000001000001000101010100010101010101000100010101010100000000000001000101010401000000", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000100000101000000000001000100000100000000000001000101010001010001010100010101010100010100000100010001000101000101010100010100000000000000010101010001010000000001000001000100000101010000000001000000010100000101010101000000000100010101010101010000010000000000010101010100010101010000000001000000010001010101000100010100010000000100010001000001000000000101010100010101010000010101010000010001010101000101010101000100010101010001010101000100010001000001000000010000000000000101010101010100010100000100000001000000000001fd000101000100000000010101010000000001000001000101000001010001000101010100010101000101010000000101000100010001000001010000000000000001000101000101000001000101010101010000000000010101000001000100000101010000010101010101000000000001010001010101010001000100010100010100000000010101000100010100000101000100010000010101010001000001000101010100010000010101010101000100010100010001000000000100010000010000000000010001010001000100000001000001010101010000010101000101000100000000000101010101010000010101000100010001000100000000fd0001000101010000000001010101010101010101000101010001000100010101010101000100000000000101010100000101010001000101010001000100000000010100000001000101010100010001000000010101000000000000000001010101000000010100010001010000000001000101010000000100010101000000000000000101010100000101010100010001010100010001000001000101000101010100010101000000000100010001010101010100010000000101000101010001010000010000010101000101010000000001010000000100010001000100000000000101000000010100000101000101010000010001010000010001000001010401000001", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000100000101000000000001000100000100000000000001000101010001010001010100010101010100010100000100010001000101000101010100010100000000000000010101010001010000000001000001000100000101010000000001000000010100000101010101000000000100010101010101010000010000000000010101010100010101010000000001000000010001010101000100010100010000000100010001000001000000000101010100010101010000010101010000010001010101000101010101000100010101010001010101000100010001000001000000010000000000000101010101010100010100000100000001000000000001fd000101010101010101000000000101000001000000000101000100010001010101000000010101000101010101000100010001010101000000010000000001000000000100000101000000000001010001010000000101010000010001010001010000010100000001000000000101010001000001000001010000000100010100000000000001010000010100010100000001010000010100010000000100010100000100000001000100010000010101000101010100000000000000010100000001000000000100000001000000000001010001000100010101010101000000000001000101010001000001010001000100010100010001000001000000000001fd0001000000000001000001010100010000010001010000000101010001000100010100010101000001010000000101010100000100000100010001000100010001000100010001000100010101010100000100000101000000010101000000000101010100000000000000000101010000010101010001000100010000000101000001000001010100010001010101000001000000000001000000000001000101000000010101000001000001010001010001010100000000010100000101000100010000000100000100000100010000010001000000000101000100000101000101000100010000010100010001010001010101000100010101000100000001010401000100", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000100000101000000000001000100000100000000000001000101010001010001010100010101010100010100000100010001000101000101010100010100000000000000010101010001010000000001000001000100000101010000000001000000010100000101010101000000000100010101010101010000010000000000010101010100010101010000000001000000010001010101000100010100010000000100010001000001000000000101010100010101010000010101010000010001010101000101010101000100010101010001010101000100010001000001000000010000000000000101010101010100010100000100000001000000000001fd000101010101010101000000000101000001000000000101000100010001010101000000010101000101010101000100010001010101000000010000000001000000000100000101000000000001010001010000000101010000010001010001010000010100000001000000000101010001000001000001010000000100010100000000000001010000010100010100000001010000010100010000000100010100000100000001000100010000010101000101010100000000000000010100000001000000000100000001000000000001010001000100010101010101000000000001000101010001000001010001000100010100010001000001000000000001fd0001010000000100010101000001000001000100010000010000010101000101000000010100010000010001000000000100000101010000000101010101010101000000000101000101000000010001010001010000010100000000000001010100010001000100000001000100000100000000010100000101010001010101010100000001010000010101010000010101010000000101010001000101000100010101000001000100000101010000010100000101010100000101000000000001000001010001010101010101000001010100000001010100000100010101010001010000010001010000000000010001000101010100000001000001010001010401000101", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000101010100010100000001000001000101000000010001000000010001010000000100010000000101010100000101010101000000000000000001000100000001010000010100000101000000000000000000010101000100000000010000010000000101000000010101010001000001000000000001010001000101010001000000000001000001000100010101010101000001000101000100000101000100000100010001010100010101000100010101000001000100000100000100010001010000000101010000010100000101000100000100000000010000000101010000010101010100000101010000000001010101000101000000010000010001fd000100000100010101010001010101000100010000010001010001010100010100000101000000010101000001000001000100010100010000010001000000010001000001010000010101000100010000010100000101000001010100010100010100010100000101010100000000010100010101010001010000000000000000010001010001000101010100000101010101010001010100000100010000010001010100000100000100000101000100010000010100000001000100010000000101000000000001010001010101010101010001000101010100010000000001010101000101000001000001010101000000010001000000000101010001010101fd0001000000010100000001000000000000000100000100010100000101010101010101010000010000000000010000000100000101000000010101000000000000000100010001000000000100000100000101010000000101000000010100010001000001010000010001000101010001010100010000010100000101010100000101000001000000000101010100010101010100010000000001000100000000010000000001010100010000010101000001000001000000000100010101000000000100000100000001010101000100010100000001010001000101000000010100010000010000010001000100010101010100000001010001010100010000010401010000", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000101010100010100000001000001000101000000010001000000010001010000000100010000000101010100000101010101000000000000000001000100000001010000010100000101000000000000000000010101000100000000010000010000000101000000010101010001000001000000000001010001000101010001000000000001000001000100010101010101000001000101000100000101000100000100010001010100010101000100010101000001000100000100000100010001010000000101010000010100000101000100000100000000010000000101010000010101010100000101010000000001010101000101000000010000010001fd000100000100010101010001010101000100010000010001010001010100010100000101000000010101000001000001000100010100010000010001000000010001000001010000010101000100010000010100000101000001010100010100010100010100000101010100000000010100010101010001010000000000000000010001010001000101010100000101010101010001010100000100010000010001010100000100000100000101000100010000010100000001000100010000000101000000000001010001010101010101010001000101010100010000000001010101000101000001000001010101000000010001000000000101010001010101fd0001010001010101010000000101010101010001010001010000000000010100000000000001010101010000000100010100000001000100000000000100000100000000000101000001000000010101010001010000010101010000000101010101000101010100000001010000010001000101010000000101010101010101010101000101000000000101000101010001010101010101000101000100000101000001010100000001010001010100010101000001000001010000010000010101000101010101000001010100000101000101010001000101010100000100000100000100000000000000000101000100000000000100000100000001000001000401010001", -! "04fd000100010100010100000100010101000101010101010101000000000001010000000000010101000100000000010000000000000001000101010100000000010001010000010101000000010100010001000000000001000000010000000100000000000101010000000100010001010100000100000100000000010101010001010101010001000000000100000000010100000100000000010000010000010101000100000100010000000000000001010100000100010101000101010000010101000100000001010001000101000101000100000000010100010000010001010001010100010100000000010000000001000100010000000000000000010100fd000101010100010100000001000001000101000000010001000000010001010000000100010000000101010100000101010101000000000000000001000100000001010000010100000101000000000000000000010101000100000000010000010000000101000000010101010001000001000000000001010001000101010001000000000001000001000100010101010101000001000101000100000101000100000100010001010100010101000100010101000001000100000100000100010001010000000101010000010100000101000100000100000000010000000101010000010101010100000101010000000001010101000101000000010000010001fd000101010100010000010001010101010101000000010001010001000100010100010000000100010000000001010000010100010001010000010100000101000001010000010101000001000001000000000100010000010101010100010000010001000100000001010101010000010101010100010100010001000100010000010001000001000100010100010100000101000000000000000100000000010000000001000000010000000100000101000101000101000001000001010000010000000101010100010000010101010101000100000101010100000000010001000100010100010100000001000001000000010100000000000100010000010101fd0001010000000001000001010000010000000000010100010000010101000001010101010000010001010000010101000000010100010001010001010101000000000100000001010001010000000000010001010101000100010101000001010101000100000100000000000101010000010100010101000000010000010000010000000000000000010100000000010001000000010001010100010000010001010000000100000001010100000001010101000100010101010001010100010101000000010101010101010001000001010100000001010001010100010000000000000100010001010000010000000000000101000100010000000100000000000401010100" - ] -diff -crB ./src/test/data/merkle_roots.json ../../komodo-jl777/src/test/data/merkle_roots.json -*** ./src/test/data/merkle_roots.json 2017-01-03 10:40:50.395338477 +0000 ---- ../../komodo-jl777/src/test/data/merkle_roots.json 2017-01-03 09:49:08.872507185 +0000 -*************** -*** 1,18 **** - [ -! "26ee6e3f8c28892382264d72789c9c65a8577549fe35d3d6df86e0f07cc80057", -! "0e54a14ab674813f2a558b18df630ae095f2cb775d0bc37677073acb1f8f3443", -! "d06e16c2e6ee0b28d8f07c76a17976fea549ce2dd1debae260dc3215d265fddb", -! "52dc4b76365472537ff15cb18a71be54c91d207f5d62fb89bd74af9010ac0e01", -! "8dd27a2340e34015cd9b00a2ddc011dcdab03d38a49497490d631f71ce9c495e", -! "0cb8ae3ff2483ea7124237b62d0ac4388477b41e83d3811c6e0dd6fec0b365e6", -! "a67c1f145456880502a3d020d538fecf0515bd285edd6e3fcae26eb53c1f56d3", -! "7fb0adeb50e1084359414071486d89ead9c9a3700c64c9892f510f87af6ec27f", -! "45cd6f71215eabb2c25206471e9293bed2bc924ce5bbc16a8f728ec1e310886f", -! "01d1f338c2abee217962120611dafe0a0e9de76c18de77cbb1e3a6d3261e887c", -! "2700b09aa19ce460d509fc3bccfbc80f8381d156a4a52a7f3d4e8b852b5c10ea", -! "ac96cc858674f67d6c6119f933080cd69c10950409722468d2ac7b81e2cc2bba", -! "f4930affd93232b6051fe3a5f744a357201bff4363312d1115762a595261f030", -! "50b48f5226a69a62206f365ac5347c723b43faf9691c04b872225d5c08876eed", -! "a867397884b157b1db4dd03dc2fd6c40c4650e70b61441d4325e0b18d5280fb6", -! "52c8456d3538eed3b73778c596c1993ac6d6c337ae5e338391ce6cae58296dec" - ] ---- 1,18 ---- - [ -! "95bf71d8e803b8601c14b5949d0f92690181154ef9d82eb3e24852266823317a", -! "73f18d3f9cd11010aa01d4f444039e566f14ef282109df9649b2eb75e7a53ed1", -! "dcde8a273c9672bee1a894d7f7f4abb81078f52b498e095f2a87d0aec5addf25", -! "4677d481ec6d1e97969afbc530958d1cbb4f1c047af6fdad4687cd10830e02bd", -! "74cd9d82de30c4222a06d420b75522ae1273729c1d8419446adf1184df61dc69", -! "2ff57f5468c6afdad30ec0fb6c2cb67289f12584e2c20c4e0065f66748697d77", -! "27e4ce010670801911c5765a003b15f75cde31d7378bd36540f593c8a44b3011", -! "62231ef2ec8c4da461072871ab7bc9de10253fcb40e164ddbad05b47e0b7fb69", -! "733a4ce688fdf07efb9e9f5a4b2dafff87cfe198fbe1dff71e028ef4cdee1f1b", -! "df39ed31924facdd69a93db07311d45fceac7a4987c091648044f37e6ecbb0d2", -! "87795c069bdb55281c666b9cb872d13174334ce135c12823541e9536489a9107", -! "438c80f532903b283230446514e400c329b29483db4fe9e279fdfc79e8f4347d", -! "08afb2813eda17e94aba1ab28ec191d4af99283cd4f1c5a04c0c2bc221bc3119", -! "a8b3ab3284f3288f7caa21bd2b69789a159ab4188b0908825b34723305c1228c", -! "db9b289e620de7dca2ae8fdac96808752e32e7a2c6d97ce0755dcebaa03123ab", -! "0bf622cb9f901b7532433ea2e7c1b7632f5935899b62dcf897a71551997dc8cc" - ] -diff -crB ./src/test/data/merkle_serialization.json ../../komodo-jl777/src/test/data/merkle_serialization.json -*** ./src/test/data/merkle_serialization.json 2017-01-03 10:40:50.399338679 +0000 ---- ../../komodo-jl777/src/test/data/merkle_serialization.json 2017-01-03 09:49:08.872507185 +0000 -*************** -*** 1,18 **** - [ -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e302018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30003018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e303018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3030001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30003018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e303018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443" -! ] -\ No newline at end of file ---- 1,18 ---- - [ -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba0000", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba0168eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c94300", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0001019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f38618", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0192498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae401019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f38618", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430002000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430168c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc02000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f", -! "018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b1000201aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af20146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f", -! "018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b10150c0b43061c39191c3ec529734328b7f9cafeb6fd162cc49a4495442d9499a2d0201aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af20146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f", -! "0170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965300030000016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a806", -! "0170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965301d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf817030000016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a806", -! "018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b000301fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a4100016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a806", -! "018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b0104e963ab731e4aaaaaf931c3c039ea8c9d7904163936e19a8929434da9adeba30301fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a4100016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a806", -! "01be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a091200030001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a806", -! "01be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a0912011880967fc8226380a849c63532bba67990f7d0a10e9c90b848f58d634957c6e9030001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a806", -! "01c465bb2893cba233351094f259396301c23d73a6cf6f92bc63428a43f0dd8f8e000301e97f16ad143359999c90a7d2a3e7daa94ad980842226d9323d3f4f0ab62460a701ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a806", -! "01c465bb2893cba233351094f259396301c23d73a6cf6f92bc63428a43f0dd8f8e0184c834e7cb38d6f08d82f5cf4839b8920185174b11c7af771fd38dd02b206a200301e97f16ad143359999c90a7d2a3e7daa94ad980842226d9323d3f4f0ab62460a701ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a806" -! ] -diff -crB ./src/test/data/merkle_witness_serialization.json ../../komodo-jl777/src/test/data/merkle_witness_serialization.json -*** ./src/test/data/merkle_witness_serialization.json 2017-01-03 10:40:50.399338679 +0000 ---- ../../komodo-jl777/src/test/data/merkle_witness_serialization.json 2017-01-03 09:49:08.872507185 +0000 -*************** -*** 1,138 **** - [ -! "0000000155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0000000255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0000000255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0000000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0000000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0000000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0000000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0000000455b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300028695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0000000455b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300028695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e302018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0000000455b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300028695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e302018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0000000455b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300028695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e302018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0000000455b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300028695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e302018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30003018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0000000455b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300028695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e302018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30003018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e303018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0000000455b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300028695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e302018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30003018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e303018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", -! "0000000455b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300028695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e302018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30003018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e303018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3030001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", -! "0000000555b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c5564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000455b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c5564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300038695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c5564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c5564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d02dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c5564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d5564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c028695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d5564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e35564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e302018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443028695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30003018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e303018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944301dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3030001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00", -! "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30003018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300" -! ] -\ No newline at end of file ---- 1,138 ---- - [ -! "0000000162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba00", -! "0000000262fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba68eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c94300", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba00000168eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c94300", -! "0000000262fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba68eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c9430101836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0000", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba00000168eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c9430101836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0000", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba0168eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c94300000101836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0000", -! "0000000362fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba68eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae00", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba00000268eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae00", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba0168eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c9430001a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae00", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0001019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f386180192498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae400", -! "0000000362fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba68eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae0101ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430000", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba00000268eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae0101ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430000", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba0168eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c9430001a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae0101ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430000", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0001019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f386180192498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae40101ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430000", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0192498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae401019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f38618000101ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430000", -! "0000000362fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba68eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae0101ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430168c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc00", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba00000268eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae0101ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430168c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc00", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba0168eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c9430001a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae0101ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430168c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc00", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0001019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f386180192498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae40101ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430168c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc00", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0192498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae401019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f38618000101ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430168c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc00", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430002000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0168c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc00", -! "0000000362fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba68eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae01018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b1000101aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af2", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba00000268eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae01018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b1000101aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af2", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba0168eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c9430001a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae01018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b1000101aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af2", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0001019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f386180192498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae401018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b1000101aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af2", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0192498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae401019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f386180001018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b1000101aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af2", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430002000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0168c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc01018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b10000", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430168c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc02000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0001018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b10000", -! "0000000462fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba68eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd00", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba00000368eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd00", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba0168eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c9430002a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd00", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0001019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f386180292498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae4112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd00", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0192498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae401019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f3861801112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd00", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430002000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0268c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc050a753bb419723abb7f22486c2a7182e390f47927435bc2c2f7fda93ad1047400", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430168c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc02000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f01050a753bb419723abb7f22486c2a7182e390f47927435bc2c2f7fda93ad1047400", -! "018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b1000201aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af20146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0150c0b43061c39191c3ec529734328b7f9cafeb6fd162cc49a4495442d9499a2d00", -! "0000000462fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba68eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd010170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b96530000", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba00000368eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd010170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b96530000", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba0168eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c9430002a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd010170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b96530000", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0001019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f386180292498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae4112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd010170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b96530000", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0192498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae401019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f3861801112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd010170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b96530000", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430002000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0268c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc050a753bb419723abb7f22486c2a7182e390f47927435bc2c2f7fda93ad10474010170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b96530000", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430168c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc02000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f01050a753bb419723abb7f22486c2a7182e390f47927435bc2c2f7fda93ad10474010170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b96530000", -! "018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b1000201aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af20146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0150c0b43061c39191c3ec529734328b7f9cafeb6fd162cc49a4495442d9499a2d010170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b96530000", -! "018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b10150c0b43061c39191c3ec529734328b7f9cafeb6fd162cc49a4495442d9499a2d0201aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af20146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f00010170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b96530000", -! "0000000462fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba68eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd010170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965301d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf81700", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba00000368eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd010170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965301d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf81700", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba0168eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c9430002a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd010170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965301d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf81700", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0001019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f386180292498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae4112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd010170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965301d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf81700", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0192498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae401019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f3861801112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd010170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965301d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf81700", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430002000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0268c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc050a753bb419723abb7f22486c2a7182e390f47927435bc2c2f7fda93ad10474010170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965301d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf81700", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430168c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc02000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f01050a753bb419723abb7f22486c2a7182e390f47927435bc2c2f7fda93ad10474010170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965301d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf81700", -! "018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b1000201aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af20146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0150c0b43061c39191c3ec529734328b7f9cafeb6fd162cc49a4495442d9499a2d010170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965301d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf81700", -! "018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b10150c0b43061c39191c3ec529734328b7f9cafeb6fd162cc49a4495442d9499a2d0201aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af20146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f00010170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965301d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf81700", -! "0170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965300030000016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a80601d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf81700", -! "0000000462fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba68eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd01018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b000101fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a41", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba00000368eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd01018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b000101fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a41", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba0168eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c9430002a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd01018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b000101fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a41", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0001019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f386180292498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae4112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd01018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b000101fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a41", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0192498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae401019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f3861801112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd01018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b000101fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a41", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430002000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0268c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc050a753bb419723abb7f22486c2a7182e390f47927435bc2c2f7fda93ad1047401018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b000101fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a41", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430168c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc02000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f01050a753bb419723abb7f22486c2a7182e390f47927435bc2c2f7fda93ad1047401018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b000101fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a41", -! "018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b1000201aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af20146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0150c0b43061c39191c3ec529734328b7f9cafeb6fd162cc49a4495442d9499a2d01018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b000101fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a41", -! "018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b10150c0b43061c39191c3ec529734328b7f9cafeb6fd162cc49a4495442d9499a2d0201aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af20146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0001018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b000101fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a41", -! "0170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965300030000016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a80601d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf81701018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b0000", -! "0170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965301d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf817030000016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a8060001018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b0000", -! "0000000462fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba68eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd01018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b0104e963ab731e4aaaaaf931c3c039ea8c9d7904163936e19a8929434da9adeba30101fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a41", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba00000368eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd01018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b0104e963ab731e4aaaaaf931c3c039ea8c9d7904163936e19a8929434da9adeba30101fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a41", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba0168eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c9430002a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd01018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b0104e963ab731e4aaaaaf931c3c039ea8c9d7904163936e19a8929434da9adeba30101fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a41", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0001019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f386180292498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae4112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd01018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b0104e963ab731e4aaaaaf931c3c039ea8c9d7904163936e19a8929434da9adeba30101fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a41", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0192498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae401019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f3861801112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd01018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b0104e963ab731e4aaaaaf931c3c039ea8c9d7904163936e19a8929434da9adeba30101fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a41", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430002000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0268c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc050a753bb419723abb7f22486c2a7182e390f47927435bc2c2f7fda93ad1047401018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b0104e963ab731e4aaaaaf931c3c039ea8c9d7904163936e19a8929434da9adeba30101fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a41", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430168c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc02000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f01050a753bb419723abb7f22486c2a7182e390f47927435bc2c2f7fda93ad1047401018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b0104e963ab731e4aaaaaf931c3c039ea8c9d7904163936e19a8929434da9adeba30101fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a41", -! "018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b1000201aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af20146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0150c0b43061c39191c3ec529734328b7f9cafeb6fd162cc49a4495442d9499a2d01018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b0104e963ab731e4aaaaaf931c3c039ea8c9d7904163936e19a8929434da9adeba30101fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a41", -! "018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b10150c0b43061c39191c3ec529734328b7f9cafeb6fd162cc49a4495442d9499a2d0201aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af20146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0001018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b0104e963ab731e4aaaaaf931c3c039ea8c9d7904163936e19a8929434da9adeba30101fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a41", -! "0170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965300030000016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a80602d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf817a1e12cd7bb8d53016cbf0729cfc1bead8759a9e97a7eb50a416a27ced07e755000", -! "0170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965301d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf817030000016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a80601a1e12cd7bb8d53016cbf0729cfc1bead8759a9e97a7eb50a416a27ced07e755000", -! "018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b000301fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a4100016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a8060104e963ab731e4aaaaaf931c3c039ea8c9d7904163936e19a8929434da9adeba300", -! "0000000462fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba68eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd0101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a091200020001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba00000368eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd0101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a091200020001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba0168eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c9430002a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd0101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a091200020001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0001019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f386180292498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae4112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd0101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a091200020001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0192498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae401019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f3861801112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd0101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a091200020001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430002000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0268c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc050a753bb419723abb7f22486c2a7182e390f47927435bc2c2f7fda93ad104740101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a091200020001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430168c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc02000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f01050a753bb419723abb7f22486c2a7182e390f47927435bc2c2f7fda93ad104740101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a091200020001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b1000201aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af20146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0150c0b43061c39191c3ec529734328b7f9cafeb6fd162cc49a4495442d9499a2d0101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a091200020001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b10150c0b43061c39191c3ec529734328b7f9cafeb6fd162cc49a4495442d9499a2d0201aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af20146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f000101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a091200020001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "0170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965300030000016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a80602d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf817a1e12cd7bb8d53016cbf0729cfc1bead8759a9e97a7eb50a416a27ced07e75500101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a09120000", -! "0170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965301d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf817030000016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a80601a1e12cd7bb8d53016cbf0729cfc1bead8759a9e97a7eb50a416a27ced07e75500101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a09120000", -! "018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b000301fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a4100016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a8060104e963ab731e4aaaaaf931c3c039ea8c9d7904163936e19a8929434da9adeba30101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a09120000", -! "018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b0104e963ab731e4aaaaaf931c3c039ea8c9d7904163936e19a8929434da9adeba30301fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a4100016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a806000101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a09120000", -! "0000000462fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba68eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd0101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a0912011880967fc8226380a849c63532bba67990f7d0a10e9c90b848f58d634957c6e9020001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba00000368eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd0101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a0912011880967fc8226380a849c63532bba67990f7d0a10e9c90b848f58d634957c6e9020001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba0168eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c9430002a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd0101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a0912011880967fc8226380a849c63532bba67990f7d0a10e9c90b848f58d634957c6e9020001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0001019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f386180292498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae4112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd0101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a0912011880967fc8226380a849c63532bba67990f7d0a10e9c90b848f58d634957c6e9020001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0192498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae401019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f3861801112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd0101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a0912011880967fc8226380a849c63532bba67990f7d0a10e9c90b848f58d634957c6e9020001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430002000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0268c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc050a753bb419723abb7f22486c2a7182e390f47927435bc2c2f7fda93ad104740101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a0912011880967fc8226380a849c63532bba67990f7d0a10e9c90b848f58d634957c6e9020001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430168c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc02000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f01050a753bb419723abb7f22486c2a7182e390f47927435bc2c2f7fda93ad104740101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a0912011880967fc8226380a849c63532bba67990f7d0a10e9c90b848f58d634957c6e9020001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b1000201aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af20146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0150c0b43061c39191c3ec529734328b7f9cafeb6fd162cc49a4495442d9499a2d0101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a0912011880967fc8226380a849c63532bba67990f7d0a10e9c90b848f58d634957c6e9020001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b10150c0b43061c39191c3ec529734328b7f9cafeb6fd162cc49a4495442d9499a2d0201aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af20146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f000101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a0912011880967fc8226380a849c63532bba67990f7d0a10e9c90b848f58d634957c6e9020001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "0170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965300030000016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a80602d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf817a1e12cd7bb8d53016cbf0729cfc1bead8759a9e97a7eb50a416a27ced07e75500101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a0912011880967fc8226380a849c63532bba67990f7d0a10e9c90b848f58d634957c6e900", -! "0170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965301d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf817030000016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a80601a1e12cd7bb8d53016cbf0729cfc1bead8759a9e97a7eb50a416a27ced07e75500101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a0912011880967fc8226380a849c63532bba67990f7d0a10e9c90b848f58d634957c6e900", -! "018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b000301fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a4100016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a8060104e963ab731e4aaaaaf931c3c039ea8c9d7904163936e19a8929434da9adeba30101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a0912011880967fc8226380a849c63532bba67990f7d0a10e9c90b848f58d634957c6e900", -! "018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b0104e963ab731e4aaaaaf931c3c039ea8c9d7904163936e19a8929434da9adeba30301fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a4100016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a806000101be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a0912011880967fc8226380a849c63532bba67990f7d0a10e9c90b848f58d634957c6e900", -! "01be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a091200030001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a806011880967fc8226380a849c63532bba67990f7d0a10e9c90b848f58d634957c6e900", -! "0000000462fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba68eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd0101c465bb2893cba233351094f259396301c23d73a6cf6f92bc63428a43f0dd8f8e000201e97f16ad143359999c90a7d2a3e7daa94ad980842226d9323d3f4f0ab62460a701ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba00000368eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd0101c465bb2893cba233351094f259396301c23d73a6cf6f92bc63428a43f0dd8f8e000201e97f16ad143359999c90a7d2a3e7daa94ad980842226d9323d3f4f0ab62460a701ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba0168eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c9430002a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd0101c465bb2893cba233351094f259396301c23d73a6cf6f92bc63428a43f0dd8f8e000201e97f16ad143359999c90a7d2a3e7daa94ad980842226d9323d3f4f0ab62460a701ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0001019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f386180292498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae4112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd0101c465bb2893cba233351094f259396301c23d73a6cf6f92bc63428a43f0dd8f8e000201e97f16ad143359999c90a7d2a3e7daa94ad980842226d9323d3f4f0ab62460a701ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0192498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae401019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f3861801112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd0101c465bb2893cba233351094f259396301c23d73a6cf6f92bc63428a43f0dd8f8e000201e97f16ad143359999c90a7d2a3e7daa94ad980842226d9323d3f4f0ab62460a701ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430002000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0268c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc050a753bb419723abb7f22486c2a7182e390f47927435bc2c2f7fda93ad104740101c465bb2893cba233351094f259396301c23d73a6cf6f92bc63428a43f0dd8f8e000201e97f16ad143359999c90a7d2a3e7daa94ad980842226d9323d3f4f0ab62460a701ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430168c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc02000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f01050a753bb419723abb7f22486c2a7182e390f47927435bc2c2f7fda93ad104740101c465bb2893cba233351094f259396301c23d73a6cf6f92bc63428a43f0dd8f8e000201e97f16ad143359999c90a7d2a3e7daa94ad980842226d9323d3f4f0ab62460a701ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b1000201aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af20146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0150c0b43061c39191c3ec529734328b7f9cafeb6fd162cc49a4495442d9499a2d0101c465bb2893cba233351094f259396301c23d73a6cf6f92bc63428a43f0dd8f8e000201e97f16ad143359999c90a7d2a3e7daa94ad980842226d9323d3f4f0ab62460a701ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b10150c0b43061c39191c3ec529734328b7f9cafeb6fd162cc49a4495442d9499a2d0201aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af20146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f000101c465bb2893cba233351094f259396301c23d73a6cf6f92bc63428a43f0dd8f8e000201e97f16ad143359999c90a7d2a3e7daa94ad980842226d9323d3f4f0ab62460a701ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625", -! "0170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965300030000016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a80602d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf817a1e12cd7bb8d53016cbf0729cfc1bead8759a9e97a7eb50a416a27ced07e75500101c465bb2893cba233351094f259396301c23d73a6cf6f92bc63428a43f0dd8f8e000101e97f16ad143359999c90a7d2a3e7daa94ad980842226d9323d3f4f0ab62460a7", -! "0170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965301d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf817030000016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a80601a1e12cd7bb8d53016cbf0729cfc1bead8759a9e97a7eb50a416a27ced07e75500101c465bb2893cba233351094f259396301c23d73a6cf6f92bc63428a43f0dd8f8e000101e97f16ad143359999c90a7d2a3e7daa94ad980842226d9323d3f4f0ab62460a7", -! "018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b000301fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a4100016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a8060104e963ab731e4aaaaaf931c3c039ea8c9d7904163936e19a8929434da9adeba30101c465bb2893cba233351094f259396301c23d73a6cf6f92bc63428a43f0dd8f8e000101e97f16ad143359999c90a7d2a3e7daa94ad980842226d9323d3f4f0ab62460a7", -! "018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b0104e963ab731e4aaaaaf931c3c039ea8c9d7904163936e19a8929434da9adeba30301fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a4100016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a806000101c465bb2893cba233351094f259396301c23d73a6cf6f92bc63428a43f0dd8f8e000101e97f16ad143359999c90a7d2a3e7daa94ad980842226d9323d3f4f0ab62460a7", -! "01be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a091200030001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a806011880967fc8226380a849c63532bba67990f7d0a10e9c90b848f58d634957c6e90101c465bb2893cba233351094f259396301c23d73a6cf6f92bc63428a43f0dd8f8e0000", -! "01be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a0912011880967fc8226380a849c63532bba67990f7d0a10e9c90b848f58d634957c6e9030001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a806000101c465bb2893cba233351094f259396301c23d73a6cf6f92bc63428a43f0dd8f8e0000", -! "0000000562fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba68eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd458cab4492ce89c6b50161e0583c2115e7900db964a53b49e152828d6a3991af00", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba00000468eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c943a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd458cab4492ce89c6b50161e0583c2115e7900db964a53b49e152828d6a3991af00", -! "0162fdad9bfbf17c38ea626a9c9b8af8a748e6b4367c8494caf0ca592999e8b6ba0168eb35bc5e1ddb80a761718e63a1ecf4d4977ae22cc19fa732b85515b2a4c9430003a6637c3308b7b8e6eabc3c9c3bd672b568d73c8de4cf14ca2a004ff20c86c7ae112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd458cab4492ce89c6b50161e0583c2115e7900db964a53b49e152828d6a3991af00", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0001019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f386180392498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae4112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd458cab4492ce89c6b50161e0583c2115e7900db964a53b49e152828d6a3991af00", -! "01836045484077cf6390184ea7cd48b460e2d0f22b2293b69633bb152314a692fb0192498a8295ea36d593eaee7cb8b55be3a3e37b8185d3807693184054cd574ae401019f5b2b1e4bf7e7318d0a1f417ca6bca36077025b3d11e074b94cd55ce9f3861802112e79af601aaa3c0a48e6c37930ccad4b5a3340a373a14d7b79697e5ee730dd458cab4492ce89c6b50161e0583c2115e7900db964a53b49e152828d6a3991af00", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430002000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0368c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc050a753bb419723abb7f22486c2a7182e390f47927435bc2c2f7fda93ad10474458cab4492ce89c6b50161e0583c2115e7900db964a53b49e152828d6a3991af00", -! "01ff7c360374a6508ae0904c782127ff5dce90918f3ee81cf92ef1b69afb8bf4430168c4d0f69d1f18b756c2ee875c14f1c6cd38682e715ded14bf7e3c1c5610e9fc02000146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f02050a753bb419723abb7f22486c2a7182e390f47927435bc2c2f7fda93ad10474458cab4492ce89c6b50161e0583c2115e7900db964a53b49e152828d6a3991af00", -! "018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b1000201aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af20146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f0250c0b43061c39191c3ec529734328b7f9cafeb6fd162cc49a4495442d9499a2d458cab4492ce89c6b50161e0583c2115e7900db964a53b49e152828d6a3991af00", -! "018b16cd3ec44875e4856e30344c0b4a68a6f929a68be5117b225b80926301e7b10150c0b43061c39191c3ec529734328b7f9cafeb6fd162cc49a4495442d9499a2d0201aed51ae31f597f976bac0f62cd5e563203ead4b5202d6459c5d45466dd737af20146c2fe50e8c66a8b402bdf071f52c7f509f7a04597f31886b2823e288a936d9f01458cab4492ce89c6b50161e0583c2115e7900db964a53b49e152828d6a3991af00", -! "0170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965300030000016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a80603d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf817a1e12cd7bb8d53016cbf0729cfc1bead8759a9e97a7eb50a416a27ced07e7550305205dbbecab7b01ec2538467c2fe41f7845eb45487bcf2f7d7bd52207f644100", -! "0170ffdd5fa0f3aea18bd4700f1ac2e2e03cf5d4b7b857e8dd93b862a8319b965301d81ef64a0063573d80cd32222d8d04debbe807345ad7af2e9edf0f44bdfaf817030000016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a80602a1e12cd7bb8d53016cbf0729cfc1bead8759a9e97a7eb50a416a27ced07e7550305205dbbecab7b01ec2538467c2fe41f7845eb45487bcf2f7d7bd52207f644100", -! "018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b000301fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a4100016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a8060204e963ab731e4aaaaaf931c3c039ea8c9d7904163936e19a8929434da9adeba3305205dbbecab7b01ec2538467c2fe41f7845eb45487bcf2f7d7bd52207f644100", -! "018b92a4ec694271fe1b16cc0ea8a433bf19e78eb5ca733cc137f38e5ecb05789b0104e963ab731e4aaaaaf931c3c039ea8c9d7904163936e19a8929434da9adeba30301fe190d5e3beaf1084c1b1cb6621d262c0cd8cd16454ef0188441abf05d356a4100016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a80601305205dbbecab7b01ec2538467c2fe41f7845eb45487bcf2f7d7bd52207f644100", -! "01be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a091200030001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a806021880967fc8226380a849c63532bba67990f7d0a10e9c90b848f58d634957c6e92f7a96ecc725694533a999db6786f6016bcfdca5c9353151837faf43d93c50ef00", -! "01be3f6c181f162824191ecf1f78cae3ffb0ddfda671bb93277ce6ebc9201a0912011880967fc8226380a849c63532bba67990f7d0a10e9c90b848f58d634957c6e9030001ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a806012f7a96ecc725694533a999db6786f6016bcfdca5c9353151837faf43d93c50ef00", -! "01c465bb2893cba233351094f259396301c23d73a6cf6f92bc63428a43f0dd8f8e000301e97f16ad143359999c90a7d2a3e7daa94ad980842226d9323d3f4f0ab62460a701ec4b1458a3cf805199803a1231e906ba095f969a5775ca4ac73348473e70f625016cbbfc183a1017859c6a088838ae487be84321274a039773a35b434b7610a8060184c834e7cb38d6f08d82f5cf4839b8920185174b11c7af771fd38dd02b206a2000" -! ] -diff -crB ./src/test/rpc_wallet_tests.cpp ../../komodo-jl777/src/test/rpc_wallet_tests.cpp -*** ./src/test/rpc_wallet_tests.cpp 2017-01-03 10:40:50.419339691 +0000 ---- ../../komodo-jl777/src/test/rpc_wallet_tests.cpp 2017-01-03 09:49:08.872507185 +0000 -*************** -*** 295,307 **** - BOOST_CHECK_THROW(CallRPC("z_listreceivedbyaddress tnRZ8bPq2pff3xBWhTJhNkVUkm2uhzksDeW5PvEa7aFKGT9Qi3YgTALZfjaY4jU3HLVKBtHdSXxoPoLA3naMPcHBcY88FcF 1"), runtime_error); - } - - /* - * This test covers RPC command z_exportwallet - */ - BOOST_AUTO_TEST_CASE(rpc_wallet_z_exportwallet) - { - LOCK2(cs_main, pwalletMain->cs_wallet); -! - // wallet should be empty - std::set addrs; - pwalletMain->GetPaymentAddresses(addrs); ---- 295,353 ---- - BOOST_CHECK_THROW(CallRPC("z_listreceivedbyaddress tnRZ8bPq2pff3xBWhTJhNkVUkm2uhzksDeW5PvEa7aFKGT9Qi3YgTALZfjaY4jU3HLVKBtHdSXxoPoLA3naMPcHBcY88FcF 1"), runtime_error); - } - -+ /** -+ * This test covers RPC command z_validateaddress -+ */ -+ BOOST_AUTO_TEST_CASE(rpc_wallet_z_validateaddress) -+ { -+ SelectParams(CBaseChainParams::MAIN); -+ -+ LOCK2(cs_main, pwalletMain->cs_wallet); -+ -+ Value retValue; -+ -+ // Check number of args -+ BOOST_CHECK_THROW(CallRPC("z_validateaddress"), runtime_error); -+ BOOST_CHECK_THROW(CallRPC("z_validateaddress toomany args"), runtime_error); -+ -+ // Wallet should be empty -+ std::set addrs; -+ pwalletMain->GetPaymentAddresses(addrs); -+ BOOST_CHECK(addrs.size()==0); -+ -+ // This address is not valid, it belongs to another network -+ BOOST_CHECK_NO_THROW(retValue = CallRPC("z_validateaddress ztaaga95QAPyp1kSQ1hD2kguCpzyMHjxWZqaYDEkzbvo7uYQYAw2S8X4Kx98AvhhofMtQL8PAXKHuZsmhRcanavKRKmdCzk")); -+ Object resultObj = retValue.get_obj(); -+ bool b = find_value(resultObj, "isvalid").get_bool(); -+ BOOST_CHECK_EQUAL(b, false); -+ -+ // This address is valid, but the spending key is not in this wallet -+ BOOST_CHECK_NO_THROW(retValue = CallRPC("z_validateaddress zcfA19SDAKRYHLoRDoShcoz4nPohqWxuHcqg8WAxsiB2jFrrs6k7oSvst3UZvMYqpMNSRBkxBsnyjjngX5L55FxMzLKach8")); -+ resultObj = retValue.get_obj(); -+ b = find_value(resultObj, "isvalid").get_bool(); -+ BOOST_CHECK_EQUAL(b, true); -+ b = find_value(resultObj, "ismine").get_bool(); -+ BOOST_CHECK_EQUAL(b, false); -+ -+ // Let's import a spending key to the wallet and validate its payment address -+ BOOST_CHECK_NO_THROW(CallRPC("z_importkey SKxoWv77WGwFnUJitQKNEcD636bL4X5Gd6wWmgaA4Q9x8jZBPJXT")); -+ BOOST_CHECK_NO_THROW(retValue = CallRPC("z_validateaddress zcWsmqT4X2V4jgxbgiCzyrAfRT1vi1F4sn7M5Pkh66izzw8Uk7LBGAH3DtcSMJeUb2pi3W4SQF8LMKkU2cUuVP68yAGcomL")); -+ resultObj = retValue.get_obj(); -+ b = find_value(resultObj, "isvalid").get_bool(); -+ BOOST_CHECK_EQUAL(b, true); -+ b = find_value(resultObj, "ismine").get_bool(); -+ BOOST_CHECK_EQUAL(b, true); -+ BOOST_CHECK_EQUAL(find_value(resultObj, "payingkey").get_str(), "f5bb3c888ccc9831e3f6ba06e7528e26a312eec3acc1823be8918b6a3a5e20ad"); -+ BOOST_CHECK_EQUAL(find_value(resultObj, "transmissionkey").get_str(), "7a58c7132446564e6b810cf895c20537b3528357dc00150a8e201f491efa9c1a"); -+ } -+ - /* - * This test covers RPC command z_exportwallet - */ - BOOST_AUTO_TEST_CASE(rpc_wallet_z_exportwallet) - { - LOCK2(cs_main, pwalletMain->cs_wallet); -! - // wallet should be empty - std::set addrs; - pwalletMain->GetPaymentAddresses(addrs); -*************** -*** 774,780 **** - - BOOST_CHECK_THROW(CallRPC("z_sendmany"), runtime_error); - BOOST_CHECK_THROW(CallRPC("z_sendmany toofewargs"), runtime_error); -! BOOST_CHECK_THROW(CallRPC("z_sendmany too many args here"), runtime_error); - - // bad from address - BOOST_CHECK_THROW(CallRPC("z_sendmany " ---- 820,826 ---- - - BOOST_CHECK_THROW(CallRPC("z_sendmany"), runtime_error); - BOOST_CHECK_THROW(CallRPC("z_sendmany toofewargs"), runtime_error); -! BOOST_CHECK_THROW(CallRPC("z_sendmany just too many args here"), runtime_error); - - // bad from address - BOOST_CHECK_THROW(CallRPC("z_sendmany " -*************** -*** 795,800 **** ---- 841,867 ---- - " {\"address\":\"tmQP9L3s31cLsghVYf2Jb5MhKj1jRBPoeQn\", \"amount\":12.0} ]" - ), runtime_error); - -+ // invalid fee amount, cannot be negative -+ BOOST_CHECK_THROW(CallRPC("z_sendmany " -+ "tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ " -+ "[{\"address\":\"tmQP9L3s31cLsghVYf2Jb5MhKj1jRBPoeQn\", \"amount\":50.0}] " -+ "1 -0.0001" -+ ), runtime_error); -+ -+ // invalid fee amount, bigger than MAX_MONEY -+ BOOST_CHECK_THROW(CallRPC("z_sendmany " -+ "tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ " -+ "[{\"address\":\"tmQP9L3s31cLsghVYf2Jb5MhKj1jRBPoeQn\", \"amount\":50.0}] " -+ "1 21000001" -+ ), runtime_error); -+ -+ // fee amount is bigger than sum of outputs -+ BOOST_CHECK_THROW(CallRPC("z_sendmany " -+ "tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ " -+ "[{\"address\":\"tmQP9L3s31cLsghVYf2Jb5MhKj1jRBPoeQn\", \"amount\":50.0}] " -+ "1 50.00000001" -+ ), runtime_error); -+ - // memo bigger than allowed length of ZC_MEMO_SIZE - std::vector v (2 * (ZC_MEMO_SIZE+1)); // x2 for hexadecimal string format - std::fill(v.begin(),v.end(), 'A'); -diff -crB ./src/test/transaction_tests.cpp ../../komodo-jl777/src/test/transaction_tests.cpp -*** ./src/test/transaction_tests.cpp 2017-01-03 10:40:50.423339894 +0000 ---- ../../komodo-jl777/src/test/transaction_tests.cpp 2017-01-03 09:49:08.872507185 +0000 -*************** -*** 341,349 **** - libzcash::JSOutput(addr, 50) - }; - - { - JSDescription jsdesc(*p, pubKeyHash, rt, inputs, outputs, 0, 0); -! BOOST_CHECK(jsdesc.Verify(*p, pubKeyHash)); - - CDataStream ss(SER_DISK, CLIENT_VERSION); - ss << jsdesc; ---- 341,351 ---- - libzcash::JSOutput(addr, 50) - }; - -+ auto verifier = libzcash::ProofVerifier::Strict(); -+ - { - JSDescription jsdesc(*p, pubKeyHash, rt, inputs, outputs, 0, 0); -! BOOST_CHECK(jsdesc.Verify(*p, verifier, pubKeyHash)); - - CDataStream ss(SER_DISK, CLIENT_VERSION); - ss << jsdesc; -*************** -*** 352,358 **** - ss >> jsdesc_deserialized; - - BOOST_CHECK(jsdesc_deserialized == jsdesc); -! BOOST_CHECK(jsdesc_deserialized.Verify(*p, pubKeyHash)); - } - - { ---- 354,360 ---- - ss >> jsdesc_deserialized; - - BOOST_CHECK(jsdesc_deserialized == jsdesc); -! BOOST_CHECK(jsdesc_deserialized.Verify(*p, verifier, pubKeyHash)); - } - - { -*************** -*** 365,371 **** - // Ensure that it won't verify if the root is changed. - auto test = JSDescription(*p, pubKeyHash, rt, inputs, outputs, 0, 0); - test.anchor = GetRandHash(); -! BOOST_CHECK(!test.Verify(*p, pubKeyHash)); - } - } - ---- 367,373 ---- - // Ensure that it won't verify if the root is changed. - auto test = JSDescription(*p, pubKeyHash, rt, inputs, outputs, 0, 0); - test.anchor = GetRandHash(); -! BOOST_CHECK(!test.Verify(*p, verifier, pubKeyHash)); - } - } - -diff -crB ./src/util.cpp ../../komodo-jl777/src/util.cpp -*** ./src/util.cpp 2017-01-03 10:40:50.427340097 +0000 ---- ../../komodo-jl777/src/util.cpp 2017-01-03 09:49:08.872507185 +0000 -*************** -*** 217,222 **** ---- 217,223 ---- - - // if not debugging everything and not debugging specific category, LogPrint does nothing. - if (setCategories.count(string("")) == 0 && -+ setCategories.count(string("1")) == 0 && - setCategories.count(string(category)) == 0) - return false; - } -*************** -*** 526,532 **** - path /= BaseParams().DataDir(); - - fs::create_directories(path); -! - return path; - } - ---- 527,534 ---- - path /= BaseParams().DataDir(); - - fs::create_directories(path); -! //std::string assetpath = path + "/assets"; -! //boost::filesystem::create_directory(assetpath); - return path; - } - -Only in ../../komodo-jl777/src: utiltest.cpp -Only in ../../komodo-jl777/src: utiltest.h -diff -crB ./src/wallet/asyncrpcoperation_sendmany.cpp ../../komodo-jl777/src/wallet/asyncrpcoperation_sendmany.cpp -*** ./src/wallet/asyncrpcoperation_sendmany.cpp 2017-01-03 10:40:50.427340097 +0000 ---- ../../komodo-jl777/src/wallet/asyncrpcoperation_sendmany.cpp 2017-01-03 09:49:08.872507185 +0000 -*************** -*** 52,60 **** - std::string fromAddress, - std::vector tOutputs, - std::vector zOutputs, -! int minDepth) : -! fromaddress_(fromAddress), t_outputs_(tOutputs), z_outputs_(zOutputs), mindepth_(minDepth) - { - if (minDepth < 0) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Minconf cannot be negative"); - } ---- 52,63 ---- - std::string fromAddress, - std::vector tOutputs, - std::vector zOutputs, -! int minDepth, -! CAmount fee) : -! fromaddress_(fromAddress), t_outputs_(tOutputs), z_outputs_(zOutputs), mindepth_(minDepth), fee_(fee) - { -+ assert(fee_ > 0); -+ - if (minDepth < 0) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Minconf cannot be negative"); - } -*************** -*** 149,156 **** - bool isSingleZaddrOutput = (t_outputs_.size()==0 && z_outputs_.size()==1); - bool isMultipleZaddrOutput = (t_outputs_.size()==0 && z_outputs_.size()>=1); - bool isPureTaddrOnlyTx = (isfromtaddr_ && z_outputs_.size() == 0); -! CAmount minersFee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE; -! - // When spending coinbase utxos, you can only specify a single zaddr as the change must go somewhere - // and if there are multiple zaddrs, we don't know where to send it. - if (isfromtaddr_) { ---- 152,159 ---- - bool isSingleZaddrOutput = (t_outputs_.size()==0 && z_outputs_.size()==1); - bool isMultipleZaddrOutput = (t_outputs_.size()==0 && z_outputs_.size()>=1); - bool isPureTaddrOnlyTx = (isfromtaddr_ && z_outputs_.size() == 0); -! CAmount minersFee = fee_; -! - // When spending coinbase utxos, you can only specify a single zaddr as the change must go somewhere - // and if there are multiple zaddrs, we don't know where to send it. - if (isfromtaddr_) { -*************** -*** 202,218 **** - assert(!isfromzaddr_ || t_inputs_total == 0); - - if (isfromtaddr_ && (t_inputs_total < targetAmount)) { -! throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strprintf("Insufficient transparent funds, have %ld, need %ld", t_inputs_total, targetAmount)); - } - - if (isfromzaddr_ && (z_inputs_total < targetAmount)) { -! throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strprintf("Insufficient protected funds, have %ld, need %ld", z_inputs_total, targetAmount)); - } - - // If from address is a taddr, select UTXOs to spend - CAmount selectedUTXOAmount = 0; - bool selectedUTXOCoinbase = false; - if (isfromtaddr_) { - std::vector selectedTInputs; - for (SendManyInputUTXO & t : t_inputs_) { - bool b = std::get<3>(t); ---- 205,233 ---- - assert(!isfromzaddr_ || t_inputs_total == 0); - - if (isfromtaddr_ && (t_inputs_total < targetAmount)) { -! throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, -! strprintf("Insufficient transparent funds, have %s, need %s", -! FormatMoney(t_inputs_total), FormatMoney(targetAmount))); - } - - if (isfromzaddr_ && (z_inputs_total < targetAmount)) { -! throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, -! strprintf("Insufficient protected funds, have %s, need %s", -! FormatMoney(z_inputs_total), FormatMoney(targetAmount))); - } - - // If from address is a taddr, select UTXOs to spend - CAmount selectedUTXOAmount = 0; - bool selectedUTXOCoinbase = false; - if (isfromtaddr_) { -+ // Get dust threshold -+ CKey secret; -+ secret.MakeNewKey(true); -+ CScript scriptPubKey = GetScriptForDestination(secret.GetPubKey().GetID()); -+ CTxOut out(CAmount(1), scriptPubKey); -+ CAmount dustThreshold = out.GetDustThreshold(minRelayTxFee); -+ CAmount dustChange = -1; -+ - std::vector selectedTInputs; - for (SendManyInputUTXO & t : t_inputs_) { - bool b = std::get<3>(t); -*************** -*** 222,230 **** - selectedUTXOAmount += std::get<2>(t); - selectedTInputs.push_back(t); - if (selectedUTXOAmount >= targetAmount) { -! break; - } - } - t_inputs_ = selectedTInputs; - t_inputs_total = selectedUTXOAmount; - ---- 237,257 ---- - selectedUTXOAmount += std::get<2>(t); - selectedTInputs.push_back(t); - if (selectedUTXOAmount >= targetAmount) { -! // Select another utxo if there is change less than the dust threshold. -! dustChange = selectedUTXOAmount - targetAmount; -! if (dustChange == 0 || dustChange >= dustThreshold) { -! break; -! } - } - } -+ -+ // If there is transparent change, is it valid or is it dust? -+ if (dustChange < dustThreshold && dustChange != 0) { -+ throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, -+ strprintf("Insufficient transparent funds, have %s, need %s more to avoid creating invalid change output %s (dust threshold is %s)", -+ FormatMoney(t_inputs_total), FormatMoney(dustThreshold - dustChange), FormatMoney(dustChange), FormatMoney(dustThreshold))); -+ } -+ - t_inputs_ = selectedTInputs; - t_inputs_total = selectedUTXOAmount; - -*************** -*** 298,304 **** - zOutputsDeque.push_back(o); - } - -! - /** - * SCENARIO #2 - * ---- 325,346 ---- - zOutputsDeque.push_back(o); - } - -! // When spending notes, take a snapshot of note witnesses and anchors as the treestate will -! // change upon arrival of new blocks which contain joinsplit transactions. This is likely -! // to happen as creating a chained joinsplit transaction can take longer than the block interval. -! if (z_inputs_.size() > 0) { -! LOCK2(cs_main, pwalletMain->cs_wallet); -! for (auto t : z_inputs_) { -! JSOutPoint jso = std::get<0>(t); -! std::vector vOutPoints = { jso }; -! uint256 inputAnchor; -! std::vector> vInputWitnesses; -! pwalletMain->GetNoteWitnesses(vOutPoints, vInputWitnesses, inputAnchor); -! jsopWitnessAnchorMap[ jso.ToString() ] = WitnessAnchorData{ vInputWitnesses[0], inputAnchor }; -! } -! } -! -! - /** - * SCENARIO #2 - * -*************** -*** 321,327 **** - if (selectedUTXOCoinbase) { - assert(isSingleZaddrOutput); - throw JSONRPCError(RPC_WALLET_ERROR, strprintf( -! "Change %ld not allowed. When protecting coinbase funds, the wallet does not allow any change as there is currently no way to specify a change address in z_sendmany.", change)); - } else { - add_taddr_change_output_to_tx(change); - LogPrint("zrpc", "%s: transparent change in transaction output (amount=%s)\n", ---- 363,371 ---- - if (selectedUTXOCoinbase) { - assert(isSingleZaddrOutput); - throw JSONRPCError(RPC_WALLET_ERROR, strprintf( -! "Change %s not allowed. When protecting coinbase funds, the wallet does not " -! "allow any change as there is currently no way to specify a change address " -! "in z_sendmany.", FormatMoney(change))); - } else { - add_taddr_change_output_to_tx(change); - LogPrint("zrpc", "%s: transparent change in transaction output (amount=%s)\n", -*************** -*** 496,510 **** - throw JSONRPCError(RPC_WALLET_ERROR, "Could not find previous JoinSplit anchor"); - } - - for (const uint256& commitment : prevJoinSplit.commitments) { - tree.append(commitment); -! previousCommitments.push_back(commitment); - } -! ZCIncrementalWitness changeWitness = tree.witness(); -! jsAnchor = changeWitness.root(); -! uint256 changeCommitment = prevJoinSplit.commitments[changeOutputIndex]; -! intermediates.insert(std::make_pair(tree.root(), tree)); -! witnesses.push_back(changeWitness); - - // Decrypt the change note's ciphertext to retrieve some data we need - ZCNoteDecryption decryptor(spendingkey_.viewing_key()); ---- 540,562 ---- - throw JSONRPCError(RPC_WALLET_ERROR, "Could not find previous JoinSplit anchor"); - } - -+ assert(changeOutputIndex != -1); -+ boost::optional changeWitness; -+ int n = 0; - for (const uint256& commitment : prevJoinSplit.commitments) { - tree.append(commitment); -! previousCommitments.push_back(commitment); -! if (!changeWitness && changeOutputIndex == n++) { -! changeWitness = tree.witness(); -! } else if (changeWitness) { -! changeWitness.get().append(commitment); -! } - } -! if (changeWitness) { -! witnesses.push_back(changeWitness); -! } -! jsAnchor = tree.root(); -! intermediates.insert(std::make_pair(tree.root(), tree)); // chained js are interstitial (found in between block boundaries) - - // Decrypt the change note's ciphertext to retrieve some data we need - ZCNoteDecryption decryptor(spendingkey_.viewing_key()); -*************** -*** 538,543 **** ---- 590,596 ---- - // - std::vector vInputNotes; - std::vector vOutPoints; -+ std::vector> vInputWitnesses; - uint256 inputAnchor; - int numInputsNeeded = (jsChange>0) ? 1 : 0; - while (numInputsNeeded++ < ZC_NUM_JS_INPUTS && zInputsDeque.size() > 0) { -*************** -*** 547,552 **** ---- 600,613 ---- - CAmount noteFunds = std::get<2>(t); - zInputsDeque.pop_front(); - -+ WitnessAnchorData wad = jsopWitnessAnchorMap[ jso.ToString() ]; -+ vInputWitnesses.push_back(wad.witness); -+ if (inputAnchor.IsNull()) { -+ inputAnchor = wad.anchor; -+ } else if (inputAnchor != wad.anchor) { -+ throw JSONRPCError(RPC_WALLET_ERROR, "Selected input notes do not share the same anchor"); -+ } -+ - vOutPoints.push_back(jso); - vInputNotes.push_back(note); - -*************** -*** 563,574 **** - - // Add history of previous commitments to witness - if (vInputNotes.size() > 0) { -! std::vector> vInputWitnesses; -! { -! LOCK(cs_main); -! pwalletMain->GetNoteWitnesses(vOutPoints, vInputWitnesses, inputAnchor); -! } -! - if (vInputWitnesses.size()==0) { - throw JSONRPCError(RPC_WALLET_ERROR, "Could not find witness for note commitment"); - } ---- 624,630 ---- - - // Add history of previous commitments to witness - if (vInputNotes.size() > 0) { -! - if (vInputWitnesses.size()==0) { - throw JSONRPCError(RPC_WALLET_ERROR, "Could not find witness for note commitment"); - } -*************** -*** 760,765 **** ---- 816,826 ---- - t_inputs_.push_back(utxo); - } - -+ // sort in ascending order, so smaller utxos appear first -+ std::sort(t_inputs_.begin(), t_inputs_.end(), [](SendManyInputUTXO i, SendManyInputUTXO j) -> bool { -+ return ( std::get<2>(i) < std::get<2>(j)); -+ }); -+ - return t_inputs_.size() > 0; - } - -*************** -*** 894,901 **** - info.vpub_new, - !this->testmode); - -! if (!(jsdesc.Verify(*pzcashParams, joinSplitPubKey_))) { -! throw std::runtime_error("error verifying joinsplit"); - } - - mtx.vjoinsplit.push_back(jsdesc); ---- 955,965 ---- - info.vpub_new, - !this->testmode); - -! { -! auto verifier = libzcash::ProofVerifier::Strict(); -! if (!(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey_))) { -! throw std::runtime_error("error verifying joinsplit"); -! } - } - - mtx.vjoinsplit.push_back(jsdesc); -diff -crB ./src/wallet/asyncrpcoperation_sendmany.h ../../komodo-jl777/src/wallet/asyncrpcoperation_sendmany.h -*** ./src/wallet/asyncrpcoperation_sendmany.h 2017-01-03 10:40:50.427340097 +0000 ---- ../../komodo-jl777/src/wallet/asyncrpcoperation_sendmany.h 2017-01-03 09:49:08.872507185 +0000 -*************** -*** 14,22 **** - #include "json/json_spirit_value.h" - #include "wallet.h" - - #include - -! // TODO: Compute fee based on a heuristic, e.g. (num tx output * dust threshold) + joinsplit bytes * ? - #define ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE 10000 - - using namespace libzcash; ---- 14,23 ---- - #include "json/json_spirit_value.h" - #include "wallet.h" - -+ #include - #include - -! // Default transaction fee if caller does not specify one. - #define ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE 10000 - - using namespace libzcash; -*************** -*** 41,49 **** - CAmount vpub_new = 0; - }; - - class AsyncRPCOperation_sendmany : public AsyncRPCOperation { - public: -! AsyncRPCOperation_sendmany(std::string fromAddress, std::vector tOutputs, std::vector zOutputs, int minDepth); - virtual ~AsyncRPCOperation_sendmany(); - - // We don't want to be copied or moved around ---- 42,56 ---- - CAmount vpub_new = 0; - }; - -+ // A struct to help us track the witness and anchor for a given JSOutPoint -+ struct WitnessAnchorData { -+ boost::optional witness; -+ uint256 anchor; -+ }; -+ - class AsyncRPCOperation_sendmany : public AsyncRPCOperation { - public: -! AsyncRPCOperation_sendmany(std::string fromAddress, std::vector tOutputs, std::vector zOutputs, int minDepth, CAmount fee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE); - virtual ~AsyncRPCOperation_sendmany(); - - // We don't want to be copied or moved around -*************** -*** 59,64 **** ---- 66,72 ---- - private: - friend class TEST_FRIEND_AsyncRPCOperation_sendmany; // class for unit testing - -+ CAmount fee_; - int mindepth_; - std::string fromaddress_; - bool isfromtaddr_; -*************** -*** 70,76 **** - uint256 joinSplitPubKey_; - unsigned char joinSplitPrivKey_[crypto_sign_SECRETKEYBYTES]; - -! - std::vector t_outputs_; - std::vector z_outputs_; - std::vector t_inputs_; ---- 78,86 ---- - uint256 joinSplitPubKey_; - unsigned char joinSplitPrivKey_[crypto_sign_SECRETKEYBYTES]; - -! // The key is the result string from calling JSOutPoint::ToString() -! std::unordered_map jsopWitnessAnchorMap; -! - std::vector t_outputs_; - std::vector z_outputs_; - std::vector t_inputs_; -diff -crB ./src/wallet/gtest/test_wallet.cpp ../../komodo-jl777/src/wallet/gtest/test_wallet.cpp -*** ./src/wallet/gtest/test_wallet.cpp 2017-01-03 10:40:50.431340299 +0000 ---- ../../komodo-jl777/src/wallet/gtest/test_wallet.cpp 2017-01-03 09:49:08.872507185 +0000 -*************** -*** 5,11 **** ---- 5,13 ---- - #include "base58.h" - #include "chainparams.h" - #include "main.h" -+ #include "primitives/block.h" - #include "random.h" -+ #include "utiltest.h" - #include "wallet/wallet.h" - #include "zcash/JoinSplit.hpp" - #include "zcash/Note.hpp" -*************** -*** 29,37 **** - - MOCK_METHOD2(WriteTx, bool(uint256 hash, const CWalletTx& wtx)); - MOCK_METHOD1(WriteWitnessCacheSize, bool(int64_t nWitnessCacheSize)); - }; - -! template void CWallet::WriteWitnessCache(MockWalletDB& walletdb); - - class TestWallet : public CWallet { - public: ---- 31,41 ---- - - MOCK_METHOD2(WriteTx, bool(uint256 hash, const CWalletTx& wtx)); - MOCK_METHOD1(WriteWitnessCacheSize, bool(int64_t nWitnessCacheSize)); -+ MOCK_METHOD1(WriteBestBlock, bool(const CBlockLocator& loc)); - }; - -! template void CWallet::SetBestChainINTERNAL( -! MockWalletDB& walletdb, const CBlockLocator& loc); - - class TestWallet : public CWallet { - public: -*************** -*** 50,60 **** - ZCIncrementalMerkleTree tree) { - CWallet::IncrementNoteWitnesses(pindex, pblock, tree); - } -! void DecrementNoteWitnesses() { -! CWallet::DecrementNoteWitnesses(); - } -! void WriteWitnessCache(MockWalletDB& walletdb) { -! CWallet::WriteWitnessCache(walletdb); - } - bool UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx) { - return CWallet::UpdatedNoteData(wtxIn, wtx); ---- 54,64 ---- - ZCIncrementalMerkleTree tree) { - CWallet::IncrementNoteWitnesses(pindex, pblock, tree); - } -! void DecrementNoteWitnesses(const CBlockIndex* pindex) { -! CWallet::DecrementNoteWitnesses(pindex); - } -! void SetBestChain(MockWalletDB& walletdb, const CBlockLocator& loc) { -! CWallet::SetBestChainINTERNAL(walletdb, loc); - } - bool UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx) { - return CWallet::UpdatedNoteData(wtxIn, wtx); -*************** -*** 65,183 **** - }; - - CWalletTx GetValidReceive(const libzcash::SpendingKey& sk, CAmount value, bool randomInputs) { -! CMutableTransaction mtx; -! mtx.nVersion = 2; // Enable JoinSplits -! mtx.vin.resize(2); -! if (randomInputs) { -! mtx.vin[0].prevout.hash = GetRandHash(); -! mtx.vin[1].prevout.hash = GetRandHash(); -! } else { -! mtx.vin[0].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); -! mtx.vin[1].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000002"); -! } -! mtx.vin[0].prevout.n = 0; -! mtx.vin[1].prevout.n = 0; -! -! // Generate an ephemeral keypair. -! uint256 joinSplitPubKey; -! unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES]; -! crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey); -! mtx.joinSplitPubKey = joinSplitPubKey; -! -! boost::array inputs = { -! libzcash::JSInput(), // dummy input -! libzcash::JSInput() // dummy input -! }; -! -! boost::array outputs = { -! libzcash::JSOutput(sk.address(), value), -! libzcash::JSOutput(sk.address(), value) -! }; -! -! boost::array output_notes; -! -! // Prepare JoinSplits -! uint256 rt; -! JSDescription jsdesc {*params, mtx.joinSplitPubKey, rt, -! inputs, outputs, value, 0, false}; -! mtx.vjoinsplit.push_back(jsdesc); -! -! // Empty output script. -! CScript scriptCode; -! CTransaction signTx(mtx); -! uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL); -! -! // Add the signature -! assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL, -! dataToBeSigned.begin(), 32, -! joinSplitPrivKey -! ) == 0); -! -! CTransaction tx {mtx}; -! CWalletTx wtx {NULL, tx}; -! return wtx; - } - - libzcash::Note GetNote(const libzcash::SpendingKey& sk, - const CTransaction& tx, size_t js, size_t n) { -! ZCNoteDecryption decryptor {sk.viewing_key()}; -! auto hSig = tx.vjoinsplit[js].h_sig(*params, tx.joinSplitPubKey); -! auto note_pt = libzcash::NotePlaintext::decrypt( -! decryptor, -! tx.vjoinsplit[js].ciphertexts[n], -! tx.vjoinsplit[js].ephemeralKey, -! hSig, -! (unsigned char) n); -! return note_pt.note(sk.address()); - } - - CWalletTx GetValidSpend(const libzcash::SpendingKey& sk, - const libzcash::Note& note, CAmount value) { -! CMutableTransaction mtx; -! mtx.vout.resize(2); -! mtx.vout[0].nValue = value; -! mtx.vout[1].nValue = 0; -! -! // Generate an ephemeral keypair. -! uint256 joinSplitPubKey; -! unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES]; -! crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey); -! mtx.joinSplitPubKey = joinSplitPubKey; -! -! // Fake tree for the unused witness -! ZCIncrementalMerkleTree tree; -! -! boost::array inputs = { -! libzcash::JSInput(tree.witness(), note, sk), -! libzcash::JSInput() // dummy input -! }; -! -! boost::array outputs = { -! libzcash::JSOutput(), // dummy output -! libzcash::JSOutput() // dummy output -! }; -! -! boost::array output_notes; -! -! // Prepare JoinSplits -! uint256 rt; -! JSDescription jsdesc {*params, mtx.joinSplitPubKey, rt, -! inputs, outputs, 0, value, false}; -! mtx.vjoinsplit.push_back(jsdesc); -! -! // Empty output script. -! CScript scriptCode; -! CTransaction signTx(mtx); -! uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL); -! -! // Add the signature -! assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL, -! dataToBeSigned.begin(), 32, -! joinSplitPrivKey -! ) == 0); -! CTransaction tx {mtx}; -! CWalletTx wtx {NULL, tx}; -! return wtx; - } - - TEST(wallet_tests, setup_datadir_location_run_as_first_test) { ---- 69,85 ---- - }; - - CWalletTx GetValidReceive(const libzcash::SpendingKey& sk, CAmount value, bool randomInputs) { -! return GetValidReceive(*params, sk, value, randomInputs); - } - - libzcash::Note GetNote(const libzcash::SpendingKey& sk, - const CTransaction& tx, size_t js, size_t n) { -! return GetNote(*params, sk, tx, js, n); - } - - CWalletTx GetValidSpend(const libzcash::SpendingKey& sk, - const libzcash::Note& note, CAmount value) { -! return GetValidSpend(*params, sk, note, value); - } - - TEST(wallet_tests, setup_datadir_location_run_as_first_test) { -*************** -*** 656,662 **** - EXPECT_TRUE((bool) witnesses[1]); - - // Until #1302 is implemented, this should triggger an assertion -! EXPECT_DEATH(wallet.DecrementNoteWitnesses(), - "Assertion `nWitnessCacheSize > 0' failed."); - } - ---- 558,564 ---- - EXPECT_TRUE((bool) witnesses[1]); - - // Until #1302 is implemented, this should triggger an assertion -! EXPECT_DEATH(wallet.DecrementNoteWitnesses(&index), - "Assertion `nWitnessCacheSize > 0' failed."); - } - -*************** -*** 729,735 **** - - // Decrementing should give us the previous anchor - uint256 anchor3; -! wallet.DecrementNoteWitnesses(); - witnesses.clear(); - wallet.GetNoteWitnesses(notes, witnesses, anchor3); - EXPECT_FALSE((bool) witnesses[0]); ---- 631,637 ---- - - // Decrementing should give us the previous anchor - uint256 anchor3; -! wallet.DecrementNoteWitnesses(&index2); - witnesses.clear(); - wallet.GetNoteWitnesses(notes, witnesses, anchor3); - EXPECT_FALSE((bool) witnesses[0]); -*************** -*** 754,759 **** ---- 656,871 ---- - } - } - -+ TEST(wallet_tests, CachedWitnessesDecrementFirst) { -+ TestWallet wallet; -+ uint256 anchor2; -+ CBlock block2; -+ CBlockIndex index2(block2); -+ ZCIncrementalMerkleTree tree; -+ -+ auto sk = libzcash::SpendingKey::random(); -+ wallet.AddSpendingKey(sk); -+ -+ { -+ // First transaction (case tested in _empty_chain) -+ auto wtx = GetValidReceive(sk, 10, true); -+ auto note = GetNote(sk, wtx, 0, 1); -+ auto nullifier = note.nullifier(sk); -+ -+ mapNoteData_t noteData; -+ JSOutPoint jsoutpt {wtx.GetHash(), 0, 1}; -+ CNoteData nd {sk.address(), nullifier}; -+ noteData[jsoutpt] = nd; -+ wtx.SetNoteData(noteData); -+ wallet.AddToWallet(wtx, true, NULL); -+ -+ // First block (case tested in _empty_chain) -+ CBlock block1; -+ block1.vtx.push_back(wtx); -+ CBlockIndex index1(block1); -+ index1.nHeight = 1; -+ wallet.IncrementNoteWitnesses(&index1, &block1, tree); -+ } -+ -+ { -+ // Second transaction (case tested in _chain_tip) -+ auto wtx = GetValidReceive(sk, 50, true); -+ auto note = GetNote(sk, wtx, 0, 1); -+ auto nullifier = note.nullifier(sk); -+ -+ mapNoteData_t noteData; -+ JSOutPoint jsoutpt {wtx.GetHash(), 0, 1}; -+ CNoteData nd {sk.address(), nullifier}; -+ noteData[jsoutpt] = nd; -+ wtx.SetNoteData(noteData); -+ wallet.AddToWallet(wtx, true, NULL); -+ -+ std::vector notes {jsoutpt}; -+ std::vector> witnesses; -+ -+ // Second block (case tested in _chain_tip) -+ block2.vtx.push_back(wtx); -+ index2.nHeight = 2; -+ wallet.IncrementNoteWitnesses(&index2, &block2, tree); -+ // Called to fetch anchor -+ wallet.GetNoteWitnesses(notes, witnesses, anchor2); -+ } -+ -+ { -+ // Third transaction - never mined -+ auto wtx = GetValidReceive(sk, 20, true); -+ auto note = GetNote(sk, wtx, 0, 1); -+ auto nullifier = note.nullifier(sk); -+ -+ mapNoteData_t noteData; -+ JSOutPoint jsoutpt {wtx.GetHash(), 0, 1}; -+ CNoteData nd {sk.address(), nullifier}; -+ noteData[jsoutpt] = nd; -+ wtx.SetNoteData(noteData); -+ wallet.AddToWallet(wtx, true, NULL); -+ -+ std::vector notes {jsoutpt}; -+ std::vector> witnesses; -+ uint256 anchor3; -+ -+ wallet.GetNoteWitnesses(notes, witnesses, anchor3); -+ EXPECT_FALSE((bool) witnesses[0]); -+ -+ // Decrementing (before the transaction has ever seen an increment) -+ // should give us the previous anchor -+ uint256 anchor4; -+ wallet.DecrementNoteWitnesses(&index2); -+ witnesses.clear(); -+ wallet.GetNoteWitnesses(notes, witnesses, anchor4); -+ EXPECT_FALSE((bool) witnesses[0]); -+ // Should not equal second anchor because none of these notes had witnesses -+ EXPECT_NE(anchor2, anchor4); -+ -+ // Re-incrementing with the same block should give the same result -+ uint256 anchor5; -+ wallet.IncrementNoteWitnesses(&index2, &block2, tree); -+ witnesses.clear(); -+ wallet.GetNoteWitnesses(notes, witnesses, anchor5); -+ EXPECT_FALSE((bool) witnesses[0]); -+ EXPECT_EQ(anchor3, anchor5); -+ } -+ } -+ -+ TEST(wallet_tests, CachedWitnessesCleanIndex) { -+ TestWallet wallet; -+ CBlock block1; -+ CBlock block2; -+ CBlock block3; -+ CBlockIndex index1(block1); -+ CBlockIndex index2(block2); -+ CBlockIndex index3(block3); -+ ZCIncrementalMerkleTree tree; -+ -+ auto sk = libzcash::SpendingKey::random(); -+ wallet.AddSpendingKey(sk); -+ -+ { -+ // First transaction (case tested in _empty_chain) -+ auto wtx = GetValidReceive(sk, 10, true); -+ auto note = GetNote(sk, wtx, 0, 1); -+ auto nullifier = note.nullifier(sk); -+ -+ mapNoteData_t noteData; -+ JSOutPoint jsoutpt {wtx.GetHash(), 0, 1}; -+ CNoteData nd {sk.address(), nullifier}; -+ noteData[jsoutpt] = nd; -+ wtx.SetNoteData(noteData); -+ wallet.AddToWallet(wtx, true, NULL); -+ -+ // First block (case tested in _empty_chain) -+ block1.vtx.push_back(wtx); -+ index1.nHeight = 1; -+ wallet.IncrementNoteWitnesses(&index1, &block1, tree); -+ } -+ -+ { -+ // Second transaction (case tested in _chain_tip) -+ auto wtx = GetValidReceive(sk, 50, true); -+ auto note = GetNote(sk, wtx, 0, 1); -+ auto nullifier = note.nullifier(sk); -+ -+ mapNoteData_t noteData; -+ JSOutPoint jsoutpt {wtx.GetHash(), 0, 1}; -+ CNoteData nd {sk.address(), nullifier}; -+ noteData[jsoutpt] = nd; -+ wtx.SetNoteData(noteData); -+ wallet.AddToWallet(wtx, true, NULL); -+ -+ // Second block (case tested in _chain_tip) -+ block2.vtx.push_back(wtx); -+ index2.nHeight = 2; -+ wallet.IncrementNoteWitnesses(&index2, &block2, tree); -+ } -+ -+ { -+ // Third transaction -+ auto wtx = GetValidReceive(sk, 20, true); -+ auto note = GetNote(sk, wtx, 0, 1); -+ auto nullifier = note.nullifier(sk); -+ -+ mapNoteData_t noteData; -+ JSOutPoint jsoutpt {wtx.GetHash(), 0, 1}; -+ CNoteData nd {sk.address(), nullifier}; -+ noteData[jsoutpt] = nd; -+ wtx.SetNoteData(noteData); -+ wallet.AddToWallet(wtx, true, NULL); -+ -+ std::vector notes {jsoutpt}; -+ std::vector> witnesses; -+ uint256 anchor3; -+ -+ // Third block -+ block3.vtx.push_back(wtx); -+ index3.nHeight = 3; -+ wallet.IncrementNoteWitnesses(&index3, &block3, tree); -+ wallet.GetNoteWitnesses(notes, witnesses, anchor3); -+ -+ // Now pretend we are reindexing: the chain is cleared, and each block is -+ // used to increment witnesses again. -+ wallet.IncrementNoteWitnesses(&index1, &block1, tree); -+ uint256 anchor3a; -+ witnesses.clear(); -+ wallet.GetNoteWitnesses(notes, witnesses, anchor3a); -+ EXPECT_TRUE((bool) witnesses[0]); -+ // Should equal third anchor because witness cache unaffected -+ EXPECT_EQ(anchor3, anchor3a); -+ -+ wallet.IncrementNoteWitnesses(&index2, &block2, tree); -+ uint256 anchor3b; -+ witnesses.clear(); -+ wallet.GetNoteWitnesses(notes, witnesses, anchor3b); -+ EXPECT_TRUE((bool) witnesses[0]); -+ EXPECT_EQ(anchor3, anchor3b); -+ -+ // Pretend a reorg happened that was recorded in the block files -+ wallet.DecrementNoteWitnesses(&index2); -+ uint256 anchor3c; -+ witnesses.clear(); -+ wallet.GetNoteWitnesses(notes, witnesses, anchor3c); -+ EXPECT_TRUE((bool) witnesses[0]); -+ EXPECT_EQ(anchor3, anchor3c); -+ -+ wallet.IncrementNoteWitnesses(&index2, &block2, tree); -+ uint256 anchor3d; -+ witnesses.clear(); -+ wallet.GetNoteWitnesses(notes, witnesses, anchor3d); -+ EXPECT_TRUE((bool) witnesses[0]); -+ EXPECT_EQ(anchor3, anchor3d); -+ -+ wallet.IncrementNoteWitnesses(&index3, &block3, tree); -+ uint256 anchor3e; -+ witnesses.clear(); -+ wallet.GetNoteWitnesses(notes, witnesses, anchor3e); -+ EXPECT_TRUE((bool) witnesses[0]); -+ EXPECT_EQ(anchor3, anchor3e); -+ } -+ } -+ - TEST(wallet_tests, ClearNoteWitnessCache) { - TestWallet wallet; - -*************** -*** 761,766 **** ---- 873,879 ---- - wallet.AddSpendingKey(sk); - - auto wtx = GetValidReceive(sk, 10, true); -+ auto hash = wtx.GetHash(); - auto note = GetNote(sk, wtx, 0, 0); - auto nullifier = note.nullifier(sk); - -*************** -*** 774,779 **** ---- 887,894 ---- - // Pretend we mined the tx by adding a fake witness - ZCIncrementalMerkleTree tree; - wtx.mapNoteData[jsoutpt].witnesses.push_front(tree.witness()); -+ wtx.mapNoteData[jsoutpt].witnessHeight = 1; -+ wallet.nWitnessCacheSize = 1; - - wallet.AddToWallet(wtx, true, NULL); - -*************** -*** 785,790 **** ---- 900,907 ---- - wallet.GetNoteWitnesses(notes, witnesses, anchor2); - EXPECT_TRUE((bool) witnesses[0]); - EXPECT_FALSE((bool) witnesses[1]); -+ EXPECT_EQ(1, wallet.mapWallet[hash].mapNoteData[jsoutpt].witnessHeight); -+ EXPECT_EQ(1, wallet.nWitnessCacheSize); - - // After clearing, we should not have a witness for either note - wallet.ClearNoteWitnessCache(); -*************** -*** 792,802 **** ---- 909,922 ---- - wallet.GetNoteWitnesses(notes, witnesses, anchor2); - EXPECT_FALSE((bool) witnesses[0]); - EXPECT_FALSE((bool) witnesses[1]); -+ EXPECT_EQ(-1, wallet.mapWallet[hash].mapNoteData[jsoutpt].witnessHeight); -+ EXPECT_EQ(0, wallet.nWitnessCacheSize); - } - - TEST(wallet_tests, WriteWitnessCache) { - TestWallet wallet; - MockWalletDB walletdb; -+ CBlockLocator loc; - - auto sk = libzcash::SpendingKey::random(); - wallet.AddSpendingKey(sk); -*************** -*** 807,813 **** - // TxnBegin fails - EXPECT_CALL(walletdb, TxnBegin()) - .WillOnce(Return(false)); -! wallet.WriteWitnessCache(walletdb); - EXPECT_CALL(walletdb, TxnBegin()) - .WillRepeatedly(Return(true)); - ---- 927,933 ---- - // TxnBegin fails - EXPECT_CALL(walletdb, TxnBegin()) - .WillOnce(Return(false)); -! wallet.SetBestChain(walletdb, loc); - EXPECT_CALL(walletdb, TxnBegin()) - .WillRepeatedly(Return(true)); - -*************** -*** 816,829 **** - .WillOnce(Return(false)); - EXPECT_CALL(walletdb, TxnAbort()) - .Times(1); -! wallet.WriteWitnessCache(walletdb); - - // WriteTx throws - EXPECT_CALL(walletdb, WriteTx(wtx.GetHash(), wtx)) - .WillOnce(ThrowLogicError()); - EXPECT_CALL(walletdb, TxnAbort()) - .Times(1); -! wallet.WriteWitnessCache(walletdb); - EXPECT_CALL(walletdb, WriteTx(wtx.GetHash(), wtx)) - .WillRepeatedly(Return(true)); - ---- 936,949 ---- - .WillOnce(Return(false)); - EXPECT_CALL(walletdb, TxnAbort()) - .Times(1); -! wallet.SetBestChain(walletdb, loc); - - // WriteTx throws - EXPECT_CALL(walletdb, WriteTx(wtx.GetHash(), wtx)) - .WillOnce(ThrowLogicError()); - EXPECT_CALL(walletdb, TxnAbort()) - .Times(1); -! wallet.SetBestChain(walletdb, loc); - EXPECT_CALL(walletdb, WriteTx(wtx.GetHash(), wtx)) - .WillRepeatedly(Return(true)); - -*************** -*** 832,857 **** - .WillOnce(Return(false)); - EXPECT_CALL(walletdb, TxnAbort()) - .Times(1); -! wallet.WriteWitnessCache(walletdb); - - // WriteWitnessCacheSize throws - EXPECT_CALL(walletdb, WriteWitnessCacheSize(0)) - .WillOnce(ThrowLogicError()); - EXPECT_CALL(walletdb, TxnAbort()) - .Times(1); -! wallet.WriteWitnessCache(walletdb); - EXPECT_CALL(walletdb, WriteWitnessCacheSize(0)) - .WillRepeatedly(Return(true)); - - // TxCommit fails - EXPECT_CALL(walletdb, TxnCommit()) - .WillOnce(Return(false)); -! wallet.WriteWitnessCache(walletdb); - EXPECT_CALL(walletdb, TxnCommit()) - .WillRepeatedly(Return(true)); - - // Everything succeeds -! wallet.WriteWitnessCache(walletdb); - } - - TEST(wallet_tests, UpdateNullifierNoteMap) { ---- 952,993 ---- - .WillOnce(Return(false)); - EXPECT_CALL(walletdb, TxnAbort()) - .Times(1); -! wallet.SetBestChain(walletdb, loc); - - // WriteWitnessCacheSize throws - EXPECT_CALL(walletdb, WriteWitnessCacheSize(0)) - .WillOnce(ThrowLogicError()); - EXPECT_CALL(walletdb, TxnAbort()) - .Times(1); -! wallet.SetBestChain(walletdb, loc); - EXPECT_CALL(walletdb, WriteWitnessCacheSize(0)) - .WillRepeatedly(Return(true)); - -+ // WriteBestBlock fails -+ EXPECT_CALL(walletdb, WriteBestBlock(loc)) -+ .WillOnce(Return(false)); -+ EXPECT_CALL(walletdb, TxnAbort()) -+ .Times(1); -+ wallet.SetBestChain(walletdb, loc); -+ -+ // WriteBestBlock throws -+ EXPECT_CALL(walletdb, WriteBestBlock(loc)) -+ .WillOnce(ThrowLogicError()); -+ EXPECT_CALL(walletdb, TxnAbort()) -+ .Times(1); -+ wallet.SetBestChain(walletdb, loc); -+ EXPECT_CALL(walletdb, WriteBestBlock(loc)) -+ .WillRepeatedly(Return(true)); -+ - // TxCommit fails - EXPECT_CALL(walletdb, TxnCommit()) - .WillOnce(Return(false)); -! wallet.SetBestChain(walletdb, loc); - EXPECT_CALL(walletdb, TxnCommit()) - .WillRepeatedly(Return(true)); - - // Everything succeeds -! wallet.SetBestChain(walletdb, loc); - } - - TEST(wallet_tests, UpdateNullifierNoteMap) { -*************** -*** 913,918 **** ---- 1049,1055 ---- - // Pretend we mined the tx by adding a fake witness - ZCIncrementalMerkleTree tree; - wtx.mapNoteData[jsoutpt].witnesses.push_front(tree.witness()); -+ wtx.mapNoteData[jsoutpt].witnessHeight = 100; - - // Now pretend we added the key for the second note, and - // the tx was "added" to the wallet again to update it. -*************** -*** 925,935 **** ---- 1062,1074 ---- - // The txs should initially be different - EXPECT_NE(wtx.mapNoteData, wtx2.mapNoteData); - EXPECT_EQ(1, wtx.mapNoteData[jsoutpt].witnesses.size()); -+ EXPECT_EQ(100, wtx.mapNoteData[jsoutpt].witnessHeight); - - // After updating, they should be the same - EXPECT_TRUE(wallet.UpdatedNoteData(wtx2, wtx)); - EXPECT_EQ(wtx.mapNoteData, wtx2.mapNoteData); - EXPECT_EQ(1, wtx.mapNoteData[jsoutpt].witnesses.size()); -+ EXPECT_EQ(100, wtx.mapNoteData[jsoutpt].witnessHeight); - // TODO: The new note should get witnessed (but maybe not here) (#1350) - } - -diff -crB ./src/wallet/rpcwallet.cpp ../../komodo-jl777/src/wallet/rpcwallet.cpp -*** ./src/wallet/rpcwallet.cpp 2017-01-03 10:40:50.431340299 +0000 ---- ../../komodo-jl777/src/wallet/rpcwallet.cpp 2017-01-03 09:49:08.876507395 +0000 -*************** -*** 2622,2627 **** ---- 2622,2633 ---- - sample_times.push_back(benchmark_verify_equihash()); - } else if (benchmarktype == "validatelargetx") { - sample_times.push_back(benchmark_large_tx()); -+ } else if (benchmarktype == "trydecryptnotes") { -+ int nAddrs = params[2].get_int(); -+ sample_times.push_back(benchmark_try_decrypt_notes(nAddrs)); -+ } else if (benchmarktype == "incnotewitnesses") { -+ int nTxs = params[2].get_int(); -+ sample_times.push_back(benchmark_increment_note_witnesses(nTxs)); - } else { - throw JSONRPCError(RPC_TYPE_ERROR, "Invalid benchmarktype"); - } -*************** -*** 2849,2855 **** - vpub_old, - vpub_new); - -! assert(jsdesc.Verify(*pzcashParams, joinSplitPubKey)); - - mtx.vjoinsplit.push_back(jsdesc); - ---- 2855,2864 ---- - vpub_old, - vpub_new); - -! { -! auto verifier = libzcash::ProofVerifier::Strict(); -! assert(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey)); -! } - - mtx.vjoinsplit.push_back(jsdesc); - -*************** -*** 3310,3326 **** - return ret; - } - - Value z_sendmany(const Array& params, bool fHelp) - { - if (!EnsureWalletIsAvailable(fHelp)) - return Value::null; - -! if (fHelp || params.size() < 2 || params.size() > 3) - throw runtime_error( -! "z_sendmany \"fromaddress\" [{\"address\":... ,\"amount\":...},...] ( minconf )\n" - "\nSend multiple times. Amounts are double-precision floating point numbers." - "\nChange from a taddr flows to a new taddr address, while change from zaddr returns to itself." -! "\nWhen sending coinbase UTXOs to a zaddr, change is not alllowed. The entire value of the UTXO(s) must be consumed." - + HelpRequiringPassphrase() + "\n" - "\nArguments:\n" - "1. \"fromaddress\" (string, required) The taddr or zaddr to send the funds from.\n" ---- 3319,3347 ---- - return ret; - } - -+ -+ // Here we define the maximum number of zaddr outputs that can be included in a transaction. -+ // If input notes are small, we might actually require more than one joinsplit per zaddr output. -+ // For now though, we assume we use one joinsplit per zaddr output (and the second output note is change). -+ // We reduce the result by 1 to ensure there is room for non-joinsplit CTransaction data. -+ #define Z_SENDMANY_MAX_ZADDR_OUTPUTS ((MAX_TX_SIZE / JSDescription().GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION)) - 1) -+ -+ // transaction.h comment: spending taddr output requires CTxIn >= 148 bytes and typical taddr txout is 34 bytes -+ #define CTXIN_SPEND_DUST_SIZE 148 -+ #define CTXOUT_REGULAR_SIZE 34 -+ - Value z_sendmany(const Array& params, bool fHelp) - { - if (!EnsureWalletIsAvailable(fHelp)) - return Value::null; - -! if (fHelp || params.size() < 2 || params.size() > 4) - throw runtime_error( -! "z_sendmany \"fromaddress\" [{\"address\":... ,\"amount\":...},...] ( minconf ) ( fee )\n" - "\nSend multiple times. Amounts are double-precision floating point numbers." - "\nChange from a taddr flows to a new taddr address, while change from zaddr returns to itself." -! "\nWhen sending coinbase UTXOs to a zaddr, change is not allowed. The entire value of the UTXO(s) must be consumed." -! + strprintf("\nCurrently, the maximum number of zaddr outputs is %d due to transaction size limits.\n", Z_SENDMANY_MAX_ZADDR_OUTPUTS) - + HelpRequiringPassphrase() + "\n" - "\nArguments:\n" - "1. \"fromaddress\" (string, required) The taddr or zaddr to send the funds from.\n" -*************** -*** 3331,3336 **** ---- 3352,3359 ---- - " \"memo\":memo (string, optional) If the address is a zaddr, raw data represented in hexadecimal string format\n" - " }, ... ]\n" - "3. minconf (numeric, optional, default=1) Only use funds confirmed at least this many times.\n" -+ "4. fee (numeric, optional, default=" -+ + strprintf("%s", FormatMoney(ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n" - "\nResult:\n" - "\"operationid\" (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n" - ); -*************** -*** 3371,3376 **** ---- 3394,3400 ---- - // Recipients - std::vector taddrRecipients; - std::vector zaddrRecipients; -+ CAmount nTotalOut = 0; - - BOOST_FOREACH(Value& output, outputs) - { -*************** -*** 3426,3431 **** ---- 3450,3481 ---- - } else { - taddrRecipients.push_back( SendManyRecipient(address, nAmount, memo) ); - } -+ -+ nTotalOut += nAmount; -+ } -+ -+ // Check the number of zaddr outputs does not exceed the limit. -+ if (zaddrRecipients.size() > Z_SENDMANY_MAX_ZADDR_OUTPUTS) { -+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, too many zaddr outputs"); -+ } -+ -+ // As a sanity check, estimate and verify that the size of the transaction will be valid. -+ // Depending on the input notes, the actual tx size may turn out to be larger and perhaps invalid. -+ size_t txsize = 0; -+ CMutableTransaction mtx; -+ mtx.nVersion = 2; -+ for (int i = 0; i < zaddrRecipients.size(); i++) { -+ mtx.vjoinsplit.push_back(JSDescription()); -+ } -+ CTransaction tx(mtx); -+ txsize += tx.GetSerializeSize(SER_NETWORK, tx.nVersion); -+ if (fromTaddr) { -+ txsize += CTXIN_SPEND_DUST_SIZE; -+ txsize += CTXOUT_REGULAR_SIZE; // There will probably be taddr change -+ } -+ txsize += CTXOUT_REGULAR_SIZE * taddrRecipients.size(); -+ if (txsize > MAX_TX_SIZE) { -+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Too many outputs, size of raw transaction would be larger than limit of %d bytes", MAX_TX_SIZE )); - } - - // Minimum confirmations -*************** -*** 3437,3445 **** - throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0"); - } - - // Create operation and add to global queue - std::shared_ptr q = getAsyncRPCQueue(); -! std::shared_ptr operation( new AsyncRPCOperation_sendmany(fromaddress, taddrRecipients, zaddrRecipients, nMinDepth) ); - q->addOperation(operation); - AsyncRPCOperationId operationId = operation->getId(); - return operationId; ---- 3487,3505 ---- - throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0"); - } - -+ // Fee in Zatoshis, not currency format) -+ CAmount nFee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE; -+ if (params.size() > 3) { -+ nFee = AmountFromValue( params[3] ); -+ // Check that the user specified fee is sane. -+ if (nFee > nTotalOut) { -+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the sum of outputs %s", FormatMoney(nFee), FormatMoney(nTotalOut))); -+ } -+ } -+ - // Create operation and add to global queue - std::shared_ptr q = getAsyncRPCQueue(); -! std::shared_ptr operation( new AsyncRPCOperation_sendmany(fromaddress, taddrRecipients, zaddrRecipients, nMinDepth, nFee) ); - q->addOperation(operation); - AsyncRPCOperationId operationId = operation->getId(); - return operationId; -diff -crB ./src/wallet/wallet.cpp ../../komodo-jl777/src/wallet/wallet.cpp -*** ./src/wallet/wallet.cpp 2017-01-03 10:40:50.431340299 +0000 ---- ../../komodo-jl777/src/wallet/wallet.cpp 2017-01-03 09:49:08.876507395 +0000 -*************** -*** 373,386 **** - if (added) { - IncrementNoteWitnesses(pindex, pblock, tree); - } else { -! DecrementNoteWitnesses(); - } - } - - void CWallet::SetBestChain(const CBlockLocator& loc) - { - CWalletDB walletdb(strWalletFile); -! walletdb.WriteBestBlock(loc); - } - - bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit) ---- 373,386 ---- - if (added) { - IncrementNoteWitnesses(pindex, pblock, tree); - } else { -! DecrementNoteWitnesses(pindex); - } - } - - void CWallet::SetBestChain(const CBlockLocator& loc) - { - CWalletDB walletdb(strWalletFile); -! SetBestChainINTERNAL(walletdb, loc); - } - - bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit) -*************** -*** 630,637 **** ---- 630,639 ---- - for (std::pair& wtxItem : mapWallet) { - for (mapNoteData_t::value_type& item : wtxItem.second.mapNoteData) { - item.second.witnesses.clear(); -+ item.second.witnessHeight = -1; - } - } -+ nWitnessCacheSize = 0; - } - - void CWallet::IncrementNoteWitnesses(const CBlockIndex* pindex, -*************** -*** 648,654 **** - // Only increment witnesses that are behind the current height - if (nd->witnessHeight < pindex->nHeight) { - // Witnesses being incremented should always be either -1 -! // (never incremented) or one below pindex - assert((nd->witnessHeight == -1) || - (nd->witnessHeight == pindex->nHeight - 1)); - // Copy the witness for the previous block if we have one ---- 650,656 ---- - // Only increment witnesses that are behind the current height - if (nd->witnessHeight < pindex->nHeight) { - // Witnesses being incremented should always be either -1 -! // (never incremented or decremented) or one below pindex - assert((nd->witnessHeight == -1) || - (nd->witnessHeight == pindex->nHeight - 1)); - // Copy the witness for the previous block if we have one -*************** -*** 739,752 **** - } - } - -! if (fFileBacked) { -! CWalletDB walletdb(strWalletFile); -! WriteWitnessCache(walletdb); -! } - } - } - -! void CWallet::DecrementNoteWitnesses() - { - extern int32_t KOMODO_REWIND; - { ---- 741,753 ---- - } - } - -! // For performance reasons, we write out the witness cache in -! // CWallet::SetBestChain() (which also ensures that overall consistency -! // of the wallet.dat is maintained). - } - } - -! void CWallet::DecrementNoteWitnesses(const CBlockIndex* pindex) - { - extern int32_t KOMODO_REWIND; - { -*************** -*** 756,765 **** - CNoteData* nd = &(item.second); - // Check the validity of the cache - assert(nWitnessCacheSize >= nd->witnesses.size()); -! if (nd->witnesses.size() > 0) { -! nd->witnesses.pop_front(); - } -- nd->witnessHeight -= 1; - } - } - nWitnessCacheSize -= 1; ---- 757,775 ---- - CNoteData* nd = &(item.second); - // Check the validity of the cache - assert(nWitnessCacheSize >= nd->witnesses.size()); -! // Only increment witnesses that are not above the current height -! if (nd->witnessHeight <= pindex->nHeight) { -! // Witnesses being decremented should always be either -1 -! // (never incremented or decremented) or equal to pindex -! assert((nd->witnessHeight == -1) || -! (nd->witnessHeight == pindex->nHeight)); -! if (nd->witnesses.size() > 0) { -! nd->witnesses.pop_front(); -! } -! // pindex is the block being removed, so the new witness cache -! // height is one below it. -! nd->witnessHeight = pindex->nHeight - 1; - } - } - } - nWitnessCacheSize -= 1; -*************** -*** 770,776 **** - assert(nWitnessCacheSize >= nd->witnesses.size()); - } - } -- // TODO: If nWitnessCache is zero, we need to regenerate the caches (#1302) - if ( nWitnessCacheSize <= 0 ) - { - extern char ASSETCHAINS_SYMBOL[16]; ---- 780,785 ---- -*************** -*** 778,787 **** - } - if ( KOMODO_REWIND == 0 ) - assert(nWitnessCacheSize > 0); -! if (fFileBacked) { -! CWalletDB walletdb(strWalletFile); -! WriteWitnessCache(walletdb); -! } - } - } - ---- 787,799 ---- - } - if ( KOMODO_REWIND == 0 ) - assert(nWitnessCacheSize > 0); -! //if (fFileBacked) { -! // CWalletDB walletdb(strWalletFile); -! // WriteWitnessCache(walletdb); -! //} -! // For performance reasons, we write out the witness cache in -! // CWallet::SetBestChain() (which also ensures that overall consistency -! // of the wallet.dat is maintained). - } - } - -*************** -*** 1109,1114 **** ---- 1121,1127 ---- - tmp.at(nd.first).witnesses.assign( - nd.second.witnesses.cbegin(), nd.second.witnesses.cend()); - } -+ tmp.at(nd.first).witnessHeight = nd.second.witnessHeight; - } - // Now copy over the updated note data - wtx.mapNoteData = tmp; -diff -crB ./src/wallet/wallet.h ../../komodo-jl777/src/wallet/wallet.h -*** ./src/wallet/wallet.h 2017-01-03 10:40:50.431340299 +0000 ---- ../../komodo-jl777/src/wallet/wallet.h 2017-01-03 09:49:08.876507395 +0000 -*************** -*** 225,231 **** - */ - std::list witnesses; - -! /** Block height corresponding to the most current witness. */ - int witnessHeight; - - CNoteData() : address(), nullifier(), witnessHeight {-1} { } ---- 225,239 ---- - */ - std::list witnesses; - -! /** -! * Block height corresponding to the most current witness. -! * -! * When we first create a CNoteData in CWallet::FindMyNotes, this is set to -! * -1 as a placeholder. The next time CWallet::ChainTip is called, we can -! * determine what height the witness cache for this note is valid for (even -! * if no witnesses were cached), and so can set the correct value in -! * CWallet::IncrementNoteWitnesses and CWallet::DecrementNoteWitnesses. -! */ - int witnessHeight; - - CNoteData() : address(), nullifier(), witnessHeight {-1} { } -*************** -*** 620,660 **** - void ClearNoteWitnessCache(); - - protected: - void IncrementNoteWitnesses(const CBlockIndex* pindex, - const CBlock* pblock, - ZCIncrementalMerkleTree& tree); -! void DecrementNoteWitnesses(); - - template -! void WriteWitnessCache(WalletDB& walletdb) { - if (!walletdb.TxnBegin()) { - // This needs to be done atomically, so don't do it at all -! LogPrintf("WriteWitnessCache(): Couldn't start atomic write\n"); - return; - } - try { - for (std::pair& wtxItem : mapWallet) { - if (!walletdb.WriteTx(wtxItem.first, wtxItem.second)) { -! LogPrintf("WriteWitnessCache(): Failed to write CWalletTx, aborting atomic write\n"); - walletdb.TxnAbort(); - return; - } - } - if (!walletdb.WriteWitnessCacheSize(nWitnessCacheSize)) { -! LogPrintf("WriteWitnessCache(): Failed to write nWitnessCacheSize, aborting atomic write\n"); - walletdb.TxnAbort(); - return; - } - } catch (const std::exception &exc) { - // Unexpected failure -! LogPrintf("WriteWitnessCache(): Unexpected error during atomic write:\n"); - LogPrintf("%s\n", exc.what()); - walletdb.TxnAbort(); - return; - } - if (!walletdb.TxnCommit()) { - // Couldn't commit all to db, but in-memory state is fine -! LogPrintf("WriteWitnessCache(): Couldn't commit atomic write\n"); - return; - } - } ---- 628,679 ---- - void ClearNoteWitnessCache(); - - protected: -+ /** -+ * pindex is the new tip being connected. -+ */ - void IncrementNoteWitnesses(const CBlockIndex* pindex, - const CBlock* pblock, - ZCIncrementalMerkleTree& tree); -! /** -! * pindex is the old tip being disconnected. -! */ -! void DecrementNoteWitnesses(const CBlockIndex* pindex); - - template -! void SetBestChainINTERNAL(WalletDB& walletdb, const CBlockLocator& loc) { - if (!walletdb.TxnBegin()) { - // This needs to be done atomically, so don't do it at all -! LogPrintf("SetBestChain(): Couldn't start atomic write\n"); - return; - } - try { - for (std::pair& wtxItem : mapWallet) { - if (!walletdb.WriteTx(wtxItem.first, wtxItem.second)) { -! LogPrintf("SetBestChain(): Failed to write CWalletTx, aborting atomic write\n"); - walletdb.TxnAbort(); - return; - } - } - if (!walletdb.WriteWitnessCacheSize(nWitnessCacheSize)) { -! LogPrintf("SetBestChain(): Failed to write nWitnessCacheSize, aborting atomic write\n"); -! walletdb.TxnAbort(); -! return; -! } -! if (!walletdb.WriteBestBlock(loc)) { -! LogPrintf("SetBestChain(): Failed to write best block, aborting atomic write\n"); - walletdb.TxnAbort(); - return; - } - } catch (const std::exception &exc) { - // Unexpected failure -! LogPrintf("SetBestChain(): Unexpected error during atomic write:\n"); - LogPrintf("%s\n", exc.what()); - walletdb.TxnAbort(); - return; - } - if (!walletdb.TxnCommit()) { - // Couldn't commit all to db, but in-memory state is fine -! LogPrintf("SetBestChain(): Couldn't commit atomic write\n"); - return; - } - } -*************** -*** 944,949 **** ---- 963,969 ---- - CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const; - CAmount GetChange(const CTransaction& tx) const; - void ChainTip(const CBlockIndex *pindex, const CBlock *pblock, ZCIncrementalMerkleTree tree, bool added); -+ /** Saves witness caches and best block locator to disk. */ - void SetBestChain(const CBlockLocator& loc); - - DBErrors LoadWallet(bool& fFirstRunRet); -diff -crB ./src/zcash/GenerateParams.cpp ../../komodo-jl777/src/zcash/GenerateParams.cpp -*** ./src/zcash/GenerateParams.cpp 2017-01-03 10:40:50.435340501 +0000 ---- ../../komodo-jl777/src/zcash/GenerateParams.cpp 2017-01-03 09:49:08.876507395 +0000 -*************** -*** 9,26 **** - return 1; - } - -! if(argc != 3) { -! std::cerr << "Usage: " << argv[0] << " provingKeyFileName verificationKeyFileName" << std::endl; - return 1; - } - - std::string pkFile = argv[1]; - std::string vkFile = argv[2]; - - auto p = ZCJoinSplit::Generate(); - - p->saveProvingKey(pkFile); - p->saveVerifyingKey(vkFile); - - delete p; - ---- 9,28 ---- - return 1; - } - -! if(argc != 4) { -! std::cerr << "Usage: " << argv[0] << " provingKeyFileName verificationKeyFileName r1csFileName" << std::endl; - return 1; - } - - std::string pkFile = argv[1]; - std::string vkFile = argv[2]; -+ std::string r1csFile = argv[3]; - - auto p = ZCJoinSplit::Generate(); - - p->saveProvingKey(pkFile); - p->saveVerifyingKey(vkFile); -+ p->saveR1CS(r1csFile); - - delete p; - -diff -crB ./src/zcash/IncrementalMerkleTree.cpp ../../komodo-jl777/src/zcash/IncrementalMerkleTree.cpp -*** ./src/zcash/IncrementalMerkleTree.cpp 2017-01-03 10:40:50.435340501 +0000 ---- ../../komodo-jl777/src/zcash/IncrementalMerkleTree.cpp 2017-01-03 09:49:08.876507395 +0000 -*************** -*** 71,76 **** ---- 71,87 ---- - } - - template -+ Hash IncrementalMerkleTree::last() const { -+ if (right) { -+ return *right; -+ } else if (left) { -+ return *left; -+ } else { -+ throw std::runtime_error("tree has no cursor"); -+ } -+ } -+ -+ template - void IncrementalMerkleTree::append(Hash obj) { - if (is_complete(Depth)) { - throw std::runtime_error("tree is full"); -diff -crB ./src/zcash/IncrementalMerkleTree.hpp ../../komodo-jl777/src/zcash/IncrementalMerkleTree.hpp -*** ./src/zcash/IncrementalMerkleTree.hpp 2017-01-03 10:40:50.435340501 +0000 ---- ../../komodo-jl777/src/zcash/IncrementalMerkleTree.hpp 2017-01-03 09:49:08.876507395 +0000 -*************** -*** 79,84 **** ---- 79,85 ---- - Hash root() const { - return root(Depth, std::deque()); - } -+ Hash last() const; - - IncrementalWitness witness() const { - return IncrementalWitness(*this); -*************** -*** 138,143 **** ---- 139,150 ---- - return tree.path(partial_path()); - } - -+ // Return the element being witnessed (should be a note -+ // commitment!) -+ Hash element() const { -+ return tree.last(); -+ } -+ - Hash root() const { - return tree.root(Depth, partial_path()); - } -diff -crB ./src/zcash/JoinSplit.cpp ../../komodo-jl777/src/zcash/JoinSplit.cpp -*** ./src/zcash/JoinSplit.cpp 2017-01-03 10:40:50.435340501 +0000 ---- ../../komodo-jl777/src/zcash/JoinSplit.cpp 2017-01-03 09:49:08.876507395 +0000 -*************** -*** 16,21 **** ---- 16,22 ---- - #include "libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.hpp" - - #include "sync.h" -+ #include "amount.h" - - using namespace libsnark; - -*************** -*** 24,30 **** - #include "zcash/circuit/gadget.tcc" - - CCriticalSection cs_ParamsIO; -! CCriticalSection cs_InitializeParams; - - template - void saveToFile(std::string path, T& obj) { ---- 25,31 ---- - #include "zcash/circuit/gadget.tcc" - - CCriticalSection cs_ParamsIO; -! CCriticalSection cs_LoadKeys; - - template - void saveToFile(std::string path, T& obj) { -*************** -*** 70,91 **** - - boost::optional> pk; - boost::optional> vk; - boost::optional pkPath; - - JoinSplitCircuit() {} - ~JoinSplitCircuit() {} - -- static void initialize() { -- LOCK(cs_InitializeParams); -- -- ppzksnark_ppT::init_public_params(); -- } -- - void setProvingKeyPath(std::string path) { - pkPath = path; - } - - void loadProvingKey() { - if (!pk) { - if (!pkPath) { - throw std::runtime_error("proving key path unknown"); ---- 71,89 ---- - - boost::optional> pk; - boost::optional> vk; -+ boost::optional> vk_precomp; - boost::optional pkPath; - - JoinSplitCircuit() {} - ~JoinSplitCircuit() {} - - void setProvingKeyPath(std::string path) { - pkPath = path; - } - - void loadProvingKey() { -+ LOCK(cs_LoadKeys); -+ - if (!pk) { - if (!pkPath) { - throw std::runtime_error("proving key path unknown"); -*************** -*** 102,108 **** ---- 100,113 ---- - } - } - void loadVerifyingKey(std::string path) { -+ LOCK(cs_LoadKeys); -+ - loadFromFile(path, vk); -+ -+ processVerifyingKey(); -+ } -+ void processVerifyingKey() { -+ vk_precomp = r1cs_ppzksnark_verifier_process_vk(*vk); - } - void saveVerifyingKey(std::string path) { - if (vk) { -*************** -*** 111,132 **** - throw std::runtime_error("cannot save verifying key; key doesn't exist"); - } - } - -! void generate() { - protoboard pb; - - joinsplit_gadget g(pb); - g.generate_r1cs_constraints(); - -! const r1cs_constraint_system constraint_system = pb.get_constraint_system(); - r1cs_ppzksnark_keypair keypair = r1cs_ppzksnark_generator(constraint_system); - - pk = keypair.pk; - vk = keypair.vk; - } - - bool verify( - const ZCProof& proof, - const uint256& pubKeyHash, - const uint256& randomSeed, - const boost::array& macs, ---- 116,150 ---- - throw std::runtime_error("cannot save verifying key; key doesn't exist"); - } - } -+ void saveR1CS(std::string path) { -+ auto r1cs = generate_r1cs(); - -! saveToFile(path, r1cs); -! } -! -! r1cs_constraint_system generate_r1cs() { - protoboard pb; - - joinsplit_gadget g(pb); - g.generate_r1cs_constraints(); - -! return pb.get_constraint_system(); -! } -! -! void generate() { -! LOCK(cs_LoadKeys); -! -! const r1cs_constraint_system constraint_system = generate_r1cs(); - r1cs_ppzksnark_keypair keypair = r1cs_ppzksnark_generator(constraint_system); - - pk = keypair.pk; - vk = keypair.vk; -+ processVerifyingKey(); - } - - bool verify( - const ZCProof& proof, -+ ProofVerifier& verifier, - const uint256& pubKeyHash, - const uint256& randomSeed, - const boost::array& macs, -*************** -*** 136,142 **** - uint64_t vpub_new, - const uint256& rt - ) { -! if (!vk) { - throw std::runtime_error("JoinSplit verifying key not loaded"); - } - ---- 154,160 ---- - uint64_t vpub_new, - const uint256& rt - ) { -! if (!vk || !vk_precomp) { - throw std::runtime_error("JoinSplit verifying key not loaded"); - } - -*************** -*** 155,161 **** - vpub_new - ); - -! return r1cs_ppzksnark_verifier_strong_IC(*vk, witness, r1cs_proof); - } catch (...) { - return false; - } ---- 173,184 ---- - vpub_new - ); - -! return verifier.check( -! *vk, -! *vk_precomp, -! witness, -! r1cs_proof -! ); - } catch (...) { - return false; - } -*************** -*** 181,188 **** - throw std::runtime_error("JoinSplit proving key not loaded"); - } - -! // Compute nullifiers of inputs - for (size_t i = 0; i < NumInputs; i++) { - out_nullifiers[i] = inputs[i].nullifier(); - } - ---- 204,254 ---- - throw std::runtime_error("JoinSplit proving key not loaded"); - } - -! if (vpub_old > MAX_MONEY) { -! throw std::invalid_argument("nonsensical vpub_old value"); -! } -! -! if (vpub_new > MAX_MONEY) { -! throw std::invalid_argument("nonsensical vpub_new value"); -! } -! -! uint64_t lhs_value = vpub_old; -! uint64_t rhs_value = vpub_new; -! - for (size_t i = 0; i < NumInputs; i++) { -+ // Sanity checks of input -+ { -+ // If note has nonzero value -+ if (inputs[i].note.value != 0) { -+ // The witness root must equal the input root. -+ if (inputs[i].witness.root() != rt) { -+ throw std::invalid_argument("joinsplit not anchored to the correct root"); -+ } -+ -+ // The tree must witness the correct element -+ if (inputs[i].note.cm() != inputs[i].witness.element()) { -+ throw std::invalid_argument("witness of wrong element for joinsplit input"); -+ } -+ } -+ -+ // Ensure we have the key to this note. -+ if (inputs[i].note.a_pk != inputs[i].key.address().a_pk) { -+ throw std::invalid_argument("input note not authorized to spend with given key"); -+ } -+ -+ // Balance must be sensical -+ if (inputs[i].note.value > MAX_MONEY) { -+ throw std::invalid_argument("nonsensical input note value"); -+ } -+ -+ lhs_value += inputs[i].note.value; -+ -+ if (lhs_value > MAX_MONEY) { -+ throw std::invalid_argument("nonsensical left hand size of joinsplit balance"); -+ } -+ } -+ -+ // Compute nullifier of input - out_nullifiers[i] = inputs[i].nullifier(); - } - -*************** -*** 197,208 **** ---- 263,291 ---- - - // Compute notes for outputs - for (size_t i = 0; i < NumOutputs; i++) { -+ // Sanity checks of output -+ { -+ if (outputs[i].value > MAX_MONEY) { -+ throw std::invalid_argument("nonsensical output value"); -+ } -+ -+ rhs_value += outputs[i].value; -+ -+ if (rhs_value > MAX_MONEY) { -+ throw std::invalid_argument("nonsensical right hand side of joinsplit balance"); -+ } -+ } -+ - // Sample r - uint256 r = random_uint256(); - - out_notes[i] = outputs[i].note(phi, r, i, h_sig); - } - -+ if (lhs_value != rhs_value) { -+ throw std::invalid_argument("invalid joinsplit balance"); -+ } -+ - // Compute the output commitments - for (size_t i = 0; i < NumOutputs; i++) { - out_commitments[i] = out_notes[i].cm(); -*************** -*** 249,257 **** - ); - } - -! if (!pb.is_satisfied()) { -! throw std::invalid_argument("Constraint system not satisfied by inputs"); -! } - - // TODO: These are copies, which is not strictly necessary. - std::vector primary_input = pb.primary_input(); ---- 331,339 ---- - ); - } - -! // The constraint system must be satisfied or there is an unimplemented -! // or incorrect sanity check above. Or the constraint system is broken! -! assert(pb.is_satisfied()); - - // TODO: These are copies, which is not strictly necessary. - std::vector primary_input = pb.primary_input(); -*************** -*** 275,281 **** - template - JoinSplit* JoinSplit::Generate() - { -! JoinSplitCircuit::initialize(); - auto js = new JoinSplitCircuit(); - js->generate(); - ---- 357,363 ---- - template - JoinSplit* JoinSplit::Generate() - { -! initialize_curve_params(); - auto js = new JoinSplitCircuit(); - js->generate(); - -*************** -*** 285,291 **** - template - JoinSplit* JoinSplit::Unopened() - { -! JoinSplitCircuit::initialize(); - return new JoinSplitCircuit(); - } - ---- 367,373 ---- - template - JoinSplit* JoinSplit::Unopened() - { -! initialize_curve_params(); - return new JoinSplitCircuit(); - } - -diff -crB ./src/zcash/JoinSplit.hpp ../../komodo-jl777/src/zcash/JoinSplit.hpp -*** ./src/zcash/JoinSplit.hpp 2017-01-03 10:40:50.435340501 +0000 ---- ../../komodo-jl777/src/zcash/JoinSplit.hpp 2017-01-03 09:49:08.876507395 +0000 -*************** -*** 62,67 **** ---- 62,68 ---- - virtual void saveProvingKey(std::string path) = 0; - virtual void loadVerifyingKey(std::string path) = 0; - virtual void saveVerifyingKey(std::string path) = 0; -+ virtual void saveR1CS(std::string path) = 0; - - virtual ZCProof prove( - const boost::array& inputs, -*************** -*** 82,87 **** ---- 83,89 ---- - - virtual bool verify( - const ZCProof& proof, -+ ProofVerifier& verifier, - const uint256& pubKeyHash, - const uint256& randomSeed, - const boost::array& hmacs, -diff -crB ./src/zcash/Proof.cpp ../../komodo-jl777/src/zcash/Proof.cpp -*** ./src/zcash/Proof.cpp 2017-01-03 10:40:50.435340501 +0000 ---- ../../komodo-jl777/src/zcash/Proof.cpp 2017-01-03 09:49:08.876507395 +0000 -*************** -*** 1,6 **** ---- 1,7 ---- - #include "Proof.hpp" - - #include -+ #include - - #include "crypto/common.h" - #include "libsnark/common/default_types/r1cs_ppzksnark_pp.hpp" -*************** -*** 211,214 **** ---- 212,247 ---- - return p; - } - -+ std::once_flag init_public_params_once_flag; -+ -+ void initialize_curve_params() -+ { -+ std::call_once (init_public_params_once_flag, curve_pp::init_public_params); -+ } -+ -+ ProofVerifier ProofVerifier::Strict() { -+ initialize_curve_params(); -+ return ProofVerifier(true); -+ } -+ -+ ProofVerifier ProofVerifier::Disabled() { -+ initialize_curve_params(); -+ return ProofVerifier(false); -+ } -+ -+ template<> -+ bool ProofVerifier::check( -+ const r1cs_ppzksnark_verification_key& vk, -+ const r1cs_ppzksnark_processed_verification_key& pvk, -+ const r1cs_primary_input& primary_input, -+ const r1cs_ppzksnark_proof& proof -+ ) -+ { -+ if (perform_verification) { -+ return r1cs_ppzksnark_online_verifier_strong_IC(pvk, primary_input, proof); -+ } else { -+ return true; -+ } -+ } -+ - } -diff -crB ./src/zcash/Proof.hpp ../../komodo-jl777/src/zcash/Proof.hpp -*** ./src/zcash/Proof.hpp 2017-01-03 10:40:50.435340501 +0000 ---- ../../komodo-jl777/src/zcash/Proof.hpp 2017-01-03 09:49:08.876507395 +0000 -*************** -*** 235,240 **** ---- 235,276 ---- - } - }; - -+ void initialize_curve_params(); -+ -+ class ProofVerifier { -+ private: -+ bool perform_verification; -+ -+ ProofVerifier(bool perform_verification) : perform_verification(perform_verification) { } -+ -+ public: -+ // ProofVerifier should never be copied -+ ProofVerifier(const ProofVerifier&) = delete; -+ ProofVerifier& operator=(const ProofVerifier&) = delete; -+ ProofVerifier(ProofVerifier&&); -+ ProofVerifier& operator=(ProofVerifier&&); -+ -+ // Creates a verification context that strictly verifies -+ // all proofs using libsnark's API. -+ static ProofVerifier Strict(); -+ -+ // Creates a verification context that performs no -+ // verification, used when avoiding duplicate effort -+ // such as during reindexing. -+ static ProofVerifier Disabled(); -+ -+ template -+ bool check( -+ const VerificationKey& vk, -+ const ProcessedVerificationKey& pvk, -+ const PrimaryInput& pi, -+ const Proof& p -+ ); -+ }; - - } - -diff -crB ./src/zcbenchmarks.cpp ../../komodo-jl777/src/zcbenchmarks.cpp -*** ./src/zcbenchmarks.cpp 2017-01-03 10:40:50.435340501 +0000 ---- ../../komodo-jl777/src/zcbenchmarks.cpp 2017-01-03 09:49:08.876507395 +0000 -*************** -*** 17,22 **** ---- 17,23 ---- - #include "script/sign.h" - #include "sodium.h" - #include "streams.h" -+ #include "utiltest.h" - #include "wallet/wallet.h" - - #include "zcbenchmarks.h" -*************** -*** 89,95 **** - 0); - double ret = timer_stop(tv_start); - -! assert(jsdesc.Verify(*pzcashParams, pubKeyHash)); - return ret; - } - ---- 90,97 ---- - 0); - double ret = timer_stop(tv_start); - -! auto verifier = libzcash::ProofVerifier::Strict(); -! assert(jsdesc.Verify(*pzcashParams, verifier, pubKeyHash)); - return ret; - } - -*************** -*** 98,104 **** - struct timeval tv_start; - timer_start(tv_start); - uint256 pubKeyHash; -! joinsplit.Verify(*pzcashParams, pubKeyHash); - return timer_stop(tv_start); - } - ---- 100,107 ---- - struct timeval tv_start; - timer_start(tv_start); - uint256 pubKeyHash; -! auto verifier = libzcash::ProofVerifier::Strict(); -! joinsplit.Verify(*pzcashParams, verifier, pubKeyHash); - return timer_stop(tv_start); - } - -*************** -*** 223,225 **** ---- 226,301 ---- - return timer_stop(tv_start); - } - -+ double benchmark_try_decrypt_notes(size_t nAddrs) -+ { -+ CWallet wallet; -+ for (int i = 0; i < nAddrs; i++) { -+ auto sk = libzcash::SpendingKey::random(); -+ wallet.AddSpendingKey(sk); -+ } -+ -+ auto sk = libzcash::SpendingKey::random(); -+ auto tx = GetValidReceive(*pzcashParams, sk, 10, true); -+ -+ struct timeval tv_start; -+ timer_start(tv_start); -+ auto nd = wallet.FindMyNotes(tx); -+ return timer_stop(tv_start); -+ } -+ -+ double benchmark_increment_note_witnesses(size_t nTxs) -+ { -+ CWallet wallet; -+ ZCIncrementalMerkleTree tree; -+ -+ auto sk = libzcash::SpendingKey::random(); -+ wallet.AddSpendingKey(sk); -+ -+ // First block -+ CBlock block1; -+ for (int i = 0; i < nTxs; i++) { -+ auto wtx = GetValidReceive(*pzcashParams, sk, 10, true); -+ auto note = GetNote(*pzcashParams, sk, wtx, 0, 1); -+ auto nullifier = note.nullifier(sk); -+ -+ mapNoteData_t noteData; -+ JSOutPoint jsoutpt {wtx.GetHash(), 0, 1}; -+ CNoteData nd {sk.address(), nullifier}; -+ noteData[jsoutpt] = nd; -+ -+ wtx.SetNoteData(noteData); -+ wallet.AddToWallet(wtx, true, NULL); -+ block1.vtx.push_back(wtx); -+ } -+ CBlockIndex index1(block1); -+ index1.nHeight = 1; -+ -+ // Increment to get transactions witnessed -+ wallet.ChainTip(&index1, &block1, tree, true); -+ -+ // Second block -+ CBlock block2; -+ block2.hashPrevBlock = block1.GetHash(); -+ { -+ auto wtx = GetValidReceive(*pzcashParams, sk, 10, true); -+ auto note = GetNote(*pzcashParams, sk, wtx, 0, 1); -+ auto nullifier = note.nullifier(sk); -+ -+ mapNoteData_t noteData; -+ JSOutPoint jsoutpt {wtx.GetHash(), 0, 1}; -+ CNoteData nd {sk.address(), nullifier}; -+ noteData[jsoutpt] = nd; -+ -+ wtx.SetNoteData(noteData); -+ wallet.AddToWallet(wtx, true, NULL); -+ block2.vtx.push_back(wtx); -+ } -+ CBlockIndex index2(block2); -+ index2.nHeight = 2; -+ -+ struct timeval tv_start; -+ timer_start(tv_start); -+ wallet.ChainTip(&index2, &block2, tree, true); -+ return timer_stop(tv_start); -+ } -+ -diff -crB ./src/zcbenchmarks.h ../../komodo-jl777/src/zcbenchmarks.h -*** ./src/zcbenchmarks.h 2017-01-03 10:40:50.435340501 +0000 ---- ../../komodo-jl777/src/zcbenchmarks.h 2017-01-03 09:49:08.876507395 +0000 -*************** -*** 12,16 **** ---- 12,18 ---- - extern double benchmark_verify_joinsplit(const JSDescription &joinsplit); - extern double benchmark_verify_equihash(); - extern double benchmark_large_tx(); -+ extern double benchmark_try_decrypt_notes(size_t nAddrs); -+ extern double benchmark_increment_note_witnesses(size_t nTxs); - - #endif -diff -crB ./zcutil/build-debian-package.sh ../../komodo-jl777/zcutil/build-debian-package.sh -*** ./zcutil/build-debian-package.sh 2017-01-03 10:40:50.435340501 +0000 ---- ../../komodo-jl777/zcutil/build-debian-package.sh 2017-01-03 09:49:08.876507395 +0000 -*************** -*** 23,32 **** - rm -R $BUILD_DIR - fi - - DEB_BIN=$BUILD_DIR/usr/bin - DEB_DOC=$BUILD_DIR/usr/share/doc/$PACKAGE_NAME - DEB_MAN=$BUILD_DIR/usr/share/man/man1 -! mkdir -p $BUILD_DIR/DEBIAN $DEB_BIN $DEB_DOC $DEB_MAN - chmod 0755 -R $BUILD_DIR/* - - # Copy control file ---- 23,33 ---- - rm -R $BUILD_DIR - fi - -+ DEB_CMP=$BUILD_DIR/etc/bash_completion.d - DEB_BIN=$BUILD_DIR/usr/bin - DEB_DOC=$BUILD_DIR/usr/share/doc/$PACKAGE_NAME - DEB_MAN=$BUILD_DIR/usr/share/man/man1 -! mkdir -p $BUILD_DIR/DEBIAN $DEB_CMP $DEB_BIN $DEB_DOC $DEB_MAN - chmod 0755 -R $BUILD_DIR/* - - # Copy control file -*************** -*** 48,53 **** ---- 49,57 ---- - # Copy manpages - cp $SRC_DEB/manpages/zcashd.1 $DEB_MAN - cp $SRC_DEB/manpages/zcash-cli.1 $DEB_MAN -+ # Copy bash completion files -+ cp $SRC_PATH/contrib/bitcoind.bash-completion $DEB_CMP/zcashd -+ cp $SRC_PATH/contrib/bitcoin-cli.bash-completion $DEB_CMP/zcash-cli - # Gzip files - gzip --best -n $DEB_DOC/changelog - gzip --best -n $DEB_DOC/changelog.Debian -diff -crB ./zcutil/build.sh ../../komodo-jl777/zcutil/build.sh -*** ./zcutil/build.sh 2017-01-03 10:40:50.435340501 +0000 ---- ../../komodo-jl777/zcutil/build.sh 2017-01-03 09:49:08.876507395 +0000 -*************** -*** 1,7 **** -! #!/bin/bash - - set -eu -o pipefail - - if [ "x$*" = 'x--help' ] - then - cat <().swap(vRandom); + nKey = GetRandHash(); + for (size_t bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) { + for (size_t entry = 0; entry < ADDRMAN_BUCKET_SIZE; entry++) { + vvNew[bucket][entry] = -1; + } + } + for (size_t bucket = 0; bucket < ADDRMAN_TRIED_BUCKET_COUNT; bucket++) { + for (size_t entry = 0; entry < ADDRMAN_BUCKET_SIZE; entry++) { + vvTried[bucket][entry] = -1; + } + } + + nIdCount = 0; + nTried = 0; + nNew = 0; + mapInfo.clear(); + mapAddr.clear(); + } + #ifdef DEBUG_ADDRMAN //! Perform consistency check. Returns an error code or zero. int Check_(); @@ -502,29 +529,12 @@ friend class CAddrManTest; void Clear() { LOCK(cs); - std::vector().swap(vRandom); - nKey = GetRandHash(); - for (size_t bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) { - for (size_t entry = 0; entry < ADDRMAN_BUCKET_SIZE; entry++) { - vvNew[bucket][entry] = -1; - } - } - for (size_t bucket = 0; bucket < ADDRMAN_TRIED_BUCKET_COUNT; bucket++) { - for (size_t entry = 0; entry < ADDRMAN_BUCKET_SIZE; entry++) { - vvTried[bucket][entry] = -1; - } - } - - nIdCount = 0; - nTried = 0; - nNew = 0; - mapInfo.clear(); - mapAddr.clear(); + Clear_(); } CAddrMan() { - Clear(); + Clear_(); } ~CAddrMan() diff --git a/src/alert.cpp b/src/alert.cpp index e76f6a41108..4991e36058e 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -261,8 +261,7 @@ bool CAlert::ProcessAlert(const std::vector& alertKey, bool fThre return true; } -void -CAlert::Notify(const std::string& strMessage, bool fThread) +void CAlert::Notify(const std::string& strMessage, bool fThread) { std::string strCmd = GetArg("-alertnotify", ""); if (strCmd.empty()) return; diff --git a/src/alert.h b/src/alert.h index 16204c9c533..51703aaba86 100644 --- a/src/alert.h +++ b/src/alert.h @@ -29,11 +29,6 @@ #include #include -class CAlert; -class CNode; -class uint256; - -extern std::map mapAlerts; extern CCriticalSection cs_mapAlerts; /** Alerts are for notifying old versions if they become too obsolete and @@ -86,6 +81,9 @@ class CUnsignedAlert std::string ToString() const; }; +class CNode; +class uint256; + /** An alert is a combination of a serialized CUnsignedAlert and a signature. */ class CAlert : public CUnsignedAlert { @@ -124,4 +122,6 @@ class CAlert : public CUnsignedAlert static CAlert getAlertByHash(const uint256 &hash); }; +extern std::map mapAlerts; + #endif // BITCOIN_ALERT_H diff --git a/src/alertkeys.h b/src/alertkeys.h index 106576add2a..82bdd680dfc 100644 --- a/src/alertkeys.h +++ b/src/alertkeys.h @@ -1,3 +1,4 @@ +#pragma once /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * @@ -13,13 +14,8 @@ * * ******************************************************************************/ -#ifndef BITCOIN_ALERTKEYS_H -#define BITCOIN_ALERTKEYS_H - // REMINDER: DO NOT COMMIT YOUR PRIVATE KEYS TO THE GIT REPOSITORY! const char* pszPrivKey = "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; const char* pszTestNetPrivKey = "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; -#endif - diff --git a/src/amount.h b/src/amount.h index be1c39a6ea3..18a31857bc1 100644 --- a/src/amount.h +++ b/src/amount.h @@ -21,10 +21,11 @@ #ifndef BITCOIN_AMOUNT_H #define BITCOIN_AMOUNT_H -#include "serialize.h" +#include "serialize.h" #include #include +#include typedef int64_t CAmount; @@ -32,17 +33,6 @@ static const CAmount COIN = 100000000; static const CAmount CENT = 1000000; extern const std::string CURRENCY_UNIT; - -/** No amount larger than this (in satoshi) is valid. - * - * Note that this constant is *not* the total money supply, which in Bitcoin - * currently happens to be less than 21,000,000 BTC for various reasons, but - * rather a sanity check. As this sanity check is used by consensus-critical - * validation code, the exact value of the MAX_MONEY constant is consensus - * critical; in unusual circumstances like a(nother) overflow bug that allowed - * for the creation of coins out of thin air modification could lead to a fork. - * */ -//static const CAmount MAX_MONEY = 21000000 * COIN; extern int64_t MAX_MONEY; inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } diff --git a/src/cc/CCPegs.h b/src/assetchain.h similarity index 52% rename from src/cc/CCPegs.h rename to src/assetchain.h index 78f1accac47..c6c4a94fb29 100644 --- a/src/cc/CCPegs.h +++ b/src/assetchain.h @@ -1,3 +1,4 @@ +#pragma once /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * @@ -12,25 +13,42 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ +#include +class assetchain +{ +public: + assetchain() : symbol_("") {} + assetchain(const std::string& symbol) : symbol_(symbol) + { + if (symbol_.size() > 64) + symbol_ = symbol_.substr(0, 64); + } + /***** + * @returns true if the chain is Komodo + */ + bool isKMD() { return symbol_.empty(); } + /**** + * @param in the symbol to compare + * @returns true if this chain's symbol matches + */ + bool isSymbol(const std::string& in) { return in == symbol_; } + /**** + * @returns this chain's symbol (will be empty for KMD) + */ + std::string symbol() { return symbol_; } + /**** + * @returns this chain's symbol, "KMD" in the case of Komodo + */ + std::string ToString() + { + if (symbol_.empty()) + return "KMD"; + return symbol_; + } + bool SymbolStartsWith(const std::string& in) { return symbol_.find(in) == 0; } +private: + std::string symbol_; +}; -#ifndef CC_PEGS_H -#define CC_PEGS_H - -#include "CCinclude.h" - -bool PegsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn); - -// CCcustom -UniValue PegsCreate(const CPubKey& pk,uint64_t txfee,int64_t amount,std::vector bindtxids); -UniValue PegsFund(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t amount); -UniValue PegsGet(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t amount); -UniValue PegsRedeem(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid); -UniValue PegsLiquidate(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid, uint256 liquidatetxid); -UniValue PegsExchange(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t amount); -UniValue PegsAccountHistory(const CPubKey& pk,uint256 pegstxid); -UniValue PegsAccountInfo(const CPubKey& pk,uint256 pegstxid); -UniValue PegsWorstAccounts(uint256 pegstxid); -UniValue PegsInfo(uint256 pegstxid); - -#endif +extern assetchain chainName; diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 544972586aa..8f613f92fa5 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -31,8 +31,10 @@ #include #include #include "support/events.h" +#include "assetchain.h" + uint16_t BITCOIND_RPCPORT = 7771; -char ASSETCHAINS_SYMBOL[65]; +assetchain chainName; #include @@ -95,10 +97,9 @@ static int AppInitRPC(int argc, char* argv[]) // Parameters // ParseParameters(argc, argv); - std:string name; - name = GetArg("-ac_name",""); + std::string name = GetArg("-ac_name",""); if ( !name.empty() ) - strncpy(ASSETCHAINS_SYMBOL,name.c_str(),sizeof(ASSETCHAINS_SYMBOL)-1); + chainName = assetchain(name); if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help") || mapArgs.count("-version")) { std::string strUsage = _("Komodo RPC client version") + " " + FormatFullVersion() + "\n" + PrivacyInfo(); diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 0e933f3cc6e..23b6ab6e1a7 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -27,6 +27,11 @@ #include "util.h" #include "httpserver.h" #include "httprpc.h" +#include "komodo.h" +#include "komodo_defs.h" +#include "komodo_gateway.h" +#include "komodo_bitcoind.h" +#include "komodo_gateway.h" #include #include @@ -56,19 +61,11 @@ */ static bool fDaemon; -#include "komodo_defs.h" -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -extern int32_t ASSETCHAINS_BLOCKTIME; -extern uint64_t ASSETCHAINS_CBOPRET; -void komodo_passport_iteration(); -uint64_t komodo_interestsum(); -int32_t komodo_longestchain(); -void komodo_cbopretupdate(int32_t forceflag); -CBlockIndex *komodo_chainactive(int32_t height); void WaitForShutdown(boost::thread_group* threadGroup) { - int32_t i,height; CBlockIndex *pindex; const uint256 zeroid; + int32_t i,height; CBlockIndex *pindex; + static const uint256 zeroid; //!< null uint256 constant bool fShutdown = ShutdownRequested(); // Tell the main threads to shutdown. if (komodo_currentheight()>KOMODO_EARLYTXID_HEIGHT && KOMODO_EARLYTXID!=zeroid && ((height=tx_height(KOMODO_EARLYTXID))==0 || height>KOMODO_EARLYTXID_HEIGHT)) @@ -76,18 +73,7 @@ void WaitForShutdown(boost::thread_group* threadGroup) fprintf(stderr,"error: earlytx must be before block height %d or tx does not exist\n",KOMODO_EARLYTXID_HEIGHT); StartShutdown(); } - /*if ( ASSETCHAINS_STAKED == 0 && ASSETCHAINS_ADAPTIVEPOW == 0 && (pindex= komodo_chainactive(1)) != 0 ) - { - if ( pindex->nTime > ADAPTIVEPOW_CHANGETO_DEFAULTON ) - { - ASSETCHAINS_ADAPTIVEPOW = 1; - fprintf(stderr,"default activate adaptivepow\n"); - } else fprintf(stderr,"height1 time %u vs %u\n",pindex->nTime,ADAPTIVEPOW_CHANGETO_DEFAULTON); - } //else fprintf(stderr,"cant find height 1\n");*/ - if ( ASSETCHAINS_CBOPRET != 0 ) - komodo_pricesinit(); /* - komodo_passport_iteration and komodo_cbopretupdate moved to a separate thread ThreadUpdateKomodoInternals fired every second (see init.cpp), original wait for shutdown loop restored. */ @@ -107,13 +93,6 @@ void WaitForShutdown(boost::thread_group* threadGroup) // // Start // -extern bool IS_KOMODO_NOTARY; -extern int32_t USE_EXTERNAL_PUBKEY; -extern uint32_t ASSETCHAIN_INIT; -extern std::string NOTARY_PUBKEY; -int32_t komodo_is_issuer(); -void komodo_passport_iteration(); - bool AppInit(int argc, char* argv[]) { boost::thread_group threadGroup; @@ -161,7 +140,7 @@ bool AppInit(int argc, char* argv[]) chainparams_commandline(); fprintf(stderr,"call komodo_args.(%s) NOTARY_PUBKEY.(%s)\n",argv[0],NOTARY_PUBKEY.c_str()); - printf("initialized %s at %u\n",ASSETCHAINS_SYMBOL,(uint32_t)time(NULL)); + printf("initialized %s at %u\n",chainName.symbol().c_str(),(uint32_t)time(NULL)); if (!boost::filesystem::is_directory(GetDataDir(false))) { fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str()); @@ -209,7 +188,7 @@ bool AppInit(int argc, char* argv[]) fDaemon = GetBoolArg("-daemon", false); if (fDaemon) { - fprintf(stdout, "Komodo %s server starting\n",ASSETCHAINS_SYMBOL); + fprintf(stdout, "Komodo %s server starting\n",chainName.symbol().c_str()); // Daemonize pid_t pid = fork(); diff --git a/src/cc/CC made easy.md b/src/cc/CC made easy.md index 2d10810039b..ff5886c84b6 100644 --- a/src/cc/CC made easy.md +++ b/src/cc/CC made easy.md @@ -98,8 +98,6 @@ EVAL(EVAL_LOTTO, 0xe9) \ EVAL(EVAL_HEIR, 0xea) \ EVAL(EVAL_CHANNELS, 0xeb) \ EVAL(EVAL_ORACLES, 0xec) \ -EVAL(EVAL_PRICES, 0xed) \ -EVAL(EVAL_PEGS, 0xee) \ EVAL(EVAL_TRIGGERS, 0xef) \ EVAL(EVAL_PAYMENTS, 0xf0) \ EVAL(EVAL_GATEWAYS, 0xf1) diff --git a/src/cc/CCGateways.h b/src/cc/CCGateways.h index 8793c0dc44a..a92a1bea516 100644 --- a/src/cc/CCGateways.h +++ b/src/cc/CCGateways.h @@ -37,4 +37,6 @@ UniValue GatewaysExternalAddress(uint256 bindtxid,CPubKey pubkey); UniValue GatewaysDumpPrivKey(uint256 bindtxid,CKey privkey); UniValue GatewaysList(); +uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,uint256 &tokenid,std::string &coin,int64_t &totalsupply,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector &gatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype); + #endif diff --git a/src/cc/CCImportGateway.h b/src/cc/CCImportGateway.h index 9be54f23a59..545d91480c8 100644 --- a/src/cc/CCImportGateway.h +++ b/src/cc/CCImportGateway.h @@ -34,4 +34,8 @@ UniValue ImportGatewayExternalAddress(uint256 bindtxid,CPubKey pubkey); UniValue ImportGatewayDumpPrivKey(uint256 bindtxid,CKey key); UniValue ImportGatewayList(); UniValue ImportGatewayInfo(uint256 bindtxid); -#endif \ No newline at end of file + +uint8_t DecodeImportGatewayBindOpRet(char *burnaddr,const CScript &scriptPubKey,std::string &coin,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector &importgatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype); +int64_t ImportGatewayVerify(char *refburnaddr,uint256 oracletxid,int32_t claimvout,std::string refcoin,uint256 burntxid,const std::string deposithex,std::vectorproof,uint256 merkleroot,CPubKey destpub,uint8_t taddr,uint8_t prefix,uint8_t prefix2); + +#endif diff --git a/src/cc/CCPayments.h b/src/cc/CCPayments.h index ac5f22c4795..fad55840e43 100644 --- a/src/cc/CCPayments.h +++ b/src/cc/CCPayments.h @@ -18,12 +18,11 @@ #define CC_PAYMENTS_H #include "CCinclude.h" -#include #include #define PAYMENTS_TXFEE 10000 #define PAYMENTS_MERGEOFSET 60 // 1H extra. -extern std::vector > vAddressSnapshot; +extern std::vector > vAddressSnapshot; // daily snapshot extern int32_t lastSnapShotHeight; bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn); diff --git a/src/cc/CCPrices.h b/src/cc/CCPrices.h deleted file mode 100644 index 554cf0ecade..00000000000 --- a/src/cc/CCPrices.h +++ /dev/null @@ -1,63 +0,0 @@ -/****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * - * * - * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * - * the top-level directory of this distribution for the individual copyright * - * holder information and the developer policies on copyright and licensing. * - * * - * Unless otherwise agreed in a custom licensing agreement, no part of the * - * SuperNET software, including this file may be copied, modified, propagated * - * or distributed except according to the terms contained in the LICENSE file * - * * - * Removal or modification of this copyright notice is prohibited. * - * * - ******************************************************************************/ - - -#ifndef CC_PRICES_H -#define CC_PRICES_H - -#include "komodo_defs.h" -#include "CCinclude.h" - -int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblocks); -extern void GetKomodoEarlytxidScriptPub(); -extern CScript KOMODO_EARLYTXID_SCRIPTPUB; - -// #define PRICES_DAYWINDOW ((3600*24/ASSETCHAINS_BLOCKTIME) + 1) // defined in komodo_defs.h -#define PRICES_TXFEE 10000 -#define PRICES_MAXLEVERAGE 777 -#define PRICES_SMOOTHWIDTH 1 -#define KOMODO_MAXPRICES 2048 // must be power of 2 and less than 8192 -#define KOMODO_PRICEMASK (~(KOMODO_MAXPRICES - 1)) // actually 1111 1000 0000 0000 -#define PRICES_WEIGHT (KOMODO_MAXPRICES * 1) // 0000 1000 0000 0000 -#define PRICES_MULT (KOMODO_MAXPRICES * 2) // 0001 0000 0000 0000 -#define PRICES_DIV (KOMODO_MAXPRICES * 3) // 0001 1000 0000 0000 -#define PRICES_INV (KOMODO_MAXPRICES * 4) // 0010 0000 0000 0000 -#define PRICES_MDD (KOMODO_MAXPRICES * 5) // 0010 1000 0000 0000 -#define PRICES_MMD (KOMODO_MAXPRICES * 6) // 0011 0000 0000 0000 -#define PRICES_MMM (KOMODO_MAXPRICES * 7) // 0011 1000 0000 0000 -#define PRICES_DDD (KOMODO_MAXPRICES * 8) // 0100 0000 0000 0000 - -//#define PRICES_NORMFACTOR (int64_t)(SATOSHIDEN) -//#define PRICES_POINTFACTOR (int64_t)10000 - -#define PRICES_REVSHAREDUST 10000 -#define PRICES_SUBREVSHAREFEE(amount) ((amount) * 199 / 200) // revshare fee percentage == 0.005 -#define PRICES_MINAVAILFUNDFRACTION 0.1 // leveraged bet limit < fund fraction - -bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn); - -// CCcustom -UniValue PricesBet(int64_t txfee,int64_t amount,int16_t leverage,std::vector synthetic); -UniValue PricesAddFunding(int64_t txfee,uint256 bettxid,int64_t amount); -UniValue PricesSetcostbasis(int64_t txfee,uint256 bettxid); -UniValue PricesRekt(int64_t txfee,uint256 bettxid,int32_t rektheight); -UniValue PricesCashout(int64_t txfee,uint256 bettxid); -UniValue PricesInfo(uint256 bettxid,int32_t refheight); -UniValue PricesList(uint32_t filter, CPubKey mypk); -UniValue PricesGetOrderbook(); -UniValue PricesRefillFund(int64_t amount); - - -#endif diff --git a/src/cc/CCassetstx.cpp b/src/cc/CCassetstx.cpp index 654f01a383f..95fc4c57c69 100644 --- a/src/cc/CCassetstx.cpp +++ b/src/cc/CCassetstx.cpp @@ -15,7 +15,7 @@ #include "CCassets.h" #include "CCtokens.h" - +#include "komodo_bitcoind.h" UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t additionalEvalCode) { diff --git a/src/cc/CCcustom.cpp b/src/cc/CCcustom.cpp index 1ae0241207b..a387914664c 100644 --- a/src/cc/CCcustom.cpp +++ b/src/cc/CCcustom.cpp @@ -25,8 +25,6 @@ #include "CCHeir.h" #include "CCchannels.h" #include "CCOracles.h" -#include "CCPrices.h" -#include "CCPegs.h" #include "CCPayments.h" #include "CCGateways.h" #include "CCtokens.h" @@ -166,28 +164,6 @@ uint8_t OraclesCCpriv[32] = { 0xf7, 0x4b, 0x5b, 0xa2, 0x7a, 0x5e, 0x9c, 0xda, 0x #undef FUNCNAME #undef EVALCODE -// Prices -#define FUNCNAME IsPricesInput -#define EVALCODE EVAL_PRICES -const char *PricesCCaddr = "RAL5Vh8NXmFqEKJRKrk1KjKaUckK7mM1iS"; -const char *PricesNormaladdr = "RBunXCsMHk5NPd6q8SQfmpgre3x133rSwZ"; -char PricesCChexstr[67] = { "039894cb054c0032e99e65e715b03799607aa91212a16648d391b6fa2cc52ed0cf" }; -uint8_t PricesCCpriv[32] = { 0x0a, 0x3b, 0xe7, 0x5d, 0xce, 0x06, 0xed, 0xb7, 0xc0, 0xb1, 0xbe, 0xe8, 0x7b, 0x5a, 0xd4, 0x99, 0xb8, 0x8d, 0xde, 0xac, 0xb2, 0x7e, 0x7a, 0x52, 0x96, 0x15, 0xd2, 0xa0, 0xc6, 0xb9, 0x89, 0x61 }; -#include "CCcustom.inc" -#undef FUNCNAME -#undef EVALCODE - -// Pegs -#define FUNCNAME IsPegsInput -#define EVALCODE EVAL_PEGS -const char *PegsCCaddr = "RHnkVb7vHuHnjEjhkCF1bS6xxLLNZPv5fd"; -const char *PegsNormaladdr = "RMcCZtX6dHf1fz3gpLQhUEMQ8cVZ6Rzaro"; -char PegsCChexstr[67] = { "03c75c1de29a35e41606363b430c08be1c2dd93cf7a468229a082cc79c7b77eece" }; -uint8_t PegsCCpriv[32] = { 0x52, 0x56, 0x4c, 0x78, 0x87, 0xf7, 0xa2, 0x39, 0xb0, 0x90, 0xb7, 0xb8, 0x62, 0x80, 0x0f, 0x83, 0x18, 0x9d, 0xf4, 0xf4, 0xbd, 0x28, 0x09, 0xa9, 0x9b, 0x85, 0x54, 0x16, 0x0f, 0x3f, 0xfb, 0x65 }; -#include "CCcustom.inc" -#undef FUNCNAME -#undef EVALCODE - // Payments #define FUNCNAME IsPaymentsInput #define EVALCODE EVAL_PAYMENTS @@ -374,22 +350,6 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) cp->validate = OraclesValidate; cp->ismyvin = IsOraclesInput; break; - case EVAL_PRICES: - strcpy(cp->unspendableCCaddr,PricesCCaddr); - strcpy(cp->normaladdr,PricesNormaladdr); - strcpy(cp->CChexstr,PricesCChexstr); - memcpy(cp->CCpriv,PricesCCpriv,32); - cp->validate = PricesValidate; - cp->ismyvin = IsPricesInput; - break; - case EVAL_PEGS: - strcpy(cp->unspendableCCaddr,PegsCCaddr); - strcpy(cp->normaladdr,PegsNormaladdr); - strcpy(cp->CChexstr,PegsCChexstr); - memcpy(cp->CCpriv,PegsCCpriv,32); - cp->validate = PegsValidate; - cp->ismyvin = IsPegsInput; - break; case EVAL_PAYMENTS: strcpy(cp->unspendableCCaddr,PaymentsCCaddr); strcpy(cp->normaladdr,PaymentsNormaladdr); diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 5f689f7a5f1..68be50dff66 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -81,9 +81,9 @@ Details. #define CC_MAXVINS 1024 #define CC_REQUIREMENTS_MSG (KOMODO_NSPV_SUPERLITE?"to use CC contracts you need to nspv_login first\n":"to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n") -#define SMALLVAL 0.000000000000001 -#define SATOSHIDEN ((uint64_t)100000000L) -#define dstr(x) ((double)(x) / SATOSHIDEN) +//#define SMALLVAL 0.000000000000001 +//#define SATOSHIDEN ((uint64_t)100000000L) +//#define dstr(x) ((double)(x) / SATOSHIDEN) #define CCDISABLEALL memset(ASSETCHAINS_CCDISABLES,1,sizeof(ASSETCHAINS_CCDISABLES)) #define CCENABLE(x) ASSETCHAINS_CCDISABLES[((uint8_t)x)] = 0 @@ -100,7 +100,6 @@ enum opretid : uint8_t { OPRETID_CHANNELSDATA = 0x14, //!< channels contract data id OPRETID_HEIRDATA = 0x15, //!< heir contract data id OPRETID_ROGUEGAMEDATA = 0x16, //!< rogue contract data id - OPRETID_PEGSDATA = 0x17, //!< pegs contract data id /*! \cond INTERNAL */ // non cc contract data: @@ -237,8 +236,6 @@ extern CWallet* pwalletMain; //!< global wallet object pointer to access wallet /// @private seems old-style bool GetAddressUnspent(uint160 addressHash, int type,std::vector > &unspentOutputs); -//CBlockIndex *komodo_getblockindex(uint256 hash); //moved to komodo_def.h -//int32_t komodo_nextheight(); //moved to komodo_def.h /// CCgetspenttxid finds the txid of the transaction which spends a transaction output. The function does this without loading transactions from the chain, by using spent index /// @param[out] spenttxid transaction id of the spending transaction @@ -254,11 +251,6 @@ void CCclearvars(struct CCcontract_info *cp); UniValue CClib(struct CCcontract_info *cp,char *method,char *jsonstr); UniValue CClib_info(struct CCcontract_info *cp); -//CBlockIndex *komodo_blockindex(uint256 hash); //moved to komodo_def.h -//CBlockIndex *komodo_chainactive(int32_t height); //moved to komodo_def.h -//int32_t komodo_blockheight(uint256 hash); //moved to komodo_def.h -//void StartShutdown(); - static const uint256 zeroid; //!< null uint256 constant /// \cond INTERNAL @@ -266,10 +258,13 @@ static uint256 ignoretxid; static int32_t ignorevin; /// \endcond -/// myGetTransaction is non-locking version of GetTransaction -/// @param hash hash of transaction to get (txid) -/// @param[out] txOut returned transaction object -/// @param[out] hashBlock hash of the block where the tx resides +/***** + * @brief get a transaction by its hash (without locks) + * @param[in] hash what to look for + * @param[out] txOut the found transaction + * @param[out] hashBlock the hash of the block (all zeros if still in mempool) + * @returns true if found + */ bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock); /// NSPV_myGetTransaction is called in NSPV mode @@ -290,7 +285,14 @@ int64_t CCgettxout(uint256 txid,int32_t vout,int32_t mempoolflag,int32_t lockfla /// \cond INTERNAL bool myIsutxo_spentinmempool(uint256 &spenttxid,int32_t &spentvini,uint256 txid,int32_t vout); -bool myAddtomempool(CTransaction &tx, CValidationState *pstate = NULL, bool fSkipExpiry = false); +/**** + * @brief add a transaction to the mempool + * @param[in] tx the transaction + * @param pstate where to store any error (can be nullptr) + * @param fSkipExpiry + * @returns true on success + */ +bool myAddtomempool(const CTransaction &tx, CValidationState *pstate = nullptr, bool fSkipExpiry = false); bool mytxid_inmempool(uint256 txid); int32_t myIsutxo_spent(uint256 &spenttxid,uint256 txid,int32_t vout); int32_t myGet_mempool_txs(std::vector &txs,uint8_t evalcode,uint8_t funcid); @@ -370,11 +372,8 @@ int64_t IsTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *c /// returns true if success bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx); -//void komodo_sendmessage(int32_t minpeers,int32_t maxpeers,const char *message,std::vector payload); // moved to komodo_defs.h - /// @private int32_t payments_parsehexdata(std::vector &hexdata,cJSON *item,int32_t len); -// int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex); // this def in komodo_defs.h /// Makes opreturn scriptPubKey for token creation transaction. Normally this function is called internally by the tokencreate rpc. You might need to call this function to create a customized token. /// The total opreturn length should not exceed 10001 byte @@ -691,7 +690,6 @@ uint64_t stringbits(char *str); uint256 revuint256(uint256 txid); char *uint256_str(char *dest,uint256 txid); char *pubkey33_str(char *dest,uint8_t *pubkey33); -//uint256 Parseuint256(const char *hexstr); // located in komodo_defs /// \endcond /// converts public key as array of uint8_t to normal address @@ -785,8 +783,6 @@ int32_t CCCointxidExists(char const *logcategory,uint256 cointxid); /// @private uint256 BitcoinGetProofMerkleRoot(const std::vector &proofData, std::vector &txids); -// bool komodo_txnotarizedconfirmed(uint256 txid); //moved to komodo_defs.h - /// @private CPubKey check_signing_pubkey(CScript scriptSig); @@ -990,6 +986,9 @@ UniValue report_ccerror(const char *category, int level, T print_to_stream) return err; } +bool komodo_txnotarizedconfirmed(uint256 txid); +uint32_t GetLatestTimestamp(int32_t height); + /// @private #define CCERR_RESULT(category,level,logoperator) return report_ccerror(category, level, [=](std::ostringstream &stream) {logoperator;}) #endif // #ifndef LOGSTREAM_DEFINED diff --git a/src/cc/CCrewards.h b/src/cc/CCrewards.h index d9f9edf6ec6..4d6cc80f938 100644 --- a/src/cc/CCrewards.h +++ b/src/cc/CCrewards.h @@ -18,7 +18,6 @@ #define CC_REWARDS_H #include "CCinclude.h" -#include #define EVAL_REWARDS 0xe5 #define REWARDSCC_MAXAPR (COIN * 25) diff --git a/src/cc/CCtokens.cpp b/src/cc/CCtokens.cpp index 054e45f9fe4..5f1095c3487 100644 --- a/src/cc/CCtokens.cpp +++ b/src/cc/CCtokens.cpp @@ -15,6 +15,7 @@ #include "CCtokens.h" #include "importcoin.h" +#include "komodo_bitcoind.h" /* TODO: correct this: ----------------------------- @@ -56,7 +57,7 @@ bool TokensValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction & char destaddr[64], origaddr[64], CCaddr[64]; std::vector voutTokenPubkeys, vinTokenPubkeys; - if (strcmp(ASSETCHAINS_SYMBOL, "ROGUE") == 0 && chainActive.Height() <= 12500) + if ( chainName.isSymbol("ROGUE") && chainActive.Height() <= 12500) return true; numvins = tx.vin.size(); @@ -401,15 +402,11 @@ int64_t IsTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true struct CCcontract_info *cpEvalCode1,CEvalCode1; cpEvalCode1 = CCinit(&CEvalCode1,evalCode1); CPubKey pk=GetUnspendable(cpEvalCode1,0); - testVouts.push_back( std::make_pair(MakeTokensCC1of2vout(evalCode1, tx.vout[v].nValue, voutPubkeys[0], pk), std::string("dual-eval1 pegscc cc1of2 pk[0] globalccpk")) ); - if (voutPubkeys.size() == 2) testVouts.push_back( std::make_pair(MakeTokensCC1of2vout(evalCode1, tx.vout[v].nValue, voutPubkeys[1], pk), std::string("dual-eval1 pegscc cc1of2 pk[1] globalccpk")) ); if (evalCode2!=0) { struct CCcontract_info *cpEvalCode2,CEvalCode2; cpEvalCode2 = CCinit(&CEvalCode2,evalCode2); CPubKey pk=GetUnspendable(cpEvalCode2,0); - testVouts.push_back( std::make_pair(MakeTokensCC1of2vout(evalCode2, tx.vout[v].nValue, voutPubkeys[0], pk), std::string("dual-eval2 pegscc cc1of2 pk[0] globalccpk")) ); - if (voutPubkeys.size() == 2) testVouts.push_back( std::make_pair(MakeTokensCC1of2vout(evalCode2, tx.vout[v].nValue, voutPubkeys[1], pk), std::string("dual-eval2 pegscc cc1of2 pk[1] globalccpk")) ); } // maybe it is single-eval or dual/three-eval token change? diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index e82f205ff79..2222786d7c6 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -19,16 +19,16 @@ #include "CCinclude.h" #include "komodo_structs.h" +#include "komodo_bitcoind.h" +#include "komodo_utils.h" #include "key_io.h" +#include "komodo_bitcoind.h" #ifdef TESTMODE #define MIN_NON_NOTARIZED_CONFIRMS 2 #else #define MIN_NON_NOTARIZED_CONFIRMS 101 #endif // TESTMODE -int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); -struct komodo_state *komodo_stateptr(char *symbol,char *dest); -extern uint32_t KOMODO_DPOWCONFS; void endiancpy(uint8_t *dest,uint8_t *src,int32_t len) { @@ -160,7 +160,7 @@ bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_ int64_t interest; uint64_t valuein; CCoinsViewMemPool viewMemPool(pcoinsTip, mempool); view.SetBackend(viewMemPool); - valuein = view.GetValueIn(height,&interest,tx,blocktime); + valuein = view.GetValueIn(height,interest,tx); actualtxfee = valuein-tx.GetValueOut(); if ( actualtxfee > txfee ) { @@ -174,7 +174,7 @@ uint32_t GetLatestTimestamp(int32_t height) { if ( KOMODO_NSPV_SUPERLITE ) return ((uint32_t)NSPV_blocktime(height)); return(komodo_heightstamp(height)); -} // :P +} void CCaddr2set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr) { @@ -382,7 +382,7 @@ bool ConstrainVout(CTxOut vout, int32_t CCflag, char *cmpaddr, int64_t nValue) } else if ( cmpaddr != 0 && (Getscriptaddress(destaddr, vout.scriptPubKey) == 0 || strcmp(destaddr, cmpaddr) != 0) ) { - fprintf(stderr,"constrain vout error: check addr %s vs script addr %s\n", cmpaddr!=0?cmpaddr:"", destaddr!=0?destaddr:""); + fprintf(stderr,"constrain vout error: check addr %s vs script addr %s\n", cmpaddr!=0?cmpaddr:"", destaddr); return(false); } else if ( nValue != 0 && nValue != vout.nValue ) //(nValue == 0 && vout.nValue < 10000) || ( @@ -434,7 +434,6 @@ bool priv2addr(char *coinaddr,uint8_t *buf33,uint8_t priv32[32]) std::vector Mypubkey() { - extern uint8_t NOTARY_PUBKEY33[33]; std::vector pubkey; int32_t i; uint8_t *dest,*pubkey33; pubkey33 = NOTARY_PUBKEY33; pubkey.resize(33); @@ -444,8 +443,6 @@ std::vector Mypubkey() return(pubkey); } -extern char NSPV_wifstr[],NSPV_pubkeystr[]; -extern uint32_t NSPV_logintime; #define NSPV_AUTOLOGOUT 777 bool Myprivkey(uint8_t myprivkey[]) @@ -453,16 +450,15 @@ bool Myprivkey(uint8_t myprivkey[]) char coinaddr[64],checkaddr[64]; std::string strAddress; char *dest; int32_t i,n; CBitcoinAddress address; CKeyID keyID; CKey vchSecret; uint8_t buf33[33]; if ( KOMODO_NSPV_SUPERLITE ) { + extern uint32_t NSPV_logintime; if ( NSPV_logintime == 0 || time(NULL) > NSPV_logintime+NSPV_AUTOLOGOUT ) { fprintf(stderr,"need to be logged in to get myprivkey\n"); return false; } + extern char *NSPV_wifstr; vchSecret = DecodeSecret(NSPV_wifstr); memcpy(myprivkey,vchSecret.begin(),32); - //for (i=0; i<32; i++) - // fprintf(stderr,"%02x",myprivkey[i]); - //fprintf(stderr," myprivkey %s\n",NSPV_wifstr); memset((uint8_t *)vchSecret.begin(),0,32); return true; } @@ -534,7 +530,7 @@ int64_t CCduration(int32_t &numblocks,uint256 txid) fprintf(stderr,"CCduration no txtime %u or txheight.%d %p for txid %s\n",txtime,txheight,pindex,uint256_str(str,txid)); return(0); } - else if ( (pindex= chainActive.LastTip()) == 0 || pindex->nTime < txtime || pindex->nHeight <= txheight ) + else if ( (pindex= chainActive.Tip()) == 0 || pindex->nTime < txtime || pindex->nHeight <= txheight ) { if ( pindex->nTime < txtime ) fprintf(stderr,"CCduration backwards timestamps %u %u for txid %s hts.(%d %d)\n",(uint32_t)pindex->nTime,txtime,uint256_str(str,txid),txheight,(int32_t)pindex->nHeight); @@ -672,7 +668,7 @@ int32_t komodo_get_current_height() { return (NSPV_inforesult.height); } - else return chainActive.LastTip()->nHeight; + else return chainActive.Tip()->nHeight; } bool komodo_txnotarizedconfirmed(uint256 txid) @@ -720,7 +716,7 @@ bool komodo_txnotarizedconfirmed(uint256 txid) fprintf(stderr,"komodo_txnotarizedconfirmed no txheight.%d %p for txid %s\n",txheight,pindex,txid.ToString().c_str()); return(0); } - else if ( (pindex= chainActive.LastTip()) == 0 || pindex->nHeight < txheight ) + else if ( (pindex= chainActive.Tip()) == 0 || pindex->nHeight < txheight ) { fprintf(stderr,"komodo_txnotarizedconfirmed backwards heights for txid %s hts.(%d %d)\n",txid.ToString().c_str(),txheight,(int32_t)pindex->nHeight); return(0); @@ -822,39 +818,27 @@ int64_t TotalPubkeyCCInputs(const CTransaction &tx, const CPubKey &pubkey) bool ProcessCC(struct CCcontract_info *cp,Eval* eval, std::vector paramsNull,const CTransaction &ctx, unsigned int nIn) { - CTransaction createTx; uint256 assetid,assetid2,hashBlock; uint8_t funcid; int32_t height,i,n,from_mempool = 0; int64_t amount; std::vector origpubkey; - height = KOMODO_CONNECTING; if ( KOMODO_CONNECTING < 0 ) // always comes back with > 0 for final confirmation - return(true); - if ( ASSETCHAINS_CC == 0 || (height & ~(1<<30)) < KOMODO_CCACTIVATE ) + return true; + + if ( ASSETCHAINS_CC == 0 || (KOMODO_CONNECTING & ~(1<<30)) < KOMODO_CCACTIVATE ) return eval->Invalid("CC are disabled or not active yet"); - if ( (KOMODO_CONNECTING & (1<<30)) != 0 ) - { - from_mempool = 1; - height &= ((1<<30) - 1); - } + if (cp->validate == NULL) return eval->Invalid("validation not supported for eval code"); - //fprintf(stderr,"KOMODO_CONNECTING.%d mempool.%d vs CCactive.%d\n",height,from_mempool,KOMODO_CCACTIVATE); - // there is a chance CC tx is valid in mempool, but invalid when in block, so we cant filter duplicate requests. if any of the vins are spent, for example - //txid = ctx.GetHash(); - //if ( txid == cp->prevtxid ) - // return(true); - //fprintf(stderr,"process CC %02x\n",cp->evalcode); + // there is a chance CC tx is valid in mempool, but invalid when in block, so we cant filter duplicate requests. + // if any of the vins are spent, for example + CCclearvars(cp); + if ( paramsNull.size() != 0 ) // Don't expect params return eval->Invalid("Cannot have params"); - //else if ( ctx.vout.size() == 0 ) // spend can go to z-addresses - // return eval->Invalid("no-vouts"); else if ( (*cp->validate)(cp,eval,ctx,nIn) != 0 ) { - //fprintf(stderr,"done CC %02x\n",cp->evalcode); - //cp->prevtxid = txid; - return(true); + return true; } - //fprintf(stderr,"invalid CC %02x\n",cp->evalcode); - return(false); + return false; } extern struct CCcontract_info CCinfos[0x100]; @@ -863,38 +847,41 @@ bool CClib_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const C bool CClib_Dispatch(const CC *cond,Eval *eval,std::vector paramsNull,const CTransaction &txTo,unsigned int nIn) { - uint8_t evalcode; int32_t height,from_mempool; struct CCcontract_info *cp; if ( ASSETCHAINS_CCLIB != MYCCLIBNAME ) { fprintf(stderr,"-ac_cclib=%s vs myname %s\n",ASSETCHAINS_CCLIB.c_str(),MYCCLIBNAME.c_str()); return eval->Invalid("-ac_cclib name mismatches myname"); } - height = KOMODO_CONNECTING; + if ( KOMODO_CONNECTING < 0 ) // always comes back with > 0 for final confirmation - return(true); + return true; + + // chain height calc and check + int32_t height = KOMODO_CONNECTING; if ( ASSETCHAINS_CC == 0 || (height & ~(1<<30)) < KOMODO_CCACTIVATE ) return eval->Invalid("CC are disabled or not active yet"); if ( (KOMODO_CONNECTING & (1<<30)) != 0 ) { - from_mempool = 1; height &= ((1<<30) - 1); } - evalcode = cond->code[0]; + + uint8_t evalcode = cond->code[0]; if ( evalcode >= EVAL_FIRSTUSER && evalcode <= EVAL_LASTUSER ) { - cp = &CCinfos[(int32_t)evalcode]; + CCcontract_info *cp = &CCinfos[(int32_t)evalcode]; if ( cp->didinit == 0 ) { if ( CClib_initcp(cp,evalcode) == 0 ) cp->didinit = 1; - else return eval->Invalid("unsupported CClib evalcode"); + else + return eval->Invalid("unsupported CClib evalcode"); } CCclearvars(cp); if ( paramsNull.size() != 0 ) // Don't expect params return eval->Invalid("Cannot have params"); else if ( CClib_validate(cp,height,eval,txTo,nIn) != 0 ) - return(true); - return(false); //eval->Invalid("error in CClib_validate"); + return true; + return false; //eval->Invalid("error in CClib_validate"); } return eval->Invalid("cclib CC must have evalcode between 16 and 127"); } diff --git a/src/cc/Makefile_custom b/src/cc/Makefile_custom index 79219ec96c1..364f9f4a121 100755 --- a/src/cc/Makefile_custom +++ b/src/cc/Makefile_custom @@ -10,9 +10,9 @@ RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program $(info $(OS)) OS := $(shell uname -s) $(info $(OS)) -TARGET = customcc.so -TARGET_DARWIN = customcc.dylib -TARGET_WIN = customcc.dll +TARGET = ../libcc.so +TARGET_DARWIN = ../libcc.dylib +TARGET_WIN = ../libcc.dll SOURCES = cclib.cpp #HEADERS = $(shell echo ../cryptoconditions/include/*.h) -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ @@ -22,16 +22,13 @@ $(TARGET): $(SOURCES) $(info Building cclib to src/) ifeq ($(OS),Darwin) $(CC_DARWIN) $(CFLAGS_DARWIN) $(DEBUGFLAGS) -o $(TARGET_DARWIN) -c $(SOURCES) - cp $(TARGET_DARWIN) ../libcc.dylib else ifeq ($(HOST),x86_64-w64-mingw32) $(info WINDOWS) $(CC_WIN) $(CFLAGS_WIN) $(DEBUGFLAGS) -o $(TARGET_WIN) -c $(SOURCES) - cp $(TARGET_WIN) ../libcc.dll #else ifeq ($(WIN_HOST),True) - todo: pass ENV var from build.sh if WIN host else $(info LINUX) $(CC) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) -c $(SOURCES) - cp $(TARGET) ../libcc.so endif clean: diff --git a/src/cc/assets.cpp b/src/cc/assets.cpp index 9ae4cc1eb40..6b98fa84522 100644 --- a/src/cc/assets.cpp +++ b/src/cc/assets.cpp @@ -148,17 +148,17 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti preventCCvins = preventCCvouts = -1; // add specific chains exceptions for old token support: - if (strcmp(ASSETCHAINS_SYMBOL, "SEC") == 0 && chainActive.Height() <= 144073) + if ( chainName.isSymbol("SEC") && chainActive.Height() <= 144073) return true; - if (strcmp(ASSETCHAINS_SYMBOL, "MGNX") == 0 && chainActive.Height() <= 210190) + if ( chainName.isSymbol("MGNX") && chainActive.Height() <= 210190) return true; // add specific chains exceptions for old token support: - if (strcmp(ASSETCHAINS_SYMBOL, "SEC") == 0 && chainActive.Height() <= 144073) + if ( chainName.isSymbol("SEC") && chainActive.Height() <= 144073) return true; - if (strcmp(ASSETCHAINS_SYMBOL, "MGNX") == 0 && chainActive.Height() <= 210190) + if ( chainName.isSymbol("MGNX") && chainActive.Height() <= 210190) return true; if (numvouts == 0) diff --git a/src/cc/auction.cpp b/src/cc/auction.cpp index 88d5134af53..21f3ce043fc 100644 --- a/src/cc/auction.cpp +++ b/src/cc/auction.cpp @@ -15,6 +15,7 @@ #include "CCauction.h" #include "../txmempool.h" +#include "komodo_bitcoind.h" /* */ diff --git a/src/cc/betprotocol.cpp b/src/cc/betprotocol.cpp index 1e0aa355e86..14d71d83f0f 100644 --- a/src/cc/betprotocol.cpp +++ b/src/cc/betprotocol.cpp @@ -24,8 +24,7 @@ #include "cc/eval.h" #include "cc/utils.h" #include "primitives/transaction.h" - -int32_t komodo_nextheight(); +#include "komodo_bitcoind.h" std::vector BetProtocol::PlayerConditions() { diff --git a/src/cc/cclib.cpp b/src/cc/cclib.cpp index f4a4db8444e..b69ef745524 100644 --- a/src/cc/cclib.cpp +++ b/src/cc/cclib.cpp @@ -27,6 +27,7 @@ #include "core_io.h" #include "crosschain.h" #include "hex.h" +#include "komodo_bitcoind.h" #define FAUCET2SIZE COIN #define EVAL_FAUCET2 EVAL_FIRSTUSER diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index 4d6299f4f6a..d9a31901111 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -14,6 +14,7 @@ ******************************************************************************/ #include "CCchannels.h" +#include "komodo_bitcoind.h" /* The idea here is to allow instant (mempool) payments that are secured by dPoW. In order to simplify things, channels CC will require creating reserves for each payee locked in the destination user's CC address. This will look like the payment is already made, but it is locked until further released. The dPoW protection comes from the cancel channel having a delayed effect until the next notarization. This way, if a payment release is made and the chain reorged, the same payment release will still be valid when it is re-broadcast into the mempool. diff --git a/src/cc/crypto777/OS_portable.h b/src/cc/crypto777/OS_portable.h index 4428876668a..8e21ec36428 100755 --- a/src/cc/crypto777/OS_portable.h +++ b/src/cc/crypto777/OS_portable.h @@ -115,10 +115,10 @@ int32_t hseek(HUFF *hp,int32_t offset,int32_t mode); #define GENESIS_PRIVKEYSTR "88a71671a6edd987ad9e9097428fc3f169decba3ac8f10da7b24e0ca16803b70" #define GENESIS_SECRET "It was a bright cold day in April, and the clocks were striking thirteen." -#define SATOSHIDEN ((uint64_t)100000000L) -#define dstr(x) ((double)(x) / SATOSHIDEN) +//#define SATOSHIDEN ((uint64_t)100000000L) +//#define dstr(x) ((double)(x) / SATOSHIDEN) -#define SMALLVAL 0.000000000000001 +//#define SMALLVAL 0.000000000000001 #define SETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] |= (1 << ((bitoffset) & 7))) #define GETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] & (1 << ((bitoffset) & 7))) @@ -130,20 +130,8 @@ int32_t hseek(HUFF *hp,int32_t offset,int32_t mode); #define portable_mutex_unlock pthread_mutex_unlock #define OS_thread_create pthread_create -#define issue_curl(cmdstr) bitcoind_RPC(0,"curl",cmdstr,0,0,0,0) #define issue_curlt(cmdstr,timeout) bitcoind_RPC(0,"curl",cmdstr,0,0,0,timeout) -struct allocitem { uint32_t allocsize,type; } PACKED; -struct queueitem { struct queueitem *next,*prev; uint32_t allocsize,type; } PACKED; -struct stritem { struct queueitem DL; void **retptrp; uint32_t expiration; char str[]; }; - -typedef struct queue -{ - struct queueitem *list; - portable_mutex_t mutex; - char name[64],initflag; -} queue_t; - struct rpcrequest_info { struct rpcrequest_info *next,*prev; @@ -270,13 +258,6 @@ void *myrealloc(uint8_t type,void *oldptr,long oldsize,long newsize); void *myaligned_alloc(uint64_t allocsize); int32_t myaligned_free(void *ptr,long size); -struct queueitem *queueitem(char *str); -void queue_enqueue(char *name,queue_t *queue,struct queueitem *origitem);//,int32_t offsetflag); -void *queue_dequeue(queue_t *queue);//,int32_t offsetflag); -void *queue_delete(queue_t *queue,struct queueitem *copy,int32_t copysize,int32_t freeitem); -void *queue_free(queue_t *queue); -void *queue_clone(queue_t *clone,queue_t *queue,int32_t size); -int32_t queue_size(queue_t *queue); char *mbstr(char *str,double n); void iguana_memreset(struct OS_memspace *mem); @@ -336,7 +317,6 @@ void calc_sha224(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); void calc_sha384(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); void calc_sha512(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); void calc_sha224(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); -void calc_rmd160(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); void calc_rmd128(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); void calc_rmd256(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); void calc_rmd320(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); diff --git a/src/cc/customcc.cpp b/src/cc/customcc.cpp index 669da14aeff..c8adbf9896e 100644 --- a/src/cc/customcc.cpp +++ b/src/cc/customcc.cpp @@ -9,6 +9,8 @@ The above will rebuild komodod and get it running again */ +#include "komodo_bitcoind.h" + CScript custom_opret(uint8_t funcid,CPubKey pk) { diff --git a/src/cc/dapps/dappstd.c b/src/cc/dapps/dappstd.c index c27f79d21b3..b46b19f8d24 100644 --- a/src/cc/dapps/dappstd.c +++ b/src/cc/dapps/dappstd.c @@ -38,7 +38,8 @@ char whoami[MAXSTR]; #define SATOSHIDEN ((uint64_t)100000000L) #define dstr(x) ((double)(x) / SATOSHIDEN) #define KOMODO_ASSETCHAIN_MAXLEN 65 -char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],IPADDRESS[100]; +char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; +char IPADDRESS[100]; #ifdef _WIN32 #ifdef _MSC_VER @@ -536,7 +537,7 @@ uint16_t _komodo_userpass(char *username, char *password, FILE *fp) return(port); } -uint16_t komodo_userpass(char *userpass,char *symbol) +uint16_t komodo_userpass(char *userpass,const char *symbol) { FILE *fp; uint16_t port = 0; char fname[512],username[512],password[512],confname[KOMODO_ASSETCHAIN_MAXLEN]; userpass[0] = 0; @@ -549,7 +550,6 @@ uint16_t komodo_userpass(char *userpass,char *symbol) #endif } else sprintf(confname,"%s.conf",symbol); - //komodo_statefname(fname,symbol,confname); if ( (fp= fopen(confname,"rb")) != 0 ) { port = _komodo_userpass(username,password,fp); @@ -573,9 +573,7 @@ char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port) { sprintf(url,(char *)"http://%s:%u",IPADDRESS,port); sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params); - //printf("[%s] (%s) postdata.(%s) params.(%s) USERPASS.(%s)\n",ASSETCHAINS_SYMBOL,url,postdata,params,USERPASS); retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,userpass,method,params); - //retstr = curl_post(&cHandle,url,USERPASS,postdata,0,0,0,0); } return(retstr2); } diff --git a/src/cc/dapps/oraclefeed.c b/src/cc/dapps/oraclefeed.c index dec5249af9d..89f590d9b8d 100644 --- a/src/cc/dapps/oraclefeed.c +++ b/src/cc/dapps/oraclefeed.c @@ -52,9 +52,6 @@ char *clonestr(char *str) if ( str == 0 || str[0]==0) { myprintf("warning cloning nullstr.%p\n",str); - //#ifdef __APPLE__ - // while ( 1 ) sleep(1); - //#endif str = (char *)""; } clone = (char *)malloc(strlen(str)+16); diff --git a/src/cc/dapps/zmigrate.c b/src/cc/dapps/zmigrate.c index 1f97ff88e94..1c6288487b7 100644 --- a/src/cc/dapps/zmigrate.c +++ b/src/cc/dapps/zmigrate.c @@ -56,9 +56,6 @@ char *clonestr(char *str) if ( str == 0 || str[0]==0) { printf("warning cloning nullstr.%p\n",str); - //#ifdef __APPLE__ - // while ( 1 ) sleep(1); - //#endif str = (char *)""; } clone = (char *)malloc(strlen(str)+16); diff --git a/src/cc/dice.cpp b/src/cc/dice.cpp index 4374d9663d6..9c5be8bf594 100644 --- a/src/cc/dice.cpp +++ b/src/cc/dice.cpp @@ -14,6 +14,7 @@ ******************************************************************************/ #include "hex.h" #include "CCdice.h" +#include "komodo_bitcoind.h" // timeout @@ -99,7 +100,6 @@ What is needed is for the dealer node to track the entropy tx that was already b #define MAX_ENTROPYUSED 8192 #define DICE_MINUTXOS 15000 -extern int32_t KOMODO_INSYNC; pthread_mutex_t DICE_MUTEX,DICEREVEALED_MUTEX; @@ -1729,7 +1729,7 @@ void *dealer0_loop(void *_arg) if ( num < DICE_MINUTXOS ) // this deadlocks, need to put it in a different thread { char *cmd = (char *)malloc(100 * 128); - sprintf(cmd,"./komodo-cli -ac_name=%s sendmany \"\" \"{\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002}\"",ASSETCHAINS_SYMBOL,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr); + sprintf(cmd,"./komodo-cli -ac_name=%s sendmany \"\" \"{\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002,\\\"%s\\\":0.0002}\"",chainName.symbol().c_str(),coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr,coinaddr); n = sqrt((DICE_MINUTXOS - num) / 100)*2 + 1; fprintf(stderr,"num normal 0.0002 utxos.%d < %d -> n.%d\n",num,DICE_MINUTXOS,n); for (i=0; i> (64-offset))) diff --git a/src/cc/eval.cpp b/src/cc/eval.cpp index 3a885378296..684038c7ac1 100644 --- a/src/cc/eval.cpp +++ b/src/cc/eval.cpp @@ -26,6 +26,9 @@ #include "chain.h" #include "core_io.h" #include "crosschain.h" +#include "komodo_structs.h" +#include "komodo_notary.h" +#include "komodo_globals.h" bool CClib_Dispatch(const CC *cond,Eval *eval,std::vector paramsNull,const CTransaction &txTo,unsigned int nIn); char *CClib_name(); @@ -160,9 +163,6 @@ bool Eval::GetBlock(uint256 hash, CBlockIndex& blockIdx) const return false; } -extern int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); - - int32_t Eval::GetNotaries(uint8_t pubkeys[64][33], int32_t height, uint32_t timestamp) const { return komodo_notaries(pubkeys, height, timestamp); @@ -176,7 +176,7 @@ bool Eval::CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t t auth.requiredSigs = 11; auth.size = GetNotaries(auth.notaries, height, timestamp); - return CheckTxAuthority(tx, auth); + return CrossChain::CheckTxAuthority(tx, auth); } /* @@ -201,7 +201,7 @@ uint32_t Eval::GetAssetchainsCC() const std::string Eval::GetAssetchainsSymbol() const { - return std::string(ASSETCHAINS_SYMBOL); + return chainName.symbol(); } diff --git a/src/cc/eval.h b/src/cc/eval.h index 2534338bad6..9583bc67ad7 100644 --- a/src/cc/eval.h +++ b/src/cc/eval.h @@ -51,8 +51,6 @@ EVAL(EVAL_HEIR, 0xea) \ EVAL(EVAL_CHANNELS, 0xeb) \ EVAL(EVAL_ORACLES, 0xec) \ - EVAL(EVAL_PRICES, 0xed) \ - EVAL(EVAL_PEGS, 0xee) \ EVAL(EVAL_PAYMENTS, 0xf0) \ EVAL(EVAL_GATEWAYS, 0xf1) \ EVAL(EVAL_TOKENS, 0xf2) \ @@ -152,8 +150,6 @@ class AppVM }; -extern char ASSETCHAINS_SYMBOL[65]; - /* * Data from notarisation OP_RETURN from chain being notarised @@ -219,7 +215,8 @@ class NotarisationData template bool DetectBackNotarisation(Stream& s, CSerActionUnserialize act) { - if (ASSETCHAINS_SYMBOL[0]) return 1; + if (!chainName.isKMD()) + return 1; if (s.size() >= 72) { if (strcmp("BTC", &s[68]) == 0) return 1; if (strcmp("KMD", &s[68]) == 0) return 1; diff --git a/src/cc/faucet.cpp b/src/cc/faucet.cpp index 74dfe43d966..7615c696344 100644 --- a/src/cc/faucet.cpp +++ b/src/cc/faucet.cpp @@ -15,6 +15,7 @@ #include "hex.h" #include "CCfaucet.h" #include "../txmempool.h" +#include "komodo_bitcoind.h" /* This file implements a simple CC faucet as an example of how to make a new CC contract. It wont have any fancy sybil protection but will serve the purpose of a fully automated faucet. diff --git a/src/cc/fsm.cpp b/src/cc/fsm.cpp index 58b2120cfbe..1aad4bbeda0 100644 --- a/src/cc/fsm.cpp +++ b/src/cc/fsm.cpp @@ -15,6 +15,7 @@ #include "CCfsm.h" #include "../txmempool.h" +#include "komodo_bitcoind.h" /* FSM CC is a highlevel CC contract that mostly uses other CC contracts. A finite state machine is defined, which combines triggers, payments and whatever other events/actions into a state machine diff --git a/src/cc/games/prices.c b/src/cc/games/prices.c index 1bc62533ee0..29c2ccdb402 100644 --- a/src/cc/games/prices.c +++ b/src/cc/games/prices.c @@ -175,9 +175,6 @@ char *clonestr(char *str) if ( str == 0 || str[0] == 0 ) { printf("warning cloning nullstr.%p\n",str); -#ifdef __APPLE__ - while ( 1 ) sleep(1); -#endif str = (char *)""; } len = strlen(str); diff --git a/src/cc/games/prices.cpp b/src/cc/games/prices.cpp index 5c8437e5d03..7e3e7168e0d 100644 --- a/src/cc/games/prices.cpp +++ b/src/cc/games/prices.cpp @@ -13,12 +13,13 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ +#include "komodo_bitcoind.h" +#include "cc/gamescc.h" std::string MYCCLIBNAME = (char *)"prices"; #define PRICES_BETPERIOD 3 UniValue games_rawtxresult(UniValue &result,std::string rawtx,int32_t broadcastflag); -extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33]; #define bstr(x) ((double)((uint32_t)x) / 10000.) diff --git a/src/cc/games/tetris.c b/src/cc/games/tetris.c index 8e7642837a2..d042e450dc6 100644 --- a/src/cc/games/tetris.c +++ b/src/cc/games/tetris.c @@ -791,9 +791,6 @@ char *clonestr(char *str) if ( str == 0 || str[0] == 0 ) { printf("warning cloning nullstr.%p\n",str); -#ifdef __APPLE__ - while ( 1 ) sleep(1); -#endif str = (char *)""; } len = strlen(str); diff --git a/src/cc/gamescc.cpp b/src/cc/gamescc.cpp index d8bd34bceba..a4f16714cd0 100644 --- a/src/cc/gamescc.cpp +++ b/src/cc/gamescc.cpp @@ -19,6 +19,8 @@ #else #include "games/tetris.c" #endif +#include "komodo_bitcoind.h" +#include "miner.h" // for komodo_sendmessage int32_t GAMEDATA(struct games_player *P,void *ptr); @@ -165,11 +167,7 @@ int32_t games_replay2(uint8_t *newdata,uint64_t seed,gamesevent *keystrokes,int3 } #ifndef STANDALONE -#ifdef BUILD_PRICES -#include "games/prices.cpp" -#else #include "games/tetris.cpp" -#endif void GAMEJSON(UniValue &obj,struct games_player *P); @@ -279,8 +277,9 @@ uint8_t games_registeropretdecode(uint256 &gametxid,uint256 &tokenid,uint256 &pl CScript games_finishopret(uint8_t funcid,uint256 gametxid,int32_t regslot,CPubKey pk,std::vectorplayerdata,std::string pname) { - CScript opret; uint8_t evalcode = EVAL_GAMES; std::string symbol(ASSETCHAINS_SYMBOL); - opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << gametxid << symbol << pname << regslot << pk << playerdata ); + CScript opret; + uint8_t evalcode = EVAL_GAMES; + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << gametxid << chainName.symbol() << pname << regslot << pk << playerdata ); return(opret); } @@ -871,7 +870,7 @@ uint64_t games_gamefields(UniValue &obj,int64_t maxplayers,int64_t buyin,uint256 obj.push_back(Pair("seed",(int64_t)seed)); if ( games_iamregistered(maxplayers,gametxid,tx,mygamesaddr) > 0 ) sprintf(cmd,"cc/%s %llu %s",GAMENAME,(long long)seed,gametxid.ToString().c_str()); - else sprintf(cmd,"./komodo-cli -ac_name=%s cclib register %d \"[%%22%s%%22]\"",ASSETCHAINS_SYMBOL,EVAL_GAMES,gametxid.ToString().c_str()); + else sprintf(cmd,"./komodo-cli -ac_name=%s cclib register %d \"[%%22%s%%22]\"",chainName.symbol().c_str(),EVAL_GAMES,gametxid.ToString().c_str()); obj.push_back(Pair("run",cmd)); } } diff --git a/src/cc/gamescc.h b/src/cc/gamescc.h index b804216d737..43413532311 100644 --- a/src/cc/gamescc.h +++ b/src/cc/gamescc.h @@ -68,6 +68,7 @@ UniValue games_extract(uint64_t txfee,struct CCcontract_info *cp,cJSON *params); UniValue games_register(uint64_t txfee,struct CCcontract_info *cp,cJSON *params); UniValue games_bet(uint64_t txfee,struct CCcontract_info *cp,cJSON *params); UniValue games_settle(uint64_t txfee,struct CCcontract_info *cp,cJSON *params); +UniValue games_rawtxresult(UniValue &result,std::string rawtx,int32_t broadcastflag); #define CUSTOM_DISPATCH \ if ( cp->evalcode == EVAL_GAMES ) \ diff --git a/src/cc/gateways.cpp b/src/cc/gateways.cpp index 515c0b3cb2e..4b8c5da2168 100644 --- a/src/cc/gateways.cpp +++ b/src/cc/gateways.cpp @@ -15,6 +15,7 @@ #include "CCGateways.h" #include "key_io.h" +#include "komodo_bitcoind.h" /* prevent duplicate bindtxid via mempool scan diff --git a/src/cc/heir.cpp b/src/cc/heir.cpp index 728d82f2697..aecc45a24d6 100644 --- a/src/cc/heir.cpp +++ b/src/cc/heir.cpp @@ -15,6 +15,8 @@ #include "CCHeir.h" #include "heir_validate.h" +#include "komodo_bitcoind.h" + #include class CoinHelper; @@ -335,7 +337,7 @@ uint8_t _DecodeHeirEitherOpRet(CScript scriptPubKey, uint256 &tokenid, CPubKey& /* if (vopretExtra.size() > 1) { // restore the second opret: - /* unmarshalled in DecodeTokenOpRet: + // unmarshalled in DecodeTokenOpRet: if (!E_UNMARSHAL(vopretExtra, { ss >> vopretStripped; })) { //strip string size if (!noLogging) std::cerr << "_DecodeHeirEitherOpret() could not unmarshal vopretStripped" << std::endl; return (uint8_t)0; diff --git a/src/cc/import.cpp b/src/cc/import.cpp index 4a1978e8d6a..13a2325dac3 100644 --- a/src/cc/import.cpp +++ b/src/cc/import.cpp @@ -12,7 +12,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - +#include "cc/import.h" #include "cc/eval.h" #include "cc/utils.h" #include "importcoin.h" @@ -21,6 +21,10 @@ #include "cc/CCinclude.h" #include #include "cc/CCtokens.h" +#include "cc/CCImportGateway.h" +#include "komodo_bitcoind.h" +#include "komodo_gateway.h" +#include "notaries_staked.h" #include "key_io.h" #define CODA_BURN_ADDRESS "KPrrRoPfHOnNpZZQ6laHXdQDkSQDkVHaN0V+LizLlHxz7NaA59sBAAAA" @@ -33,21 +37,67 @@ ##### 0xffffffff is a special CCid for single chain/dual daemon imports */ -extern std::string ASSETCHAINS_SELFIMPORT; +/*extern std::string ASSETCHAINS_SELFIMPORT; extern uint16_t ASSETCHAINS_CODAPORT,ASSETCHAINS_BEAMPORT; extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33]; extern uint256 KOMODO_EARLYTXID; // utilities from gateways.cpp uint256 BitcoinGetProofMerkleRoot(const std::vector &proofData, std::vector &txids); -uint256 GatewaysReverseScan(uint256 &txid, int32_t height, uint256 reforacletxid, uint256 batontxid); -int32_t GatewaysCointxidExists(struct CCcontract_info *cp, uint256 cointxid); uint8_t DecodeImportGatewayBindOpRet(char *burnaddr,const CScript &scriptPubKey,std::string &coin,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector &importgatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype); int64_t ImportGatewayVerify(char *refburnaddr,uint256 oracletxid,int32_t claimvout,std::string refcoin,uint256 burntxid,const std::string deposithex,std::vectorproof,uint256 merkleroot,CPubKey destpub,uint8_t taddr,uint8_t prefix,uint8_t prefix2); -char *nonportable_path(char *str); -char *portable_path(char *str); -void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep); -void *filestr(long *allocsizep,char *_fname); +*/ +/** + * @brief For Windows, convert / to \ in paths + * + * @param str the input + * @return the modified str + */ +std::string portable_path(std::string str) +{ +#ifdef _WIN32 + for(size_t i = 0; i < str.size(); ++i) + if ( str[i] == '/' ) + str[i] = '\\'; +#endif + return str; +} + + +/** + * @brief load a file into memory + * + * @param[out] allocsizep the memory buffer size + * @param _fname the file name + * @return the pointer to the allocated buffer + */ +void *filestr(long *allocsizep, std::string fname) +{ + FILE *fp = fopen( portable_path(fname).c_str(), "rb"); + if ( fp != nullptr ) + { + fseek(fp,0,SEEK_END); + size_t filesize = ftell(fp); + if ( filesize == 0 ) + { + fclose(fp); + *allocsizep = 0; + return nullptr; + } + uint8_t *buf = (uint8_t *)malloc(filesize); + rewind(fp); + if ( buf == 0 ) + printf("Null buf ???\n"); + else + { + if ( fread(buf,1,filesize,fp) != filesize ) + printf("error reading filesize.%ld\n",(long)filesize); + } + fclose(fp); + return buf; + } + return nullptr; +} cJSON* CodaRPC(char **retstr,char const *arg0,char const *arg1,char const *arg2,char const *arg3,char const *arg4,char const *arg5) { @@ -69,182 +119,82 @@ cJSON* CodaRPC(char **retstr,char const *arg0,char const *arg1,char const *arg2, return(retjson); } -// makes source tx for self import tx -CMutableTransaction MakeSelfImportSourceTx(CTxDestination &dest, int64_t amount) -{ - const int64_t txfee = 10000; - int64_t inputs, change; - CPubKey myPubKey = Mypubkey(); - struct CCcontract_info *cpDummy, C; - - cpDummy = CCinit(&C, EVAL_TOKENS); // this is just for FinalizeCCTx to work - - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - - if (AddNormalinputs(mtx, myPubKey, 2 * txfee, 4) == 0) { - LOGSTREAM("importcoin", CCLOG_INFO, stream << "MakeSelfImportSourceTx() warning: cannot find normal inputs for txfee" << std::endl); - } - - CScript scriptPubKey = GetScriptForDestination(dest); - mtx.vout.push_back(CTxOut(txfee, scriptPubKey)); - - //make opret with 'burned' amount: - FinalizeCCTx(0, cpDummy, mtx, myPubKey, txfee, CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_IMPORTCOIN << (uint8_t)'A' << amount)); - return mtx; -} - -// make sure vin is signed by pubkey33 -bool CheckVinPubKey(const CTransaction &sourcetx, int32_t i, uint8_t pubkey33[33]) -{ - CTransaction vintx; - uint256 blockHash; - char destaddr[64], pkaddr[64]; - - if (i < 0 || i >= sourcetx.vin.size()) - return false; - - if( !myGetTransaction(sourcetx.vin[i].prevout.hash, vintx, blockHash) ) { - LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckVinPubKey() could not load vintx" << sourcetx.vin[i].prevout.hash.GetHex() << std::endl); - return false; - } - if( sourcetx.vin[i].prevout.n < vintx.vout.size() && Getscriptaddress(destaddr, vintx.vout[sourcetx.vin[i].prevout.n].scriptPubKey) != 0 ) - { - pubkey2addr(pkaddr, pubkey33); - if (strcmp(pkaddr, destaddr) == 0) { - return true; - } - LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckVinPubKey() mismatched vin[" << i << "].prevout.n=" << sourcetx.vin[i].prevout.n << " -> destaddr=" << destaddr << " vs pkaddr=" << pkaddr << std::endl); - } - return false; -} - -// ac_import=PUBKEY support: -// prepare a tx for creating import tx and quasi-burn tx -int32_t GetSelfimportProof(const CMutableTransaction sourceMtx, CMutableTransaction &templateMtx, ImportProof &proofNull) // find burnTx with hash from "other" daemon -{ - MerkleBranch newBranch; - CMutableTransaction tmpmtx; - //CTransaction sourcetx; - - tmpmtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - - /* - if (!E_UNMARSHAL(ParseHex(rawsourcetx), ss >> sourcetx)) { - LOGSTREAM("importcoin", CCLOG_INFO, stream << "GetSelfimportProof: could not unmarshal source tx" << std::endl); - return(-1); - } - - if (sourcetx.vout.size() == 0) { - LOGSTREAM("importcoin", CCLOG_INFO, stream << "GetSelfimportProof: vout size is 0" << std::endl); - return -1; - } */ - - /*if (ivout < 0) { // "ivout < 0" means "find" - // try to find vout - CPubKey myPubkey = Mypubkey(); - ivout = 0; - // skip change: - if (sourcetx.vout[ivout].scriptPubKey == (CScript() << ParseHex(HexStr(myPubkey)) << OP_CHECKSIG)) - ivout++; - } - - if (ivout >= sourcetx.vout.size()) { - LOGSTREAM("importcoin", CCLOG_INFO, stream << "GetSelfimportProof: needed vout not found" << std::endl); - return -1; - } */ - - int32_t ivout = 0; - - // LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "GetSelfimportProof: using vout[" << ivout << "] of the passed rawtx" << std::endl); - - CScript scriptPubKey = sourceMtx.vout[ivout].scriptPubKey; - - //mtx is template for import tx - templateMtx = sourceMtx; - templateMtx.fOverwintered = tmpmtx.fOverwintered; - - //malleability fix for burn tx: - //mtx.nExpiryHeight = tmpmtx.nExpiryHeight; - templateMtx.nExpiryHeight = sourceMtx.nExpiryHeight; - - templateMtx.nVersionGroupId = tmpmtx.nVersionGroupId; - templateMtx.nVersion = tmpmtx.nVersion; - templateMtx.vout.clear(); - templateMtx.vout.resize(1); - - uint8_t evalCode, funcId; - int64_t burnAmount; - vscript_t vopret; - if( !GetOpReturnData(sourceMtx.vout.back().scriptPubKey, vopret) || - !E_UNMARSHAL(vopret, ss >> evalCode; ss >> funcId; ss >> burnAmount)) { - LOGSTREAM("importcoin", CCLOG_INFO, stream << "GetSelfimportProof() could not unmarshal source tx opret" << std::endl); - return -1; - } - templateMtx.vout[0].nValue = burnAmount; - templateMtx.vout[0].scriptPubKey = scriptPubKey; - - // not sure we need this now as we create sourcetx ourselves: - /*if (sourcetx.GetHash() != sourcetxid) { - LOGSTREAM("importcoin", CCLOG_INFO, stream << "GetSelfimportProof: passed source txid incorrect" << std::endl); - return(-1); - }*/ - - // check ac_pubkey: - if (!CheckVinPubKey(sourceMtx, 0, ASSETCHAINS_OVERRIDE_PUBKEY33)) { - return -1; - } - proofNull = ImportProof(std::make_pair(sourceMtx.GetHash(), newBranch)); - return 0; -} - -// make import tx with burntx and dual daemon -std::string MakeCodaImportTx(uint64_t txfee, std::string receipt, std::string srcaddr, std::vector vouts) +/**** + * @brief make import tx with burntx and dual daemon + * @param txfee fee + * @param receipt + * @param srcaddr source address + * @param vouts collection of vouts + * @returns the hex string of the import transaction + */ +std::string MakeCodaImportTx(uint64_t txfee, const std::string& receipt, const std::string& srcaddr, + const std::vector& vouts) { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()),burntx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk; uint256 codaburntxid; std::vector dummyproof; - int32_t i,numvouts,n,m; std::string coin,error; struct CCcontract_info *cp, C; - cJSON *result,*tmp,*tmp1; unsigned char hash[SHA256_DIGEST_LENGTH+1]; - char out[SHA256_DIGEST_LENGTH*2+1],*retstr,*destaddr,*receiver; TxProof txProof; uint64_t amount; + CMutableTransaction mtx = CreateNewContextualCMutableTransaction( + Params().GetConsensus(), komodo_nextheight()); + CMutableTransaction burntx = CreateNewContextualCMutableTransaction( + Params().GetConsensus(), komodo_nextheight()); + CCcontract_info *cp; + CCcontract_info C; cp = CCinit(&C, EVAL_GATEWAYS); + if (txfee == 0) txfee = 10000; - mypk = pubkey2pk(Mypubkey()); + CPubKey mypk = pubkey2pk(Mypubkey()); + SHA256_CTX sha256; SHA256_Init(&sha256); SHA256_Update(&sha256, receipt.c_str(), receipt.size()); + unsigned char hash[SHA256_DIGEST_LENGTH+1]; SHA256_Final(hash, &sha256); - for(i = 0; i < SHA256_DIGEST_LENGTH; i++) + char out[SHA256_DIGEST_LENGTH*2+1]; + for(int32_t i = 0; i < SHA256_DIGEST_LENGTH; i++) { sprintf(out + (i * 2), "%02x", hash[i]); } - out[65]='\0'; + out[SHA256_DIGEST_LENGTH*2]='\0'; LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeCodaImportTx: hash=" << out << std::endl); + uint256 codaburntxid; codaburntxid.SetHex(out); - LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeCodaImportTx: receipt=" << receipt << " codaburntxid=" << codaburntxid.GetHex().data() << " amount=" << (double)amount / COIN << std::endl); - result=CodaRPC(&retstr,"prove-payment","-address",srcaddr.c_str(),"-receipt-chain-hash",receipt.c_str(),""); - if (result==0) + LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeCodaImportTx: receipt=" + << receipt << " codaburntxid=" << codaburntxid.GetHex().data() + << std::endl); + + char *retstr; + cJSON *result = CodaRPC(&retstr,"prove-payment","-address",srcaddr.c_str(), + "-receipt-chain-hash",receipt.c_str(),""); + if (result == nullptr) { - if (retstr!=0) + if (retstr != nullptr) { - CCerror=std::string("CodaRPC: ")+retstr; + CCerror = std::string("CodaRPC: ") + retstr; free(retstr); } - return(""); + return ""; } else { - if ((tmp=jobj(jitem(jarray(&n,result,(char *)"payments"),0),(char *)"payload"))!=0 && (destaddr=jstr(jobj(tmp,(char *)"common"),(char *)"memo"))!=0 && - (receiver=jstr(jitem(jarray(&m,tmp,(char *)"body"),1),(char *)"receiver"))!=0 && (amount=j64bits(jitem(jarray(&m,tmp,(char *)"body"),1),(char *)"amount"))!=0) + int32_t n; + int32_t m; + cJSON *tmp = jobj(jitem(jarray(&n,result,(char *)"payments"),0),(char *)"payload"); + char *destaddr; + char *receiver; + uint64_t amount; + if ( tmp != nullptr + && (destaddr=jstr(jobj(tmp,(char *)"common"),(char *)"memo")) != nullptr + && (receiver=jstr(jitem(jarray(&m,tmp,(char *)"body"),1),(char *)"receiver")) != nullptr + && (amount=j64bits(jitem(jarray(&m,tmp,(char *)"body"),1),(char *)"amount")) != 0 ) { - LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeCodaImportTx: receiver=" << receiver << " destaddr=" << destaddr << " amount=" << amount << std::endl); + LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "MakeCodaImportTx: receiver=" + << receiver << " destaddr=" << destaddr << " amount=" << amount << std::endl); if (strcmp(receiver,CODA_BURN_ADDRESS)!=0) { CCerror="MakeCodaImportTx: invalid burn address, coins do not go to predefined burn address - "; CCerror+=CODA_BURN_ADDRESS; LOGSTREAM("importcoin", CCLOG_INFO, stream << CCerror << std::endl); free(result); - return(""); + return ""; } CTxDestination dest = DecodeDestination(destaddr); CScript scriptPubKey = GetScriptForDestination(dest); @@ -253,17 +203,20 @@ std::string MakeCodaImportTx(uint64_t txfee, std::string receipt, std::string sr CCerror="MakeCodaImportTx: invalid destination address, burnTx memo!=importTx destination"; LOGSTREAM("importcoin", CCLOG_INFO, stream << CCerror << std::endl); free(result); - return(""); + return ""; } if (amount*COIN!=vouts[0].nValue) { CCerror="MakeCodaImportTx: invalid amount, burnTx amount!=importTx amount"; LOGSTREAM("importcoin", CCLOG_INFO, stream << CCerror << std::endl); free(result); - return(""); + return ""; } burntx.vin.push_back(CTxIn(codaburntxid,0,CScript())); + std::vector dummyproof; burntx.vout.push_back(MakeBurnOutput(amount*COIN,0xffffffff,"CODA",vouts,dummyproof,srcaddr,receipt)); + + TxProof txProof; return HexStr(E_MARSHAL(ss << MakeImportCoinTransaction(txProof,burntx,vouts))); } else @@ -271,7 +224,7 @@ std::string MakeCodaImportTx(uint64_t txfee, std::string receipt, std::string sr CCerror="MakeCodaImportTx: invalid Coda burn tx"; LOGSTREAM("importcoin", CCLOG_INFO, stream << CCerror << std::endl); free(result); - return(""); + return ""; } } @@ -291,8 +244,10 @@ int32_t CheckBEAMimport(TxProof proof,std::vector rawproof,CTransaction int32_t CheckCODAimport(CTransaction importTx,CTransaction burnTx,std::vector payouts,std::string srcaddr,std::string receipt) { - cJSON *result,*tmp,*tmp1; char *retstr,out[SHA256_DIGEST_LENGTH*2+1]; unsigned char hash[SHA256_DIGEST_LENGTH+1]; int i,n,m; - SHA256_CTX sha256; uint256 codaburntxid; char *destaddr,*receiver; uint64_t amount; + cJSON *result,*tmp,*tmp1; char *retstr,out[SHA256_DIGEST_LENGTH*2+1]; int i,n,m; + uint256 codaburntxid; char *destaddr,*receiver; uint64_t amount; + unsigned char hash[SHA256_DIGEST_LENGTH+1]; + SHA256_CTX sha256; // check with dual-CODA daemon via ASSETCHAINS_CODAPORT for validity of burnTx SHA256_Init(&sha256); @@ -322,7 +277,7 @@ int32_t CheckCODAimport(CTransaction importTx,CTransaction burnTx,std::vectorInvalid("no-tokens-migrate-on-LABS"); struct CCcontract_info *cpTokens, CCtokens_info; std::vector> oprets; @@ -620,11 +575,9 @@ bool CheckMigration(Eval *eval, const CTransaction &importTx, const CTransaction return eval->Invalid("import-tx-token-params-incorrect"); } - // Check burntx shows correct outputs hash -// if (payoutsHash != SerializeHash(payouts)) // done in ImportCoin -// return eval->Invalid("wrong-payouts"); - + // if (payoutsHash != SerializeHash(payouts)) // done in ImportCoin + // return eval->Invalid("wrong-payouts"); TxProof merkleBranchProof; std::vector notaryTxids; @@ -633,13 +586,13 @@ bool CheckMigration(Eval *eval, const CTransaction &importTx, const CTransaction if (proof.IsMerkleBranch(merkleBranchProof)) { uint256 target = merkleBranchProof.second.Exec(burnTx.GetHash()); LOGSTREAM("importcoin", CCLOG_DEBUG2, stream << "Eval::ImportCoin() momom target=" << target.GetHex() << " merkleBranchProof.first=" << merkleBranchProof.first.GetHex() << std::endl); - if (!CheckMoMoM(merkleBranchProof.first, target)) { + if (!CrossChain::CheckMoMoM(merkleBranchProof.first, target)) { LOGSTREAM("importcoin", CCLOG_INFO, stream << "MoMoM check failed for importtx=" << importTx.GetHash().GetHex() << std::endl); return eval->Invalid("momom-check-fail"); } } else if (proof.IsNotaryTxids(notaryTxids)) { - if (!CheckNotariesApproval(burnTx.GetHash(), notaryTxids)) { + if (!CrossChain::CheckNotariesApproval(burnTx.GetHash(), notaryTxids)) { return eval->Invalid("notaries-approval-check-fail"); } } @@ -671,9 +624,6 @@ bool Eval::ImportCoin(const std::vector params, const CTransaction &imp LOGSTREAM("importcoin", CCLOG_DEBUG1, stream << "Validating import tx..., txid=" << importTx.GetHash().GetHex() << std::endl); - if (strcmp(ASSETCHAINS_SYMBOL, "CFEKDIMXY6") == 0 && chainActive.Height() <= 44693) - return true; - if (importTx.vout.size() < 2) return Invalid("too-few-vouts"); // params @@ -681,7 +631,7 @@ bool Eval::ImportCoin(const std::vector params, const CTransaction &imp return Invalid("invalid-params"); // Control all aspects of this transaction // It should not be at all malleable - if (ASSETCHAINS_SELFIMPORT!="PEGSCC" && MakeImportCoinTransaction(proof, burnTx, payouts, importTx.nExpiryHeight).GetHash() != importTx.GetHash()) // ExistsImportTombstone prevents from duplication + if (MakeImportCoinTransaction(proof, burnTx, payouts, importTx.nExpiryHeight).GetHash() != importTx.GetHash()) // ExistsImportTombstone prevents from duplication return Invalid("non-canonical"); // burn params if (!UnmarshalBurnTx(burnTx, targetSymbol, &targetCcid, payoutsHash, rawproof)) @@ -706,7 +656,9 @@ bool Eval::ImportCoin(const std::vector params, const CTransaction &imp return Invalid("wrong-payouts"); if (targetCcid < KOMODO_FIRSTFUNGIBLEID) return Invalid("chain-not-fungible"); - + if (targetSymbol.empty()) + return Invalid("target-chain-not-specified"); + if ( targetCcid != 0xffffffff ) { @@ -736,13 +688,6 @@ bool Eval::ImportCoin(const std::vector params, const CTransaction &imp else if ( UnmarshalBurnTx(burnTx,srcaddr,receipt)==0 || CheckCODAimport(importTx,burnTx,payouts,srcaddr,receipt) < 0 ) return Invalid("CODA-import-failure"); } - else if ( targetSymbol == "PEGSCC" ) - { - if ( ASSETCHAINS_SELFIMPORT != "PEGSCC" ) - return Invalid("PEGSCC-import-when-not PEGSCC"); - // else if ( CheckPUBKEYimport(merkleBranchProof,rawproof,burnTx,payouts) < 0 ) - // return Invalid("PEGSCC-import-failure"); - } else if ( targetSymbol == "PUBKEY" ) { if ( ASSETCHAINS_SELFIMPORT != "PUBKEY" ) @@ -764,3 +709,116 @@ bool Eval::ImportCoin(const std::vector params, const CTransaction &imp return Valid(); } + +/***** + * @brief makes source tx for self import tx + * @param dest the tx destination + * @param amount the amount + * @returns a transaction based on the inputs + */ +CMutableTransaction MakeSelfImportSourceTx(const CTxDestination &dest, int64_t amount) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + + const int64_t txfee = 10000; + CPubKey myPubKey = Mypubkey(); + if (AddNormalinputs(mtx, myPubKey, 2 * txfee, 4) == 0) { + LOGSTREAM("importcoin", CCLOG_INFO, stream + << "MakeSelfImportSourceTx() warning: cannot find normal inputs for txfee" << std::endl); + } + + CScript scriptPubKey = GetScriptForDestination(dest); + mtx.vout.push_back(CTxOut(txfee, scriptPubKey)); + + //make opret with 'burned' amount: + CCcontract_info *cpDummy; + CCcontract_info C; + cpDummy = CCinit(&C, EVAL_TOKENS); // this is just for FinalizeCCTx to work + FinalizeCCTx(0, cpDummy, mtx, myPubKey, txfee, CScript() + << OP_RETURN + << E_MARSHAL(ss << (uint8_t)EVAL_IMPORTCOIN << (uint8_t)'A' << amount)); + return mtx; +} + +/****** + * @brief make sure vin is signed by a particular key + * @param sourcetx the source transaction + * @param i the index of the input to check + * @param pubkey33 the key + * @returns true if the vin of i was signed by the given key + */ +bool CheckVinPubKey(const CTransaction &sourcetx, int32_t i, uint8_t pubkey33[33]) +{ + CTransaction vintx; + uint256 blockHash; + char destaddr[64], pkaddr[64]; + + if (i < 0 || i >= sourcetx.vin.size()) + return false; + + if( !myGetTransaction(sourcetx.vin[i].prevout.hash, vintx, blockHash) ) { + LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckVinPubKey() could not load vintx" << sourcetx.vin[i].prevout.hash.GetHex() << std::endl); + return false; + } + if( sourcetx.vin[i].prevout.n < vintx.vout.size() && Getscriptaddress(destaddr, vintx.vout[sourcetx.vin[i].prevout.n].scriptPubKey) != 0 ) + { + pubkey2addr(pkaddr, pubkey33); + if (strcmp(pkaddr, destaddr) == 0) { + return true; + } + LOGSTREAM("importcoin", CCLOG_INFO, stream << "CheckVinPubKey() mismatched vin[" << i << "].prevout.n=" << sourcetx.vin[i].prevout.n << " -> destaddr=" << destaddr << " vs pkaddr=" << pkaddr << std::endl); + } + return false; +} + +/***** + * @brief generate a self import proof + * @note this prepares a tx for creating an import tx and quasi-burn tx + * @note find burnTx with hash from "other" daemon + * @param[in] sourceMtx the original transaction + * @param[out] templateMtx the resultant transaction + * @param[out] proofNull the import proof + * @returns true on success + */ +bool GetSelfimportProof(const CMutableTransaction sourceMtx, CMutableTransaction &templateMtx, + ImportProof &proofNull) +{ + + CMutableTransaction tmpmtx = CreateNewContextualCMutableTransaction( + Params().GetConsensus(), komodo_nextheight()); + + CScript scriptPubKey = sourceMtx.vout[0].scriptPubKey; + + //mtx is template for import tx + templateMtx = sourceMtx; + templateMtx.fOverwintered = tmpmtx.fOverwintered; + + //malleability fix for burn tx: + //mtx.nExpiryHeight = tmpmtx.nExpiryHeight; + templateMtx.nExpiryHeight = sourceMtx.nExpiryHeight; + + templateMtx.nVersionGroupId = tmpmtx.nVersionGroupId; + templateMtx.nVersion = tmpmtx.nVersion; + templateMtx.vout.clear(); + templateMtx.vout.resize(1); + + uint8_t evalCode, funcId; + int64_t burnAmount; + vscript_t vopret; + if( !GetOpReturnData(sourceMtx.vout.back().scriptPubKey, vopret) || + !E_UNMARSHAL(vopret, ss >> evalCode; ss >> funcId; ss >> burnAmount)) { + LOGSTREAM("importcoin", CCLOG_INFO, stream << "GetSelfimportProof() could not unmarshal source tx opret" << std::endl); + return false; + } + templateMtx.vout[0].nValue = burnAmount; + templateMtx.vout[0].scriptPubKey = scriptPubKey; + + // check ac_pubkey: + if (!CheckVinPubKey(sourceMtx, 0, ASSETCHAINS_OVERRIDE_PUBKEY33)) { + return false; + } + + MerkleBranch newBranch; + proofNull = ImportProof(std::make_pair(sourceMtx.GetHash(), newBranch)); + return true; +} diff --git a/src/cc/import.h b/src/cc/import.h new file mode 100644 index 00000000000..29ed9de5487 --- /dev/null +++ b/src/cc/import.h @@ -0,0 +1,59 @@ +#pragma once +/****************************************************************************** + * Copyright © 2021 Komodo Core developers * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + +#include "primitives/transaction.h" // CTransaction +#include "script/standard.h" // CTxDestination +#include "importcoin.h" // ImportProof +#include + +/**** + * @brief make import tx with burntx and dual daemon + * @param txfee fee + * @param receipt + * @param srcaddr source address + * @param vouts collection of vouts + * @returns the hex string of the import transaction + */ +std::string MakeCodaImportTx(uint64_t txfee, const std::string& receipt, + const std::string& srcaddr, const std::vector& vouts); + +/****** + * @brief make sure vin is signed by a particular key + * @param sourcetx the source transaction + * @param i the index of the input to check + * @param pubkey33 the key + * @returns true if the vin of i was signed by the given key + */ +bool CheckVinPubKey(const CTransaction &sourcetx, int32_t i, uint8_t pubkey33[33]); + +/***** + * @brief makes source tx for self import tx + * @param dest the tx destination + * @param amount the amount + * @returns a transaction based on the inputs + */ +CMutableTransaction MakeSelfImportSourceTx(const CTxDestination &dest, int64_t amount); + +/***** + * @brief generate a self import proof + * @note this prepares a tx for creating an import tx and quasi-burn tx + * @note find burnTx with hash from "other" daemon + * @param[in] sourceMtx the original transaction + * @param[out] templateMtx the resultant transaction + * @param[out] proofNull the import proof + * @returns true on success + */ +bool GetSelfimportProof(const CMutableTransaction sourceMtx, CMutableTransaction &templateMtx, ImportProof &proofNull); diff --git a/src/cc/importgateway.cpp b/src/cc/importgateway.cpp index 16b54d2b634..4f271333121 100644 --- a/src/cc/importgateway.cpp +++ b/src/cc/importgateway.cpp @@ -16,6 +16,7 @@ #include "CCImportGateway.h" #include "key_io.h" #include "../importcoin.h" +#include "komodo_bitcoind.h" // start of consensus code @@ -25,8 +26,6 @@ #define KMD_TADDR 0 #define CC_MARKER_VALUE 10000 -extern uint256 KOMODO_EARLYTXID; - CScript EncodeImportGatewayBindOpRet(uint8_t funcid,std::string coin,uint256 oracletxid,uint8_t M,uint8_t N,std::vector importgatewaypubkeys,uint8_t taddr,uint8_t prefix,uint8_t prefix2,uint8_t wiftype) { CScript opret; uint8_t evalcode = EVAL_IMPORTGATEWAY; diff --git a/src/cc/includes/cJSON.h b/src/cc/includes/cJSON.h index d919a47a9f2..a95880253aa 100755 --- a/src/cc/includes/cJSON.h +++ b/src/cc/includes/cJSON.h @@ -48,8 +48,11 @@ #include "../crypto777/OS_portable.h" -#define SATOSHIDEN ((uint64_t)100000000L) -#define dstr(x) ((double)(x) / SATOSHIDEN) + +// todo remove +//#define SATOSHIDEN ((uint64_t)100000000L) +//#define dstr(x) ((double)(x) / SATOSHIDEN) + #define MAX_JSON_FIELD 4096 // on the big side #ifdef __cplusplus diff --git a/src/cc/lotto.cpp b/src/cc/lotto.cpp index db441444564..8eec713806a 100644 --- a/src/cc/lotto.cpp +++ b/src/cc/lotto.cpp @@ -15,6 +15,7 @@ #include "CClotto.h" #include "../txmempool.h" +#include "komodo_bitcoind.h" /* A blockchain lotto has the problem of generating the deterministic random numbers needed to get a winner in a way that doesnt allow cheating. If we save the entropy for later publishing and display the hash of the entropy, it is true that the players wont know what the entropy value is, however the creator of the lotto funds will be able to know and simply create a winning ticket when the jackpot is large enough. diff --git a/src/cc/marmara.cpp b/src/cc/marmara.cpp deleted file mode 100644 index 65f4107a51a..00000000000 --- a/src/cc/marmara.cpp +++ /dev/null @@ -1,1104 +0,0 @@ -/****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * - * * - * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * - * the top-level directory of this distribution for the individual copyright * - * holder information and the developer policies on copyright and licensing. * - * * - * Unless otherwise agreed in a custom licensing agreement, no part of the * - * SuperNET software, including this file may be copied, modified, propagated * - * or distributed except according to the terms contained in the LICENSE file * - * * - * Removal or modification of this copyright notice is prohibited. * - * * - ******************************************************************************/ -#include "hex.h" -#include "CCMarmara.h" - -/* - Marmara CC is for the MARMARA project - - 'R': two forms for initial issuance and for accepting existing - vins normal - vout0 approval to senderpk (issuer or owner of baton) - - 'I' - vin0 approval from 'R' - vins1+ normal - vout0 baton to 1st receiverpk - vout1 marker to Marmara so all issuances can be tracked (spent when loop is closed) - - 'T' - vin0 approval from 'R' - vin1 baton from 'I'/'T' - vins2+ normal - vout0 baton to next receiverpk (following the unspent baton back to original is the credit loop) - - 'S' - vin0 'I' marker - vin1 baton - vins CC utxos from credit loop - - 'D' default/partial payment - - 'L' lockfunds - -*/ - -// start of consensus code - -int64_t IsMarmaravout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) -{ - char destaddr[64]; - if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) - { - if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 ) - return(tx.vout[v].nValue); - } - return(0); -} - -int32_t MarmaraRandomize(uint32_t ind) -{ - uint64_t val64; uint32_t val,range = (MARMARA_MAXLOCK - MARMARA_MINLOCK); - val64 = komodo_block_prg(ind); - val = (uint32_t)(val64 >> 32); - val ^= (uint32_t)val64; - return((val % range) + MARMARA_MINLOCK); -} - -int32_t MarmaraUnlockht(int32_t height) -{ - uint32_t ind = height / MARMARA_GROUPSIZE; - height = (height / MARMARA_GROUPSIZE) * MARMARA_GROUPSIZE; - return(height + MarmaraRandomize(ind)); -} - -uint8_t DecodeMaramaraCoinbaseOpRet(const CScript scriptPubKey,CPubKey &pk,int32_t &height,int32_t &unlockht) -{ - std::vector vopret; uint8_t *script,e,f,funcid; - GetOpReturnData(scriptPubKey,vopret); - script = (uint8_t *)vopret.data(); - if ( 0 ) - { - int32_t i; - for (i=0; i 2 && script[0] == EVAL_MARMARA ) - { - if ( script[1] == 'C' || script[1] == 'P' || script[1] == 'L' ) - { - if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> pk; ss >> height; ss >> unlockht) != 0 ) - { - return(script[1]); - } else fprintf(stderr,"DecodeMaramaraCoinbaseOpRet unmarshal error for %c\n",script[1]); - } //else fprintf(stderr,"script[1] is %d != 'C' %d or 'P' %d or 'L' %d\n",script[1],'C','P','L'); - } else fprintf(stderr,"vopret.size() is %d\n",(int32_t)vopret.size()); - return(0); -} - -CScript EncodeMarmaraCoinbaseOpRet(uint8_t funcid,CPubKey pk,int32_t ht) -{ - CScript opret; int32_t unlockht; uint8_t evalcode = EVAL_MARMARA; - unlockht = MarmaraUnlockht(ht); - opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << pk << ht << unlockht); - if ( 0 ) - { - std::vector vopret; uint8_t *script,i; - GetOpReturnData(opret,vopret); - script = (uint8_t *)vopret.data(); - { - for (i=0; i vopret; uint8_t *script,e,f; - GetOpReturnData(scriptPubKey, vopret); - script = (uint8_t *)vopret.data(); - if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> createtxid; ss >> senderpk; ss >> amount; ss >> matures; ss >> currency) != 0 ) - { - return(f); - } - return(0); -} - -int32_t MarmaraGetcreatetxid(uint256 &createtxid,uint256 txid) -{ - CTransaction tx; uint256 hashBlock; uint8_t funcid; int32_t numvouts,matures; std::string currency; CPubKey senderpk; int64_t amount; - if ( myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 1 ) - { - if ( (funcid= MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,createtxid,senderpk,amount,matures,currency)) == 'I' || funcid == 'T' ) - return(0); - else if ( funcid == 'R' ) - { - if ( createtxid == zeroid ) - createtxid = txid; - return(0); - } - } - return(-1); -} - -int32_t MarmaraGetbatontxid(std::vector &creditloop,uint256 &batontxid,uint256 txid) -{ - uint256 createtxid,spenttxid; int64_t value; int32_t vini,height,n=0,vout = 0; - memset(&batontxid,0,sizeof(batontxid)); - if ( MarmaraGetcreatetxid(createtxid,txid) == 0 ) - { - txid = createtxid; - //fprintf(stderr,"txid.%s -> createtxid %s\n",txid.GetHex().c_str(),createtxid.GetHex().c_str()); - while ( CCgetspenttxid(spenttxid,vini,height,txid,vout) == 0 ) - { - creditloop.push_back(txid); - //fprintf(stderr,"%d: %s\n",n,txid.GetHex().c_str()); - n++; - if ( (value= CCgettxout(spenttxid,vout,1,1)) == 10000 ) - { - batontxid = spenttxid; - //fprintf(stderr,"got baton %s %.8f\n",batontxid.GetHex().c_str(),(double)value/COIN); - return(n); - } - else if ( value > 0 ) - { - batontxid = spenttxid; - fprintf(stderr,"n.%d got false baton %s/v%d %.8f\n",n,batontxid.GetHex().c_str(),vout,(double)value/COIN); - return(n); - } - // get funcid - txid = spenttxid; - } - } - return(-1); -} - -CScript Marmara_scriptPubKey(int32_t height,CPubKey pk) -{ - CTxOut ccvout; struct CCcontract_info *cp,C; CPubKey Marmarapk; - cp = CCinit(&C,EVAL_MARMARA); - Marmarapk = GetUnspendable(cp,0); - if ( height > 0 && (height & 1) == 0 && pk.size() == 33 ) - { - ccvout = MakeCC1of2vout(EVAL_MARMARA,0,Marmarapk,pk); - //char coinaddr[64]; - //Getscriptaddress(coinaddr,ccvout.scriptPubKey); - //fprintf(stderr,"Marmara_scriptPubKey %s ht.%d -> %s\n",HexStr(pk).c_str(),height,coinaddr); - } - return(ccvout.scriptPubKey); -} - -CScript MarmaraCoinbaseOpret(uint8_t funcid,int32_t height,CPubKey pk) -{ - uint8_t *ptr; - //fprintf(stderr,"height.%d pksize.%d\n",height,(int32_t)pk.size()); - if ( height > 0 && (height & 1) == 0 && pk.size() == 33 ) - return(EncodeMarmaraCoinbaseOpRet(funcid,pk,height)); - return(CScript()); -} - -int32_t MarmaraValidateCoinbase(int32_t height,CTransaction tx) -{ - struct CCcontract_info *cp,C; CPubKey Marmarapk,pk; int32_t ht,unlockht; CTxOut ccvout; - cp = CCinit(&C,EVAL_MARMARA); - Marmarapk = GetUnspendable(cp,0); - if ( 0 ) - { - int32_t d,histo[365*2+30]; - memset(histo,0,sizeof(histo)); - for (ht=2; ht<100; ht++) - fprintf(stderr,"%d ",MarmaraUnlockht(ht)); - fprintf(stderr," <- first 100 unlock heights\n"); - for (ht=2; ht<1000000; ht+=MARMARA_GROUPSIZE) - { - d = (MarmaraUnlockht(ht) - ht) / 1440; - if ( d < 0 || d > sizeof(histo)/sizeof(*histo) ) - fprintf(stderr,"d error.%d at ht.%d\n",d,ht); - else histo[d]++; - } - for (ht=0; ht unlock.%d\n",ht,unlockht); - ccvout = MakeCC1of2vout(EVAL_MARMARA,0,Marmarapk,pk); - if ( ccvout.scriptPubKey == tx.vout[0].scriptPubKey ) - return(0); - char addr0[64],addr1[64]; - Getscriptaddress(addr0,ccvout.scriptPubKey); - Getscriptaddress(addr1,tx.vout[0].scriptPubKey); - fprintf(stderr,"ht.%d mismatched CCvout scriptPubKey %s vs %s pk.%d %s\n",height,addr0,addr1,(int32_t)pk.size(),HexStr(pk).c_str()); - } else fprintf(stderr,"ht.%d %d vs %d unlock.%d\n",height,MarmaraUnlockht(height),ht,unlockht); - } else fprintf(stderr,"ht.%d error decoding coinbase opret\n",height); - } - return(-1); -} - -bool MarmaraPoScheck(char *destaddr,CScript opret,CTransaction staketx) -{ - CPubKey Marmarapk,pk; int32_t height,unlockht; uint8_t funcid; char coinaddr[64]; struct CCcontract_info *cp,C; - //fprintf(stderr,"%s numvins.%d numvouts.%d %.8f opret[%d]\n",staketx.GetHash().ToString().c_str(),(int32_t)staketx.vin.size(),(int32_t)staketx.vout.size(),(double)staketx.vout[0].nValue/COIN,(int32_t)opret.size()); - if ( staketx.vout.size() == 2 && opret == staketx.vout[1].scriptPubKey ) - { - cp = CCinit(&C,EVAL_MARMARA); - funcid = DecodeMaramaraCoinbaseOpRet(opret,pk,height,unlockht); - Marmarapk = GetUnspendable(cp,0); - GetCCaddress1of2(cp,coinaddr,Marmarapk,pk); - //fprintf(stderr,"matched opret! funcid.%c ht.%d unlock.%d %s\n",funcid,height,unlockht,coinaddr); - return(strcmp(destaddr,coinaddr) == 0); - } - return(0); -} - -bool MarmaraValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) -{ - std::vector vopret; CTransaction vinTx; uint256 hashBlock; int32_t numvins,numvouts,i,ht,unlockht,vht,vunlockht; uint8_t funcid,vfuncid,*script; CPubKey pk,vpk; - if ( ASSETCHAINS_MARMARA == 0 ) - return eval->Invalid("-ac_marmara must be set for marmara CC"); - numvins = tx.vin.size(); - numvouts = tx.vout.size(); - if ( numvouts < 1 ) - return eval->Invalid("no vouts"); - else if ( tx.vout.size() >= 2 ) - { - GetOpReturnData(tx.vout[tx.vout.size()-1].scriptPubKey,vopret); - script = (uint8_t *)vopret.data(); - if ( vopret.size() < 2 || script[0] != EVAL_MARMARA ) - return eval->Invalid("no opreturn"); - funcid = script[1]; - if ( funcid == 'P' ) - { - funcid = DecodeMaramaraCoinbaseOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,pk,ht,unlockht); - for (i=0; iismyvin)(tx.vin[i].scriptSig) != 0 ) - { - if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 ) - return eval->Invalid("cant find vinTx"); - else - { - if ( vinTx.IsCoinBase() == 0 ) - return eval->Invalid("noncoinbase input"); - else if ( vinTx.vout.size() != 2 ) - return eval->Invalid("coinbase doesnt have 2 vouts"); - vfuncid = DecodeMaramaraCoinbaseOpRet(vinTx.vout[1].scriptPubKey,vpk,vht,vunlockht); - if ( vfuncid != 'C' || vpk != pk || vunlockht != unlockht ) - return eval->Invalid("mismatched opreturn"); - } - } - } - return(true); - } - else if ( funcid == 'L' ) // lock -> lock funds with a unlockht - { - return(true); - } - else if ( funcid == 'R' ) // receive -> agree to receive 'I' from pk, amount, currency, dueht - { - return(true); - } - else if ( funcid == 'I' ) // issue -> issue currency to pk with due date height - { - return(true); - } - else if ( funcid == 'T' ) // transfer -> given 'R' transfer 'I' or 'T' to the pk of 'R' - { - return(true); - } - else if ( funcid == 'S' ) // settlement -> automatically spend issuers locked funds, given 'I' - { - return(true); - } - else if ( funcid == 'D' ) // insufficient settlement - { - return(true); - } - else if ( funcid == 'C' ) // coinbase - { - return(true); - } - // staking only for locked utxo - } - return eval->Invalid("fall through error"); -} -// end of consensus code - -// helper functions for rpc calls in rpcwallet.cpp - -int64_t AddMarmaraCoinbases(struct CCcontract_info *cp,CMutableTransaction &mtx,int32_t firstheight,CPubKey poolpk,int32_t maxinputs) -{ - char coinaddr[64]; CPubKey Marmarapk,pk; int64_t nValue,totalinputs = 0; uint256 txid,hashBlock; CTransaction vintx; int32_t unlockht,ht,vout,unlocks,n = 0; - std::vector > unspentOutputs; - Marmarapk = GetUnspendable(cp,0); - GetCCaddress1of2(cp,coinaddr,Marmarapk,poolpk); - SetCCunspents(unspentOutputs,coinaddr,true); - unlocks = MarmaraUnlockht(firstheight); - //fprintf(stderr,"check coinaddr.(%s)\n",coinaddr); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - //fprintf(stderr,"txid.%s/v%d\n",txid.GetHex().c_str(),vout); - if ( myGetTransaction(txid,vintx,hashBlock) != 0 ) - { - if ( vintx.IsCoinBase() != 0 && vintx.vout.size() == 2 && vintx.vout[1].nValue == 0 ) - { - if ( DecodeMaramaraCoinbaseOpRet(vintx.vout[1].scriptPubKey,pk,ht,unlockht) == 'C' && unlockht == unlocks && pk == poolpk && ht >= firstheight ) - { - if ( (nValue= vintx.vout[vout].nValue) > 0 && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 ) - { - if ( maxinputs != 0 ) - mtx.vin.push_back(CTxIn(txid,vout,CScript())); - nValue = it->second.satoshis; - totalinputs += nValue; - n++; - if ( maxinputs > 0 && n >= maxinputs ) - break; - } //else fprintf(stderr,"nValue.%8f\n",(double)nValue/COIN); - } //else fprintf(stderr,"decode error unlockht.%d vs %d pk.%d\n",unlockht,unlocks,pk == poolpk); - } else fprintf(stderr,"not coinbase\n"); - } else fprintf(stderr,"error getting tx\n"); - } - return(totalinputs); -} - -int64_t AddMarmarainputs(CMutableTransaction &mtx,std::vector &pubkeys,char *coinaddr,int64_t total,int32_t maxinputs) -{ - uint64_t threshold,nValue,totalinputs = 0; uint256 txid,hashBlock; CTransaction tx; int32_t numvouts,ht,unlockht,vout,i,n = 0; uint8_t funcid; CPubKey pk; std::vector vals; - std::vector > unspentOutputs; - SetCCunspents(unspentOutputs,coinaddr,true); - if ( maxinputs > CC_MAXVINS ) - maxinputs = CC_MAXVINS; - if ( maxinputs > 0 ) - threshold = total/maxinputs; - else threshold = total; - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - if ( it->second.satoshis < threshold ) - continue; - if ( myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 0 && vout < numvouts && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 ) - { - if ( (funcid= DecodeMaramaraCoinbaseOpRet(tx.vout[numvouts-1].scriptPubKey,pk,ht,unlockht)) == 'C' || funcid == 'P' || funcid == 'L' ) - { - //char str[64]; fprintf(stderr,"(%s) %s/v%d %.8f ht.%d unlockht.%d\n",coinaddr,uint256_str(str,txid),vout,(double)it->second.satoshis/COIN,ht,unlockht); - if ( total != 0 && maxinputs != 0 ) - { - mtx.vin.push_back(CTxIn(txid,vout,CScript())); - pubkeys.push_back(pk); - } - totalinputs += it->second.satoshis; - vals.push_back(it->second.satoshis); - n++; - if ( maxinputs != 0 && total == 0 ) - continue; - if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) - break; - } else fprintf(stderr,"null funcid\n"); - } - } - if ( maxinputs != 0 && total == 0 ) - { - std::sort(vals.begin(),vals.end()); - totalinputs = 0; - for (i=0; i txfee ) - inputsum = AddNormalinputs2(mtx,val,CC_MAXVINS/2); - //fprintf(stderr,"normal inputs %.8f val %.8f\n",(double)inputsum/COIN,(double)val/COIN); - mtx.vout.push_back(MakeCC1of2vout(EVAL_MARMARA,amount,Marmarapk,mypk)); - if ( inputsum < amount+txfee ) - { - refunlockht = MarmaraUnlockht(height); - result.push_back(Pair("normalfunds",ValueFromAmount(inputsum))); - result.push_back(Pair("height",height)); - result.push_back(Pair("unlockht",refunlockht)); - remains = (amount + txfee) - inputsum; - std::vector > unspentOutputs; - GetCCaddress1of2(cp,coinaddr,Marmarapk,mypk); - SetCCunspents(unspentOutputs,coinaddr,true); - threshold = remains / (MARMARA_VINS+1); - uint8_t mypriv[32]; - Myprivkey(mypriv); - CCaddr1of2set(cp,Marmarapk,mypk,mypriv,coinaddr); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - if ( (nValue= it->second.satoshis) < threshold ) - continue; - if ( myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 0 && vout < numvouts && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 ) - { - if ( (funcid= DecodeMaramaraCoinbaseOpRet(tx.vout[numvouts-1].scriptPubKey,pk,ht,unlockht)) == 'C' || funcid == 'P' || funcid == 'L' ) - { - if ( unlockht < refunlockht ) - { - mtx.vin.push_back(CTxIn(txid,vout,CScript())); - //fprintf(stderr,"merge CC vout %s/v%d %.8f unlockht.%d < ref.%d\n",txid.GetHex().c_str(),vout,(double)nValue/COIN,unlockht,refunlockht); - inputsum += nValue; - remains -= nValue; - if ( inputsum >= amount + txfee ) - { - //fprintf(stderr,"inputsum %.8f >= amount %.8f, update amount\n",(double)inputsum/COIN,(double)amount/COIN); - amount = inputsum - txfee; - break; - } - } - } - } - } - memset(mypriv,0,sizeof(mypriv)); - } - if ( inputsum >= amount+txfee ) - { - if ( inputsum > amount+txfee ) - { - change = (inputsum - amount); - mtx.vout.push_back(CTxOut(change,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - } - rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraCoinbaseOpret('L',height,mypk)); - if ( rawtx.size() == 0 ) - errorstr = (char *)"couldnt finalize CCtx"; - else - { - result.push_back(Pair("result",(char *)"success")); - result.push_back(Pair("hex",rawtx)); - return(result); - } - } else errorstr = (char *)"insufficient funds"; - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",errorstr)); - return(result); -} - -int32_t MarmaraSignature(uint8_t *utxosig,CMutableTransaction &mtx) -{ - uint256 txid,hashBlock; uint8_t *ptr; int32_t i,siglen,vout,numvouts; CTransaction tx; std::string rawtx; CPubKey mypk; std::vector pubkeys; struct CCcontract_info *cp,C; uint64_t txfee; - txfee = 10000; - vout = mtx.vin[0].prevout.n; - if ( myGetTransaction(mtx.vin[0].prevout.hash,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 1 && vout < numvouts ) - { - cp = CCinit(&C,EVAL_MARMARA); - mypk = pubkey2pk(Mypubkey()); - pubkeys.push_back(mypk); - rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,tx.vout[numvouts - 1].scriptPubKey,pubkeys); - if ( rawtx.size() > 0 ) - { - siglen = mtx.vin[0].scriptSig.size(); - ptr = &mtx.vin[0].scriptSig[0]; - for (i=0; i from utxo making change - -UniValue MarmaraSettlement(uint64_t txfee,uint256 refbatontxid) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - UniValue result(UniValue::VOBJ),a(UniValue::VARR); std::vector creditloop; uint256 batontxid,createtxid,refcreatetxid,hashBlock; uint8_t funcid; int32_t numerrs=0,i,n,numvouts,matures,refmatures,height; int64_t amount,refamount,remaining,inputsum,change; CPubKey Marmarapk,mypk,pk; std::string currency,refcurrency,rawtx; CTransaction tx,batontx; char coinaddr[64],myCCaddr[64],destaddr[64],batonCCaddr[64],str[2],txidaddr[64]; std::vector pubkeys; struct CCcontract_info *cp,C; - if ( txfee == 0 ) - txfee = 10000; - cp = CCinit(&C,EVAL_MARMARA); - mypk = pubkey2pk(Mypubkey()); - Marmarapk = GetUnspendable(cp,0); - remaining = change = 0; - height = chainActive.LastTip()->nHeight; - if ( (n= MarmaraGetbatontxid(creditloop,batontxid,refbatontxid)) > 0 ) - { - if ( myGetTransaction(batontxid,batontx,hashBlock) != 0 && (numvouts= batontx.vout.size()) > 1 ) - { - if ( (funcid= MarmaraDecodeLoopOpret(batontx.vout[numvouts-1].scriptPubKey,refcreatetxid,pk,refamount,refmatures,refcurrency)) != 0 ) - { - if ( refcreatetxid != creditloop[0] ) - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"invalid refcreatetxid, setting to creditloop[0]")); - return(result); - } - else if ( chainActive.LastTip()->nHeight < refmatures ) - { - fprintf(stderr,"doesnt mature for another %d blocks\n",refmatures - chainActive.LastTip()->nHeight); - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"cant settle immature creditloop")); - return(result); - } - else if ( (refmatures & 1) == 0 ) - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"cant automatic settle even maturity heights")); - return(result); - } - else if ( n < 1 ) - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"creditloop too short")); - return(result); - } - remaining = refamount; - GetCCaddress(cp,myCCaddr,Mypubkey()); - Getscriptaddress(batonCCaddr,batontx.vout[0].scriptPubKey); - if ( strcmp(myCCaddr,batonCCaddr) == 0 ) - { - mtx.vin.push_back(CTxIn(n == 1 ? batontxid : creditloop[1],1,CScript())); // issuance marker - pubkeys.push_back(Marmarapk); - mtx.vin.push_back(CTxIn(batontxid,0,CScript())); - pubkeys.push_back(mypk); - for (i=1; i 1 ) - { - if ( (funcid= MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,createtxid,pk,amount,matures,currency)) != 0 ) - { - GetCCaddress1of2(cp,coinaddr,Marmarapk,pk); - if ( (inputsum= AddMarmarainputs(mtx,pubkeys,coinaddr,remaining,MARMARA_VINS)) >= remaining ) - { - change = (inputsum - remaining); - mtx.vout.push_back(CTxOut(amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - if ( change > txfee ) - mtx.vout.push_back(MakeCC1of2vout(EVAL_MARMARA,change,Marmarapk,pk)); - rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraLoopOpret('S',createtxid,mypk,0,refmatures,currency),pubkeys); - result.push_back(Pair("result",(char *)"success")); - result.push_back(Pair("hex",rawtx)); - return(result); - } else remaining -= inputsum; - if ( mtx.vin.size() >= CC_MAXVINS - MARMARA_VINS ) - break; - } else fprintf(stderr,"null funcid for creditloop[%d]\n",i); - } else fprintf(stderr,"couldnt get creditloop[%d]\n",i); - } - if ( refamount - remaining > 2*txfee ) - { - mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(CCtxidaddr(txidaddr,createtxid))) << OP_CHECKSIG)); // failure marker - if ( refamount-remaining > 3*txfee ) - mtx.vout.push_back(CTxOut(refamount-remaining-2*txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraLoopOpret('D',createtxid,mypk,-remaining,refmatures,currency),pubkeys); - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"insufficient funds")); - result.push_back(Pair("hex",rawtx)); - result.push_back(Pair("remaining",ValueFromAmount(remaining))); - } - else - { - // jl777: maybe fund a txfee to report no funds avail - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"no funds available at all")); - } - } - else - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"this node does not have the baton")); - result.push_back(Pair("myCCaddr",myCCaddr)); - result.push_back(Pair("batonCCaddr",batonCCaddr)); - } - } - else - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"couldnt get batontxid opret")); - } - } - else - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"couldnt find batontxid")); - } - } - else - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"couldnt get creditloop")); - } - return(result); -} - -int32_t MarmaraGetCreditloops(int64_t &totalamount,std::vector &issuances,int64_t &totalclosed,std::vector &closed,struct CCcontract_info *cp,int32_t firstheight,int32_t lastheight,int64_t minamount,int64_t maxamount,CPubKey refpk,std::string refcurrency) -{ - char coinaddr[64]; CPubKey Marmarapk,senderpk; int64_t amount; uint256 createtxid,txid,hashBlock; CTransaction tx; int32_t numvouts,vout,matures,n=0; std::string currency; - std::vector > unspentOutputs; - Marmarapk = GetUnspendable(cp,0); - GetCCaddress(cp,coinaddr,Marmarapk); - SetCCunspents(unspentOutputs,coinaddr,true); - // do all txid, conditional on spent/unspent - //fprintf(stderr,"check coinaddr.(%s)\n",coinaddr); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - //fprintf(stderr,"txid.%s/v%d\n",txid.GetHex().c_str(),vout); - if ( vout == 1 && myGetTransaction(txid,tx,hashBlock) != 0 ) - { - if ( tx.IsCoinBase() == 0 && (numvouts= tx.vout.size()) > 2 && tx.vout[numvouts - 1].nValue == 0 ) - { - if ( MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,createtxid,senderpk,amount,matures,currency) == 'I' ) - { - n++; - if ( currency == refcurrency && matures >= firstheight && matures <= lastheight && amount >= minamount && amount <= maxamount && (refpk.size() == 0 || senderpk == refpk) ) - { - issuances.push_back(txid); - totalamount += amount; - } - } - } - } else fprintf(stderr,"error getting tx\n"); - } - return(n); -} - -UniValue MarmaraReceive(uint64_t txfee,CPubKey senderpk,int64_t amount,std::string currency,int32_t matures,uint256 batontxid,bool automaticflag) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - UniValue result(UniValue::VOBJ); CPubKey mypk; struct CCcontract_info *cp,C; std::string rawtx; char *errorstr=0; uint256 createtxid; int64_t batonamount; int32_t needbaton = 0; - cp = CCinit(&C,EVAL_MARMARA); - if ( txfee == 0 ) - txfee = 10000; - if ( automaticflag != 0 && (matures & 1) == 0 ) - matures++; - else if ( automaticflag == 0 && (matures & 1) != 0 ) - matures++; - mypk = pubkey2pk(Mypubkey()); - memset(&createtxid,0,sizeof(createtxid)); - if ( batontxid != zeroid && MarmaraGetcreatetxid(createtxid,batontxid) < 0 ) - errorstr = (char *)"cant get createtxid from batontxid"; - else if ( currency != "MARMARA" ) - errorstr = (char *)"for now, only MARMARA loops are supported"; - else if ( amount <= txfee ) - errorstr = (char *)"amount must be for more than txfee"; - else if ( matures <= chainActive.LastTip()->nHeight ) - errorstr = (char *)"it must mature in the future"; - if ( errorstr == 0 ) - { - if ( batontxid != zeroid ) - batonamount = txfee; - else batonamount = 2*txfee; - if ( AddNormalinputs(mtx,mypk,batonamount + txfee,1) > 0 ) - { - errorstr = (char *)"couldnt finalize CCtx"; - mtx.vout.push_back(MakeCC1vout(EVAL_MARMARA,batonamount,senderpk)); - rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraLoopOpret('R',createtxid,senderpk,amount,matures,currency)); - if ( rawtx.size() > 0 ) - errorstr = 0; - } else errorstr = (char *)"dont have enough normal inputs for 2*txfee"; - } - if ( rawtx.size() == 0 || errorstr != 0 ) - { - result.push_back(Pair("result","error")); - if ( errorstr != 0 ) - result.push_back(Pair("error",errorstr)); - } - else - { - result.push_back(Pair("result",(char *)"success")); - result.push_back(Pair("hex",rawtx)); - result.push_back(Pair("funcid","R")); - result.push_back(Pair("createtxid",createtxid.GetHex())); - if ( batontxid != zeroid ) - result.push_back(Pair("batontxid",batontxid.GetHex())); - result.push_back(Pair("senderpk",HexStr(senderpk))); - result.push_back(Pair("amount",ValueFromAmount(amount))); - result.push_back(Pair("matures",matures)); - result.push_back(Pair("currency",currency)); - } - return(result); -} - -UniValue MarmaraIssue(uint64_t txfee,uint8_t funcid,CPubKey receiverpk,int64_t amount,std::string currency,int32_t matures,uint256 approvaltxid,uint256 batontxid) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - UniValue result(UniValue::VOBJ); CPubKey mypk,Marmarapk; struct CCcontract_info *cp,C; std::string rawtx; uint256 createtxid; char *errorstr=0; - cp = CCinit(&C,EVAL_MARMARA); - if ( txfee == 0 ) - txfee = 10000; - // make sure less than maxlength - Marmarapk = GetUnspendable(cp,0); - mypk = pubkey2pk(Mypubkey()); - if ( MarmaraGetcreatetxid(createtxid,approvaltxid) < 0 ) - errorstr = (char *)"cant get createtxid from approvaltxid"; - else if ( currency != "MARMARA" ) - errorstr = (char *)"for now, only MARMARA loops are supported"; - else if ( amount <= txfee ) - errorstr = (char *)"amount must be for more than txfee"; - else if ( matures <= chainActive.LastTip()->nHeight ) - errorstr = (char *)"it must mature in the future"; - if ( errorstr == 0 ) - { - mtx.vin.push_back(CTxIn(approvaltxid,0,CScript())); - if ( funcid == 'T' ) - mtx.vin.push_back(CTxIn(batontxid,0,CScript())); - if ( funcid == 'I' || AddNormalinputs(mtx,mypk,txfee,1) > 0 ) - { - errorstr = (char *)"couldnt finalize CCtx"; - mtx.vout.push_back(MakeCC1vout(EVAL_MARMARA,txfee,receiverpk)); - if ( funcid == 'I' ) - mtx.vout.push_back(MakeCC1vout(EVAL_MARMARA,txfee,Marmarapk)); - rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraLoopOpret(funcid,createtxid,receiverpk,amount,matures,currency)); - if ( rawtx.size() > 0 ) - errorstr = 0; - } else errorstr = (char *)"dont have enough normal inputs for 2*txfee"; - } - if ( rawtx.size() == 0 || errorstr != 0 ) - { - result.push_back(Pair("result","error")); - if ( errorstr != 0 ) - result.push_back(Pair("error",errorstr)); - } - else - { - result.push_back(Pair("result",(char *)"success")); - result.push_back(Pair("hex",rawtx)); - char str[2]; str[0] = funcid, str[1] = 0; - result.push_back(Pair("funcid",str)); - result.push_back(Pair("createtxid",createtxid.GetHex())); - result.push_back(Pair("approvaltxid",approvaltxid.GetHex())); - if ( funcid == 'T' ) - result.push_back(Pair("batontxid",batontxid.GetHex())); - result.push_back(Pair("receiverpk",HexStr(receiverpk))); - result.push_back(Pair("amount",ValueFromAmount(amount))); - result.push_back(Pair("matures",matures)); - result.push_back(Pair("currency",currency)); - } - return(result); -} - -UniValue MarmaraCreditloop(uint256 txid) -{ - UniValue result(UniValue::VOBJ),a(UniValue::VARR); std::vector creditloop; uint256 batontxid,createtxid,refcreatetxid,hashBlock; uint8_t funcid; int32_t numerrs=0,i,n,numvouts,matures,refmatures; int64_t amount,refamount; CPubKey pk; std::string currency,refcurrency; CTransaction tx; char coinaddr[64],myCCaddr[64],destaddr[64],batonCCaddr[64],str[2]; struct CCcontract_info *cp,C; - cp = CCinit(&C,EVAL_MARMARA); - if ( (n= MarmaraGetbatontxid(creditloop,batontxid,txid)) > 0 ) - { - if ( myGetTransaction(batontxid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 1 ) - { - result.push_back(Pair("result",(char *)"success")); - Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(Mypubkey())) << OP_CHECKSIG); - result.push_back(Pair("myaddress",coinaddr)); - GetCCaddress(cp,myCCaddr,Mypubkey()); - result.push_back(Pair("myCCaddress",myCCaddr)); - if ( (funcid= MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,refcreatetxid,pk,refamount,refmatures,refcurrency)) != 0 ) - { - str[0] = funcid, str[1] = 0; - result.push_back(Pair("funcid",str)); - result.push_back(Pair("currency",refcurrency)); - if ( funcid == 'S' ) - { - refcreatetxid = creditloop[0]; - result.push_back(Pair("settlement",batontxid.GetHex())); - result.push_back(Pair("createtxid",refcreatetxid.GetHex())); - result.push_back(Pair("remainder",ValueFromAmount(refamount))); - result.push_back(Pair("settled",refmatures)); - result.push_back(Pair("pubkey",HexStr(pk))); - Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG); - result.push_back(Pair("coinaddr",coinaddr)); - result.push_back(Pair("collected",ValueFromAmount(tx.vout[0].nValue))); - Getscriptaddress(destaddr,tx.vout[0].scriptPubKey); - if ( strcmp(coinaddr,destaddr) != 0 ) - { - result.push_back(Pair("destaddr",destaddr)); - numerrs++; - } - refamount = -1; - } - else if ( funcid == 'D' ) - { - refcreatetxid = creditloop[0]; - result.push_back(Pair("settlement",batontxid.GetHex())); - result.push_back(Pair("createtxid",refcreatetxid.GetHex())); - result.push_back(Pair("remainder",ValueFromAmount(refamount))); - result.push_back(Pair("settled",refmatures)); - Getscriptaddress(destaddr,tx.vout[0].scriptPubKey); - result.push_back(Pair("txidaddr",destaddr)); - if ( tx.vout.size() > 1 ) - result.push_back(Pair("collected",ValueFromAmount(tx.vout[1].nValue))); - } - else - { - result.push_back(Pair("batontxid",batontxid.GetHex())); - result.push_back(Pair("createtxid",refcreatetxid.GetHex())); - result.push_back(Pair("amount",ValueFromAmount(refamount))); - result.push_back(Pair("matures",refmatures)); - if ( refcreatetxid != creditloop[0] ) - { - fprintf(stderr,"invalid refcreatetxid, setting to creditloop[0]\n"); - refcreatetxid = creditloop[0]; - numerrs++; - } - result.push_back(Pair("batonpk",HexStr(pk))); - Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG); - result.push_back(Pair("batonaddr",coinaddr)); - GetCCaddress(cp,batonCCaddr,pk); - result.push_back(Pair("batonCCaddr",batonCCaddr)); - Getscriptaddress(coinaddr,tx.vout[0].scriptPubKey); - if ( strcmp(coinaddr,batonCCaddr) != 0 ) - { - result.push_back(Pair("vout0address",coinaddr)); - numerrs++; - } - if ( strcmp(myCCaddr,coinaddr) == 0 ) - result.push_back(Pair("ismine",1)); - else result.push_back(Pair("ismine",0)); - } - for (i=0; i 1 ) - { - if ( (funcid= MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,createtxid,pk,amount,matures,currency)) != 0 ) - { - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("txid",creditloop[i].GetHex())); - str[0] = funcid, str[1] = 0; - obj.push_back(Pair("funcid",str)); - if ( funcid == 'R' && createtxid == zeroid ) - { - createtxid = creditloop[i]; - obj.push_back(Pair("issuerpk",HexStr(pk))); - Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG); - obj.push_back(Pair("issueraddr",coinaddr)); - GetCCaddress(cp,coinaddr,pk); - obj.push_back(Pair("issuerCCaddr",coinaddr)); - } - else - { - obj.push_back(Pair("receiverpk",HexStr(pk))); - Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG); - obj.push_back(Pair("receiveraddr",coinaddr)); - GetCCaddress(cp,coinaddr,pk); - obj.push_back(Pair("receiverCCaddr",coinaddr)); - } - Getscriptaddress(destaddr,tx.vout[0].scriptPubKey); - if ( strcmp(destaddr,coinaddr) != 0 ) - { - obj.push_back(Pair("vout0address",destaddr)); - numerrs++; - } - if ( i == 0 && refamount < 0 ) - { - refamount = amount; - refmatures = matures; - result.push_back(Pair("amount",ValueFromAmount(refamount))); - result.push_back(Pair("matures",refmatures)); - } - if ( createtxid != refcreatetxid || amount != refamount || matures != refmatures || currency != refcurrency ) - { - numerrs++; - obj.push_back(Pair("objerror",(char *)"mismatched createtxid or amount or matures or currency")); - obj.push_back(Pair("createtxid",createtxid.GetHex())); - obj.push_back(Pair("amount",ValueFromAmount(amount))); - obj.push_back(Pair("matures",matures)); - obj.push_back(Pair("currency",currency)); - } - a.push_back(obj); - } - } - } - result.push_back(Pair("n",n)); - result.push_back(Pair("numerrors",numerrs)); - result.push_back(Pair("creditloop",a)); - } - else - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"couldnt get batontxid opret")); - } - } - else - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"couldnt find batontxid")); - } - } - else - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"couldnt get creditloop")); - } - return(result); -} - -UniValue MarmaraPoolPayout(uint64_t txfee,int32_t firstheight,double perc,char *jsonstr) // [[pk0, shares0], [pk1, shares1], ...] -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - UniValue result(UniValue::VOBJ),a(UniValue::VARR); cJSON *item,*array; std::string rawtx; int32_t i,n; uint8_t buf[33]; CPubKey Marmarapk,pk,poolpk; int64_t payout,poolfee=0,total,totalpayout=0; double poolshares,share,shares = 0.; char *pkstr,*errorstr=0; struct CCcontract_info *cp,C; - poolpk = pubkey2pk(Mypubkey()); - if ( txfee == 0 ) - txfee = 10000; - cp = CCinit(&C,EVAL_MARMARA); - Marmarapk = GetUnspendable(cp,0); - if ( (array= cJSON_Parse(jsonstr)) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) - { - for (i=0; i, ]"; - break; - } - } - if ( errorstr == 0 && shares > SMALLVAL ) - { - shares += shares * perc; - if ( (total= AddMarmaraCoinbases(cp,mtx,firstheight,poolpk,60)) > 0 ) - { - for (i=0; i SMALLVAL ) - { - payout = (share * (total - txfee)) / shares; - if ( payout > 0 ) - { - if ( (pkstr= jstr(jitem(item,0),0)) != 0 && strlen(pkstr) == 66 ) - { - UniValue x(UniValue::VOBJ); - totalpayout += payout; - decode_hex(buf,33,pkstr); - mtx.vout.push_back(MakeCC1of2vout(EVAL_MARMARA,payout,Marmarapk,buf2pk(buf))); - x.push_back(Pair(pkstr, (double)payout/COIN)); - a.push_back(x); - } - } - } - } - if ( totalpayout > 0 && total > totalpayout-txfee ) - { - poolfee = (total - totalpayout - txfee); - mtx.vout.push_back(MakeCC1of2vout(EVAL_MARMARA,poolfee,Marmarapk,poolpk)); - } - rawtx = FinalizeCCTx(0,cp,mtx,poolpk,txfee,MarmaraCoinbaseOpret('P',firstheight,poolpk)); - if ( rawtx.size() == 0 ) - errorstr = (char *)"couldnt finalize CCtx"; - } else errorstr = (char *)"couldnt find any coinbases to payout"; - } - else if ( errorstr == 0 ) - errorstr = (char *)"no valid shares submitted"; - free(array); - } else errorstr = (char *)"couldnt parse poolshares jsonstr"; - if ( rawtx.size() == 0 || errorstr != 0 ) - { - result.push_back(Pair("result","error")); - if ( errorstr != 0 ) - result.push_back(Pair("error",errorstr)); - } - else - { - result.push_back(Pair("result",(char *)"success")); - result.push_back(Pair("hex",rawtx)); - if ( totalpayout > 0 && total > totalpayout-txfee ) - { - result.push_back(Pair("firstheight",firstheight)); - result.push_back(Pair("lastheight",((firstheight / MARMARA_GROUPSIZE)+1) * MARMARA_GROUPSIZE - 1)); - result.push_back(Pair("total",ValueFromAmount(total))); - result.push_back(Pair("totalpayout",ValueFromAmount(totalpayout))); - result.push_back(Pair("totalshares",shares)); - result.push_back(Pair("poolfee",ValueFromAmount(poolfee))); - result.push_back(Pair("perc",ValueFromAmount((int64_t)(100. * (double)poolfee/totalpayout * COIN)))); - result.push_back(Pair("payouts",a)); - } - } - return(result); -} - -// get all tx, constrain by vout, issuances[] and closed[] - -UniValue MarmaraInfo(CPubKey refpk,int32_t firstheight,int32_t lastheight,int64_t minamount,int64_t maxamount,std::string currency) -{ - CMutableTransaction mtx; std::vector pubkeys; - UniValue result(UniValue::VOBJ),a(UniValue::VARR),b(UniValue::VARR); int32_t i,n,matches; int64_t totalclosed=0,totalamount=0; std::vector issuances,closed; char coinaddr[64]; - CPubKey Marmarapk; struct CCcontract_info *cp,C; - cp = CCinit(&C,EVAL_MARMARA); - Marmarapk = GetUnspendable(cp,0); - result.push_back(Pair("result","success")); - Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(Mypubkey())) << OP_CHECKSIG); - result.push_back(Pair("myaddress",coinaddr)); - result.push_back(Pair("normal",ValueFromAmount(CCaddress_balance(coinaddr,0)))); - - GetCCaddress1of2(cp,coinaddr,Marmarapk,Mypubkey()); - result.push_back(Pair("myCCactivated",coinaddr)); - result.push_back(Pair("activated",ValueFromAmount(CCaddress_balance(coinaddr,1)))); - result.push_back(Pair("activated16",ValueFromAmount(AddMarmarainputs(mtx,pubkeys,coinaddr,0,MARMARA_VINS)))); - - GetCCaddress(cp,coinaddr,Mypubkey()); - result.push_back(Pair("myCCaddress",coinaddr)); - result.push_back(Pair("CCutxos",ValueFromAmount(CCaddress_balance(coinaddr,1)))); - - if ( refpk.size() == 33 ) - result.push_back(Pair("issuer",HexStr(refpk))); - if ( currency.size() == 0 ) - currency = (char *)"MARMARA"; - if ( firstheight <= lastheight ) - firstheight = 0, lastheight = (1 << 30); - if ( minamount <= maxamount ) - minamount = 0, maxamount = (1LL << 60); - result.push_back(Pair("firstheight",firstheight)); - result.push_back(Pair("lastheight",lastheight)); - result.push_back(Pair("minamount",ValueFromAmount(minamount))); - result.push_back(Pair("maxamount",ValueFromAmount(maxamount))); - result.push_back(Pair("currency",currency)); - if ( (n= MarmaraGetCreditloops(totalamount,issuances,totalclosed,closed,cp,firstheight,lastheight,minamount,maxamount,refpk,currency)) > 0 ) - { - result.push_back(Pair("n",n)); - matches = (int32_t)issuances.size(); - result.push_back(Pair("pending",matches)); - for (i=0; i /* @@ -639,12 +642,6 @@ bool OraclesDataValidate(struct CCcontract_info *cp,Eval* eval,const CTransactio else return(true); } -/*nt32_t GetLatestTimestamp(int32_t height) -{ - if ( KOMODO_NSPV_SUPERLITE ) return (NSPV_blocktime(height)); - return(komodo_heightstamp(height)); -} */ - bool OraclesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) { uint256 oracletxid,batontxid,txid; uint64_t txfee=10000; int32_t numvins,numvouts,preventCCvins,preventCCvouts; int64_t amount; uint256 hashblock; @@ -1128,7 +1125,7 @@ UniValue OracleDataSamples(uint256 reforacletxid,char* batonaddr,int32_t num) } } else - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid oracletxid " << oracletxid.GetHex()); + CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "invalid oracletxid " << oracletxid.GetHex()); } else CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "cant find oracletxid " << oracletxid.GetHex()); @@ -1203,7 +1200,7 @@ UniValue OracleInfo(uint256 origtxid) result.push_back(Pair("registered",a)); } else - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid oracletxid " << oracletxid.GetHex()); + CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "invalid oracletxid " << oracletxid.GetHex()); } else CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "cant find oracletxid " << oracletxid.GetHex()); diff --git a/src/cc/payments.cpp b/src/cc/payments.cpp index 948b97eb2a2..52c6b96b07e 100644 --- a/src/cc/payments.cpp +++ b/src/cc/payments.cpp @@ -14,6 +14,8 @@ ******************************************************************************/ #include "hex.h" #include "CCPayments.h" +#include "komodo_bitcoind.h" +#include /* 0) txidopret <- allocation, scriptPubKey, opret @@ -350,8 +352,7 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction & Paymentspk = GetUnspendable(cp,0); txidpk = CCtxidaddr(txidaddr,createtxid); GetCCaddress1of2(cp,txidaddr,Paymentspk,txidpk); - //fprintf(stderr, "lockedblocks.%i minrelease.%i totalallocations.%i txidopret1.%s txidopret2.%s\n",lockedblocks, minrelease, totalallocations, txidoprets[0].ToString().c_str(), txidoprets[1].ToString().c_str() ); - if ( !CheckTxFee(tx, PAYMENTS_TXFEE+1, chainActive.LastTip()->nHeight, chainActive.LastTip()->nTime, actualtxfee) ) + if ( !CheckTxFee(tx, PAYMENTS_TXFEE+1, chainActive.Tip()->nHeight, chainActive.Tip()->nTime, actualtxfee) ) return eval->Invalid("txfee is too high"); // Check that the change vout is playing the txid address. if ( IsPaymentsvout(cp,tx,0,txidaddr,ccopret) == 0 ) diff --git a/src/cc/pegs.cpp b/src/cc/pegs.cpp deleted file mode 100644 index 6ef33a88458..00000000000 --- a/src/cc/pegs.cpp +++ /dev/null @@ -1,1284 +0,0 @@ -/****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * - * * - * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * - * the top-level directory of this distribution for the individual copyright * - * holder information and the developer policies on copyright and licensing. * - * * - * Unless otherwise agreed in a custom licensing agreement, no part of the * - * SuperNET software, including this file may be copied, modified, propagated * - * or distributed except according to the terms contained in the LICENSE file * - * * - * Removal or modification of this copyright notice is prohibited. * - * * - ******************************************************************************/ - -#include "CCPegs.h" -#include "../importcoin.h" -#include "key_io.h" -#include - - -/* -pegs CC is able to create a coin backed (by any supported coin with gateways CC deposits) and pegged to any synthetic price that is able to be calculated based on prices CC - - First, the prices CC needs to be understood, so the extensive comments at the top of ~/src/cc/prices.cpp needs to be understood. - - The second aspect is the ability to import coins, as used by the crosschain burn/import and the -ac_import chains. - - - - OK, now we are ready to describe the pegs CC. Let us imagine an -ac_import sidechain with KMD gateways CC. Now we have each native coin fungible with the real KMD via the gateways deposit/withdraw mechanism. Let us start with that and make a pegged and backed USD chain. - - - - Here the native coin is KMD, but we want USD, so there needs to be a way to convert the KMD amounts into USD amounts. Something like "KMDBTC, BTCUSD, *, 1" which is the prices CC syntax to calculate KMD/USD, which is exactly what we need. So now we can assume that we have a block by block usable KMD/USD price. implementationwise, there can be an -ac option like -ac_peg="KMDBTC, BTCUSD, *, 1" and in conjunction with -ac_import=KMD gateways CC sidechain, we now have a chain where deposit of KMD issues the correct USD coins and redeem of USD coins releases the correct number of KMD coins. - - Are we done yet? - - Not quite, as the prices of KMD will be quite volatile relative to USD, which is good during bull markets, not so happy during bear markets. There are 2 halves to this problem, how to deal with massive price increase (easy to solve), how to solve 90% price drop (a lot harder). - - In order to solve both, what is needed is an "account" based tracking which updates based on both price change, coins issued, payments made. So let us create an account that is based on a specific pubkey, where all relevant deposits, issuances, withdraws are tracked via appropriate vin/vout markers. - - Let us modify the USD chain above so that only 80% of the possible USD is issued and 20% held in reserve. This 80% should be at least some easily changeable #define, or even an -ac parameter. We want the issued coins to be released without any encumberances, but the residual 20% value is still controlled (owned) but the depositor. This account has the amount of KMD deposited and USD issued. At the moment of deposit, there will still be 20% equity left. Let us start with 1000 KMD deposit, $1.5 per KMD -> 800 KMD converted to 1200 USD into depositor pubkey and the account of (1000 KMD, -1200 USD) = 200 KMD or $300 equity. - - Now it becomes easy for the bull market case, which is to allow (for a fee like 1%) issuance of more USD as the equity increases, so let us imagine KMD at $10: - - (1000 KMD, -1200 USD, 200KMD reserve) -> $2000 equity, issue 80% -> $1600 using 160 KMD - (1000 KMD, -1200 USD, 200KMD reserve, -160KMD, issue $1600 USD, 40 KMD reserve) - - we have $2800 USD in circulation, 40 KMD reserve left against $10000 marketcap of the original deposit. It it easy to see that there are never any problems with lack of KMD to redeem the issued USD in a world where prices only go up. Total USD issuance can be limited by using a decentralized account tracking based on each deposit. - - What is evident though is that with the constantly changing price and the various times that all the various deposits issue USD, the global reserves are something that will be hard to predict and in fact needs to be specifically tracked. Let us combine all accounts exposure in to a global reserves factor. This factor will control various max/min/ allowed and fee percentages. - - Now we are prepared to handle the price goes down scenario. We can rely on the global equity/reserve ratio to be changing relatively slowly as the reference price is the smooted trustless oracles price. This means there will be enough blocks to adjust the global reserves percentage. What we need to do is liquidate specific positions that have the least reserves. - - What does liquidation mean? It means a specific account will be purchased at below its current value and the KMD withdrawn. Let us assume the price drops to $5: - - (1000 KMD, -1200 USD, 200KMD reserve, -160KMD, issue $1600 USD, 40 KMD reserve) 1000 KMD with 2800 USD issued so $2200 reserves. Let us assume it can be liquidated at a 10% discount, so for $2000 in addition to the $2800, the 5000 KMD is able to be withdrawn. This removes 4800 USD coins for 1000 KMD, which is a very low reserve amount of 4%. If a low reserve amount is removed from the system, then the global reserve amount must be improved. - - In addition to the global reserves calculation, there needs to be a trigger percentage that enables positions to be liquidated. We also want to liquidate the worst positions, so in addition to the trigger percentage, there should be a liquidation threshold, and the liquidator would need to find 3 or more better positions that are beyond the liquidation threshold, to be able to liquidate. This will get us to at most 3 accounts that could be liquidated but are not able to, so some method to allow those to also be liquidated. The liquidating nodes are making instant profits, so they should be expected to do whatever blockchain scanning and proving to make things easy for the rest of the nodes. - - One last issue is the normal redemption case where we are not liquidating. In this case, it should be done at the current marketprice, should improve the global reserves metrics and not cause anybody whose position was modified to have cause for complaint. Ideally, there would be an account that has the identical to the global reserve percentage and also at the same price as current marketprice, but this is not realistic, so we need to identify classes of accounts and consider which ones can be fully or partially liquidated to satisfy the constraints. - - looking at our example account: - (1000 KMD, -1200 USD, 200KMD reserve, -160KMD, issue $1600 USD, 40 KMD reserve) - - what sort of non-liquidation withdraw would be acceptable? if the base amount 1000 KMD is reduced along with USD owed, then the reserve status will go up for the account. but that would seem to allow extra USD to be able to be issued. there should be no disadvantage from funding a withdraw, but also not any large advantage. it needs to be a neutral event.... - - One solution is to allow for the chance for any account to be liquidated, but the equity compensated for with a premium based on the account reserves. So in the above case, a premium of 5% on the 40KMD reserve is paid to liquidate its account. Instead of 5% premium, a lower 1% can be done if based on the MAX(correlated[daywindow],smoothed) so we get something that is close to the current marketprice. To prevent people taking advantage of the slowness of the smoothed price to adjust, there would need to be a one day delay in the withdraw. - - From a practical sense, it seems a day is a long time, so maybe having a way to pay a premium like 10%, or wait a day to get the MAX(correlated[daywindow],smoothed) price. This price "jumping" might also be taken advantage of in the deposit side, so similar to prices CC it seems good to have the MAX(correlated[daywindow],smoothed) method. - - Now, we have a decentralized mechanism to handle the price going lower! Combined with the fully decentralized method new USD coins are issued, makes this argubably the first decentralized blockchain that is both backed and pegged. There is the reliance on the gateways CC multisig signers, so there is a fundamental federated trust for chains without intrinsic value. - - Also, notice that the flexibly syntax of prices CC allows to define pegs easily for virtually any type of synthetic, and all the ECB fiats can easily get a backed and pegged coin. - - Let us now consider how to enforce a peg onto a specific gateways CC token. If this can also be achieved, then a full DEX for all the different gateways CC supported coins can be created onto a single fiat denominated chain. - - I think just having a pegscreate rpc call that binds an existing gateways create to a price CC syntax price will be almost enough to support this. Let us assume a USD stablechain and we have a BTC token, then pegscreate "BTCUSD, 1" - that will specify using the BTCUSD price, so now we need to create a based way to do tokenbid/tokenask. For a based price, the smoothed price is substituted. - - There is the issue of the one day delay, so it might make sense to allow specific bid/ask to be based on some simple combinations of the three possible prices. it might even be possible to go a bit overboard and make a forth like syntax to define the dynamic price for a bid, which maybe at times wont be valid, like it is only valid if the three prices are within 1% of each other. But all that seems over complex and for initial release it can just use the mined, correlated or smoothed price, with some specified percentage offset - - Implementation notes: - make sure that fees and markers that can be sent to an unspendable address are sent to: RNdqHx26GWy9bk8MtmH1UiXjQcXE4RKK2P, this is the address for BOTS - - - */ - -// start of consensus code -#ifndef PEGS_THRESHOLDS -#define PEGS_THRESHOLDS -#define PEGS_ACCOUNT_MAX_DEBT 80 -#define PEGS_GLOBAL_RED_ZONE 60 -#define PEGS_ACCOUNT_YELLOW_ZONE 60 -#define PEGS_ACCOUNT_RED_ZONE 90 -#endif // PEGS_THRESHOLDS -#define CC_MARKER_VALUE 10000 - -extern uint64_t ASSETCHAINS_PEGSCCPARAMS[3]; - -extern uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,uint256 &tokenid,std::string &coin,int64_t &totalsupply,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector &gatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype); -extern int64_t GetTokenBalance(CPubKey pk, uint256 tokenid); -extern int32_t komodo_currentheight(); -extern int32_t prices_syntheticvec(std::vector &vec, std::vector synthetic); -extern int64_t prices_syntheticprice(std::vector vec, int32_t height, int32_t minmax, int16_t leverage); - -CScript EncodePegsCreateOpRet(std::vector bindtxids) -{ - CScript opret; uint8_t evalcode = EVAL_PEGS; - opret << OP_RETURN << E_MARSHAL(ss << evalcode << 'C' << bindtxids); - return(opret); -} - -uint8_t DecodePegsCreateOpRet(const CScript &scriptPubKey,std::vector &bindtxids) -{ - std::vector vopret; uint8_t *script,e,f; - - GetOpReturnData(scriptPubKey, vopret); - script = (uint8_t *)vopret.data(); - if ( vopret.size() > 2 && script[0] == EVAL_PEGS && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> bindtxids) != 0 ) - { - return(f); - } - return(0); -} - -CScript EncodePegsFundOpRet(uint256 tokenid,uint256 pegstxid,CPubKey srcpub,int64_t amount,std::pair account) -{ - CScript opret; uint8_t evalcode=EVAL_PEGS,funcid='F'; struct CCcontract_info *cp,C; CPubKey pegspk; - std::vector pubkeys; vscript_t vopret; - - cp = CCinit(&C,EVAL_PEGS); - pegspk = GetUnspendable(cp,0); - pubkeys.push_back(srcpub); - pubkeys.push_back(pegspk); - LOGSTREAM("pegscc", CCLOG_DEBUG1, stream << "EncodePegsFundOpRet [" << account.first << "," << account.second << "]" << std::endl); - vopret = E_MARSHAL(ss << evalcode << funcid << pegstxid << srcpub << amount << account); - return(EncodeTokenOpRet(tokenid,pubkeys,make_pair(OPRETID_PEGSDATA, vopret))); -} - -uint8_t DecodePegsFundOpRet(const CScript &scriptPubKey,uint256 &tokenid,uint256 &pegstxid,CPubKey &srcpub,int64_t &amount,std::pair &account) -{ - std::vector> oprets; - std::vector vopret,vOpretExtra; uint8_t *script,e,f,tokenevalcode; std::vector pubkeys; - - if (DecodeTokenOpRet(scriptPubKey,tokenevalcode,tokenid,pubkeys, oprets)!=0 && GetOpretBlob(oprets, OPRETID_PEGSDATA, vOpretExtra) && tokenevalcode==EVAL_TOKENS && vOpretExtra.size()>0) - { - vopret=vOpretExtra; - } - else GetOpReturnData(scriptPubKey, vopret); - script = (uint8_t *)vopret.data(); - if ( vopret.size() > 2 && script[0] == EVAL_PEGS && E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> pegstxid; ss >> srcpub; ss >> amount; ss >> account) != 0 ) - { - return(f); - } - return(0); -} - -uint8_t DecodePegsGetOpRet(const CTransaction tx,uint256& pegstxid,uint256 &tokenid,CPubKey &srcpub,int64_t &amount,std::pair &account) -{ - std::vector vopret; uint8_t *script; - ImportProof proof; CTransaction burntx; std::vector payouts; - - GetOpReturnData(tx.vout[tx.vout.size()-1].scriptPubKey, vopret); - - script = (uint8_t *)vopret.data(); - if ( vopret.size() > 2 && script[0] == EVAL_IMPORTCOIN && UnmarshalImportTx(tx,proof,burntx,payouts) && UnmarshalBurnTx(burntx,pegstxid,tokenid,srcpub,amount,account)) - { - return('G'); - } - return(0); -} - -CScript EncodePegsReedemOpRet(uint256 tokenid,uint256 pegstxid,CPubKey srcpub,int64_t amount,std::pair account) -{ - CScript opret; uint8_t evalcode=EVAL_PEGS,funcid='R'; struct CCcontract_info *cp,C; - std::vector pubkeys; vscript_t vopret; - - cp = CCinit(&C,EVAL_PEGS); - pubkeys.push_back(srcpub); - vopret = E_MARSHAL(ss << evalcode << funcid << pegstxid << srcpub << amount << account); - return(EncodeTokenOpRet(tokenid,pubkeys,make_pair(OPRETID_PEGSDATA, vopret))); -} - -uint8_t DecodePegsRedeemOpRet(const CScript &scriptPubKey,uint256 &tokenid,uint256 &pegstxid,CPubKey &srcpub,int64_t &amount,std::pair &account) -{ - std::vector> oprets; - std::vector vopret,vOpretExtra; uint8_t *script,e,f,tokenevalcode; std::vector pubkeys; - - if (DecodeTokenOpRet(scriptPubKey,tokenevalcode,tokenid,pubkeys, oprets)!=0 && GetOpretBlob(oprets, OPRETID_PEGSDATA, vOpretExtra) && tokenevalcode==EVAL_TOKENS && vOpretExtra.size()>0) - { - vopret=vOpretExtra; - } - else GetOpReturnData(scriptPubKey, vopret); - script = (uint8_t *)vopret.data(); - if ( vopret.size() > 2 && script[0] == EVAL_PEGS && E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> pegstxid; ss >> srcpub; ss >> amount; ss >> account) != 0 ) - { - return(f); - } - return(0); -} - -CScript EncodePegsExchangeOpRet(uint256 tokenid,uint256 pegstxid,CPubKey pk1,CPubKey pk2,int64_t amount,std::pair account) -{ - CScript opret; uint8_t evalcode=EVAL_PEGS,funcid='E'; struct CCcontract_info *cp,C; - std::vector pubkeys; vscript_t vopret; CPubKey pegspk; - - cp = CCinit(&C,EVAL_PEGS); - pegspk = GetUnspendable(cp,0); - pubkeys.push_back(pk1); - pubkeys.push_back(pk2); - vopret = E_MARSHAL(ss << evalcode << funcid << pegstxid << pk1 << amount << account); - return(EncodeTokenOpRet(tokenid,pubkeys,make_pair(OPRETID_PEGSDATA, vopret))); -} - -uint8_t DecodePegsExchangeOpRet(const CScript &scriptPubKey,uint256 &tokenid,uint256 &pegstxid,CPubKey &srcpub,int64_t &amount,std::pair &account) -{ - std::vector> oprets; - std::vector vopret,vOpretExtra; uint8_t *script,e,f,tokenevalcode; std::vector pubkeys; - - if (DecodeTokenOpRet(scriptPubKey,tokenevalcode,tokenid,pubkeys, oprets)!=0 && GetOpretBlob(oprets, OPRETID_PEGSDATA, vOpretExtra) && tokenevalcode==EVAL_TOKENS && vOpretExtra.size()>0) - { - vopret=vOpretExtra; - } - else GetOpReturnData(scriptPubKey, vopret); - script = (uint8_t *)vopret.data(); - if ( vopret.size() > 2 && script[0] == EVAL_PEGS && E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> pegstxid; ss >> srcpub; ss >> amount; ss >> account) != 0 ) - { - return(f); - } - return(0); -} - -CScript EncodePegsLiquidateOpRet(uint256 tokenid,uint256 pegstxid,CPubKey srcpub,int64_t amount,std::pair account) -{ - CScript opret; uint8_t evalcode=EVAL_PEGS,funcid='L'; struct CCcontract_info *cp,C; - std::vector pubkeys; vscript_t vopret; - - cp = CCinit(&C,EVAL_PEGS); - pubkeys.push_back(srcpub); - vopret = E_MARSHAL(ss << evalcode << funcid << pegstxid << srcpub << amount << account); - return(EncodeTokenOpRet(tokenid,pubkeys,make_pair(OPRETID_PEGSDATA, vopret))); -} - -uint8_t DecodePegsLiquidateOpRet(const CScript &scriptPubKey,uint256 &tokenid,uint256 &pegstxid,CPubKey &srcpub,int64_t &amount,std::pair &account) -{ - std::vector> oprets; - std::vector vopret,vOpretExtra; uint8_t *script,e,f,tokenevalcode; std::vector pubkeys; - - if (DecodeTokenOpRet(scriptPubKey,tokenevalcode,tokenid,pubkeys, oprets)!=0 && GetOpretBlob(oprets, OPRETID_PEGSDATA, vOpretExtra) && tokenevalcode==EVAL_TOKENS && vOpretExtra.size()>0) - { - vopret=vOpretExtra; - } - else GetOpReturnData(scriptPubKey, vopret); - script = (uint8_t *)vopret.data(); - if ( vopret.size() > 2 && script[0] == EVAL_PEGS && E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> pegstxid; ss >> srcpub; ss >> amount; ss >> account) != 0 ) - { - return(f); - } - return(0); -} - -uint8_t DecodePegsOpRet(CTransaction tx,uint256& pegstxid,uint256& tokenid) -{ - std::vector> oprets; int32_t numvouts=tx.vout.size(); - std::vector vopret,vOpretExtra; uint8_t *script,e,f,tokenevalcode; std::vector pubkeys; - ImportProof proof; CTransaction burntx; std::vector payouts; uint256 tmppegstxid; CPubKey srcpub; int64_t amount; std::pair account; - - if (DecodeTokenOpRet(tx.vout[numvouts-1].scriptPubKey,tokenevalcode,tokenid,pubkeys, oprets)!=0 && GetOpretBlob(oprets, OPRETID_PEGSDATA, vOpretExtra) && tokenevalcode==EVAL_TOKENS && vOpretExtra.size()>0) - { - vopret=vOpretExtra; - } - else GetOpReturnData(tx.vout[numvouts-1].scriptPubKey, vopret); - script = (uint8_t *)vopret.data(); - if (tx.IsPegsImport()) - return(DecodePegsGetOpRet(tx,pegstxid,tokenid,srcpub,amount,account)); - else if ( vopret.size() > 2 && script[0] == EVAL_PEGS) - { - E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> pegstxid); - return(f); - } - return(0); -} - -int64_t IsPegsvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) -{ - char destaddr[64]; - if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) - { - if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 ) - return(tx.vout[v].nValue); - } - return(0); -} - -bool PegsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee) -{ - static uint256 zerohash; - CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis; - numvins = tx.vin.size(); - numvouts = tx.vout.size(); - for (i=0; iismyvin)(tx.vin[i].scriptSig) != 0 ) - { - //fprintf(stderr,"vini.%d check mempool\n",i); - if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 ) - return eval->Invalid("cant find vinTx"); - else - { - //fprintf(stderr,"vini.%d check hash and vout\n",i); - if ( hashBlock == zerohash ) - return eval->Invalid("cant Pegs from mempool"); - if ( (assetoshis= IsPegsvout(cp,vinTx,tx.vin[i].prevout.n)) != 0 ) - inputs += assetoshis; - } - } - } - for (i=0; iInvalid("mismatched inputs != outputs + txfee"); - } - else return(true); -} - -bool PegsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) -{ - int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64]; - return (true); - std::vector > txids; - numvins = tx.vin.size(); - numvouts = tx.vout.size(); - preventCCvins = preventCCvouts = -1; - if ( numvouts < 1 ) - return eval->Invalid("no vouts"); - else - { - for (i=0; iInvalid("illegal normal vini"); - } - } - //fprintf(stderr,"check amounts\n"); - if ( PegsExactAmounts(cp,eval,tx,1,10000) == false ) - { - fprintf(stderr,"Pegsget invalid amount\n"); - return false; - } - else - { - txid = tx.GetHash(); - memcpy(hash,&txid,sizeof(hash)); - retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts); - if ( retval != 0 ) - fprintf(stderr,"Pegsget validated\n"); - else fprintf(stderr,"Pegsget invalid\n"); - return(retval); - } - } -} -// end of consensus code - -// helper functions for rpc calls in rpcwallet.cpp - -int64_t AddPegsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk1,CPubKey pk2,int64_t total,int32_t maxinputs) -{ - // add threshold check - char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t vout,n = 0; - std::vector > unspentOutputs; - - if (pk2.IsValid()) GetCCaddress1of2(cp,coinaddr,pk1,pk2); - else GetCCaddress(cp,coinaddr,pk1); - SetCCunspents(unspentOutputs,coinaddr,true); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - // no need to prevent dup - if ( myGetTransaction(txid,vintx,hashBlock) != 0 ) - { - if (myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 ) - { - if ( total != 0 && maxinputs != 0 ) - mtx.vin.push_back(CTxIn(txid,vout,CScript())); - nValue = it->second.satoshis; - totalinputs += nValue; - n++; - if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) - break; - } - } - } - return(totalinputs); -} - -int64_t AddPegsTokenInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,uint256 pegstxid, uint256 tokenid, CPubKey pk1,CPubKey pk2, int64_t total,int32_t maxinputs) -{ - // add threshold check - char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t vout,n = 0; - std::vector > unspentOutputs; uint256 tmppegstxid,tmptokenid; CPubKey mypk; - - if (pk2.IsValid()) GetTokensCCaddress1of2(cp,coinaddr,pk1,pk2); - else GetTokensCCaddress(cp,coinaddr,pk1); - SetCCunspents(unspentOutputs,coinaddr,true); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - // no need to prevent dup - if ( myGetTransaction(txid,vintx,hashBlock) != 0 ) - { - if (myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 && DecodePegsOpRet(vintx,tmppegstxid,tmptokenid)!=0 && tmppegstxid==pegstxid && tmptokenid==tokenid) - { - if ( total != 0 && maxinputs != 0 ) - mtx.vin.push_back(CTxIn(txid,vout,CScript())); - nValue = it->second.satoshis; - totalinputs += nValue; - n++; - if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) - break; - } - } - } - if (pk2.IsValid()) - { - mypk = pubkey2pk(Mypubkey()); - if (mypk!=pk1 && mypk!=pk2) - { - CCaddrTokens1of2set(cp,pk1,pk2,cp->CCpriv,coinaddr); - } - else - { - uint8_t mypriv[32]; - Myprivkey(mypriv); - CCaddrTokens1of2set(cp,pk1,pk2,mypriv,coinaddr); - memset(mypriv,0,sizeof(mypriv)); - } - } - return(totalinputs); -} - -std::string PegsDecodeAccountTx(CTransaction tx,CPubKey& pk,int64_t &amount,std::pair &account) -{ - uint256 hashBlock,tokenid,pegstxid; int32_t numvouts=tx.vout.size(); char funcid; - - if ((funcid=DecodePegsOpRet(tx,pegstxid,tokenid))!=0) - { - switch(funcid) - { - case 'F': if (DecodePegsFundOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,pegstxid,pk,amount,account)=='F') return("fund"); - break; - case 'G': if (DecodePegsGetOpRet(tx,pegstxid,tokenid,pk,amount,account)=='G') return("get"); - break; - case 'R': if (DecodePegsRedeemOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,pegstxid,pk,amount,account)=='R') return("redeem"); - break; - case 'E': if (DecodePegsExchangeOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,pegstxid,pk,amount,account)=='R') return("exchange"); - break; - case 'L': if (DecodePegsLiquidateOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,pegstxid,pk,amount,account)=='L') return("liquidate"); - break; - } - } - return (""); -} - -char PegsFindAccount(struct CCcontract_info *cp,CPubKey pk,uint256 pegstxid, uint256 tokenid, uint256 &accounttxid, std::pair &account) -{ - char coinaddr[64]; int64_t nValue,tmpamount; uint256 txid,spenttxid,hashBlock,tmptokenid,tmppegstxid; - CTransaction tx,acctx; int32_t numvouts,vout,ratio; char funcid,f; CPubKey pegspk,tmppk; - std::vector > unspentOutputs; - ImportProof proof; CTransaction burntx; std::vector payouts; - - accounttxid=zeroid; - pegspk = GetUnspendable(cp,0); - GetCCaddress1of2(cp,coinaddr,pk,pegspk); - SetCCunspents(unspentOutputs,coinaddr,true); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - nValue = (int64_t)it->second.satoshis; - LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "txid=" << txid.GetHex() << ", vout=" << vout << ", nValue=" << nValue << std::endl); - if (vout == 1 && nValue == CC_MARKER_VALUE && myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts=tx.vout.size())>0 && - (f=DecodePegsOpRet(tx,tmppegstxid,tmptokenid))!=0 && pegstxid==tmppegstxid && tokenid==tmptokenid) - { - accounttxid=txid; - funcid=f; - acctx=tx; - } - } - if (accounttxid!=zeroid && myIsutxo_spentinmempool(spenttxid,ignorevin,accounttxid,1) != 0) - { - accounttxid=zeroid; - if (myGetTransaction(spenttxid,tx,hashBlock)!=0 && (numvouts=tx.vout.size()) > 0 && - (f=DecodePegsOpRet(tx,tmppegstxid,tmptokenid))!=0 && pegstxid==tmppegstxid && tokenid==tmptokenid) - { - funcid=f; - accounttxid=spenttxid; - acctx=tx; - } - } - if (accounttxid!=zeroid) - { - PegsDecodeAccountTx(acctx,tmppk,tmpamount,account); - return(funcid); - } - else return(0); -} - -int64_t PegsGetTokenPrice(uint256 tokenid) -{ - int64_t price; CTransaction tokentx; uint256 hashBlock; std::vector exp; - std::string name,desc; std::vector vorigpubkey; int32_t numvouts; - - if (myGetTransaction(tokenid,tokentx,hashBlock)!=0 && (numvouts=tokentx.vout.size())>0 && DecodeTokenCreateOpRet(tokentx.vout[numvouts-1].scriptPubKey,vorigpubkey,name,desc)=='c') - { - std::vector vexpr; - SplitStr(desc, vexpr); - if (prices_syntheticvec(exp, vexpr)>=0 && (price = prices_syntheticprice(exp, komodo_currentheight(), 0, 1))>=0) - return (price); - } - return (0); -} - -std::string PegsGetTokenName(uint256 tokenid) -{ - CTransaction tokentx; uint256 hashBlock; std::string name,desc; std::vector vorigpubkey; int32_t numvouts; - - if (myGetTransaction(tokenid,tokentx,hashBlock)!=0 && (numvouts=tokentx.vout.size())>0 && DecodeTokenCreateOpRet(tokentx.vout[numvouts-1].scriptPubKey,vorigpubkey,name,desc)=='c') - { - return (name); - } - CCerror = strprintf("cant find token create or invalid tokenid %s",tokenid.GetHex()); - LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl); - return(""); -} - -int64_t PegsGetTokensAmountPerPrice(int64_t amount,uint256 tokenid) -{ - mpz_t res,a,b; - mpz_init(res); - mpz_init(a); - mpz_init(b); - mpz_set_si(a, amount); - mpz_set_si(b, COIN); - mpz_mul(res, a, b); - mpz_set_si(a, PegsGetTokenPrice(tokenid)); - mpz_tdiv_q(res, res, a); - return (mpz_get_si(res)); -} - -double PegsGetRatio(uint256 tokenid,std::pair account) -{ - mpz_t res,a,b; - mpz_init(res); - mpz_init(a); - mpz_init(b); - mpz_set_si(a, account.first); - mpz_set_si(b, PegsGetTokenPrice(tokenid)); - mpz_mul(res, a, b); - mpz_set_si(a, COIN); - mpz_tdiv_q(res, res, a); - return ((double)account.second)*100/mpz_get_si(res); -} - -double PegsGetAccountRatio(uint256 pegstxid,uint256 tokenid,uint256 accounttxid) -{ - int64_t amount; uint256 hashBlock,tmptokenid,tmppegstxid; - CTransaction tx; int32_t numvouts; char funcid; CPubKey pk; - std::pair account; struct CCcontract_info *cp,C; - - cp = CCinit(&C,EVAL_PEGS); - if (myGetTransaction(accounttxid,tx,hashBlock) != 0 && (numvouts=tx.vout.size())>0 && - (funcid=DecodePegsOpRet(tx,tmppegstxid,tmptokenid))!=0 && pegstxid==tmppegstxid && tokenid==tmptokenid) - { - PegsDecodeAccountTx(tx,pk,amount,account); - return PegsGetRatio(tokenid,account); - } - return (0); -} - -double PegsGetGlobalRatio(uint256 pegstxid) -{ - char coinaddr[64]; int64_t nValue,amount,globaldebt=0; uint256 txid,accounttxid,hashBlock,tmppegstxid,tokenid; - CTransaction tx; int32_t numvouts,vout; char funcid; CPubKey mypk,pegspk,pk; - std::vector > unspentOutputs; std::pair account; - std::map> globalaccounts; - struct CCcontract_info *cp,C; - - cp = CCinit(&C,EVAL_PEGS); - pegspk = GetUnspendable(cp,0); - GetCCaddress1of2(cp,coinaddr,pegspk,pegspk); - SetCCunspents(unspentOutputs,coinaddr,true); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - nValue = (int64_t)it->second.satoshis; - if (vout == 0 && nValue == CC_MARKER_VALUE && myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts=tx.vout.size())>0 && - (funcid=DecodePegsOpRet(tx,tmppegstxid,tokenid))!=0 && pegstxid==tmppegstxid && (funcid=='F' || funcid=='G' || funcid=='E')) - { - PegsDecodeAccountTx(tx,pk,amount,account); - globalaccounts[tokenid].first+=account.first; - globalaccounts[tokenid].second+=account.second; - } - } - unspentOutputs.clear(); - GetTokensCCaddress(cp,coinaddr,pegspk); - SetCCunspents(unspentOutputs,coinaddr,true); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - nValue = (int64_t)it->second.satoshis; - if (myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts=tx.vout.size())>0 && DecodePegsOpRet(tx,tmppegstxid,tokenid)!=0 && pegstxid==tmppegstxid) - { - globalaccounts[tokenid].first+=nValue; - } - } - mpz_t res,globaldeposit,a,b; - mpz_init(res); - mpz_init(globaldeposit); - mpz_init(a); - mpz_init(b); - mpz_set_si(globaldeposit, 0); - for (std::map>::iterator it = globalaccounts.begin(); it != globalaccounts.end(); ++it) - { - mpz_set_si(res, 0); - mpz_set_si(a, globalaccounts[it->first].first); - mpz_set_si(b, PegsGetTokenPrice(it->first)); - mpz_mul(res,a,b); - mpz_add(globaldeposit,globaldeposit,res); - globaldebt+=globalaccounts[it->first].second; - } - if (globaldebt>0) - { - mpz_set_si(res, 0); - mpz_set_si(a, COIN); - mpz_tdiv_q(res, globaldeposit, a); - printf("%lu %lu\n",globaldebt,mpz_get_si(res)); - return ((double)globaldebt)*100/mpz_get_si(res); - } - return (0); -} - -std::string PegsFindBestAccount(struct CCcontract_info *cp,uint256 pegstxid, uint256 tokenid, int64_t tokenamount,uint256 &accounttxid, std::pair &account) -{ - char coinaddr[64]; int64_t nValue,tmpamount; uint256 txid,hashBlock,tmptokenid,tmppegstxid; - CTransaction tx,acctx; int32_t numvouts,vout; char funcid,f; CPubKey pegspk,tmppk; - std::vector > unspentOutputs; - ImportProof proof; CTransaction burntx; std::vector payouts; double ratio,maxratio=0; - std::pair tmpaccount; - - accounttxid=zeroid; - pegspk = GetUnspendable(cp,0); - GetCCaddress1of2(cp,coinaddr,pegspk,pegspk); - SetCCunspents(unspentOutputs,coinaddr,true); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - nValue = (int64_t)it->second.satoshis; - LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "txid=" << txid.GetHex() << ", vout=" << vout << ", nValue=" << nValue << std::endl); - if (vout == 0 && nValue == CC_MARKER_VALUE && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,0) == 0 && - (ratio=PegsGetAccountRatio(pegstxid,tokenid,txid))>(ASSETCHAINS_PEGSCCPARAMS[2]?ASSETCHAINS_PEGSCCPARAMS[2]:PEGS_ACCOUNT_YELLOW_ZONE) && ratio>maxratio) - { - if (myGetTransaction(txid,tx,hashBlock)!=0 && !PegsDecodeAccountTx(tx,tmppk,tmpamount,tmpaccount).empty() && tmpaccount.first>=tokenamount) - { - accounttxid=txid; - acctx=tx; - maxratio=ratio; - } - } - } - if (accounttxid!=zeroid) - { - return(PegsDecodeAccountTx(acctx,tmppk,tmpamount,account)); - } - else return(""); -} - -UniValue PegsCreate(const CPubKey& pk,uint64_t txfee,int64_t amount, std::vector bindtxids) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk,pegspk; struct CCcontract_info *cp,C; CTransaction tx; int32_t numvouts; int64_t totalsupply; std::string coin; - char depositaddr[64]; uint256 txid,hashBlock,tmptokenid,oracletxid; uint8_t M,N,taddr,prefix,prefix2,wiftype; std::vector pubkeys; - - cp = CCinit(&C,EVAL_PEGS); - if ( txfee == 0 ) - txfee = 10000; - mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey()); - pegspk = GetUnspendable(cp,0); - for(auto txid : bindtxids) - { - if (myGetTransaction(txid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find bindtxid " << txid.GetHex()); - if (DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tmptokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype)!='B') - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid bindtxid " << txid.GetHex()); - } - if ( AddNormalinputs(mtx,mypk,amount,64,pk.IsValid()) >= amount ) - { - for (int i=0; i<100; i++) mtx.vout.push_back(MakeCC1vout(EVAL_PEGS,(amount-txfee)/100,pegspk)); - return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodePegsCreateOpRet(bindtxids))); - } - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "error adding normal inputs"); -} - -UniValue PegsFund(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid,int64_t amount) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); std::string coin; - CTransaction pegstx,tx; int32_t numvouts; int64_t totalsupply,balance=0,funds=0,tokenfunds=0; uint256 accounttxid=zeroid,hashBlock,txid,tmptokenid,oracletxid; - CPubKey mypk,pegspk,tmppk; struct CCcontract_info *cp,*cpTokens,CTokens,C; char depositaddr[64],coinaddr[64]; std::pair account(0,0); - uint8_t M,N,taddr,prefix,prefix2,wiftype,mypriv[32]; std::vector pubkeys; bool found=false; std::vector bindtxids; - - cp = CCinit(&C,EVAL_PEGS); - cpTokens = CCinit(&CTokens,EVAL_TOKENS); - if ( txfee == 0 ) - txfee = 10000; - mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey()); - pegspk = GetUnspendable(cp,0); - if (myGetTransaction(pegstxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find pegstxid " << pegstxid.GetHex()); - if (DecodePegsCreateOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxids)!='C') - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid pegstxid " << pegstxid.GetHex()); - for(auto txid : bindtxids) - { - if (myGetTransaction(txid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find bindtxid " << txid.GetHex()); - if (DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tmptokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype)!='B') - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid bindtxid " << txid.GetHex()); - if (tmptokenid==tokenid) - { - found=true; - break; - } - } - if (!found) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid tokenid " << tokenid.GetHex()); - if ((balance=GetTokenBalance(mypk,tokenid))>=amount) - { - PegsFindAccount(cp,mypk,pegstxid,tokenid,accounttxid,account); - LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "current accounttxid=" << accounttxid.GetHex() << " [deposit=" << account.first << ",debt=" << account.second << "]" << std::endl); - if (accounttxid!=zeroid && myIsutxo_spentinmempool(ignoretxid,ignorevin,accounttxid,1) != 0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "previous account tx not yet confirmed"); - if (accounttxid!=zeroid && (funds=AddPegsInputs(cp,mtx,pegspk,CPubKey(),txfee,1))>=txfee) - { - funds+=2*CC_MARKER_VALUE; - mtx.vin.push_back(CTxIn(accounttxid,0,CScript())); - Myprivkey(mypriv); - mtx.vin.push_back(CTxIn(accounttxid,1,CScript())); - GetCCaddress1of2(cp,coinaddr,mypk,pegspk); - CCaddr1of2set(cp,mypk,pegspk,mypriv,coinaddr); - memset(mypriv,0,sizeof(mypriv)); - } - else funds=AddPegsInputs(cp,mtx,pegspk,CPubKey(),txfee+2*CC_MARKER_VALUE,3); - if (funds>=txfee+2*CC_MARKER_VALUE) - { - if ((tokenfunds=AddTokenCCInputs(cpTokens,mtx,mypk,tokenid,amount,64))>=amount) - { - mtx.vout.push_back(MakeCC1of2vout(EVAL_PEGS,CC_MARKER_VALUE,pegspk,pegspk)); - mtx.vout.push_back(MakeCC1of2vout(EVAL_PEGS,CC_MARKER_VALUE,mypk,pegspk)); - mtx.vout.push_back(MakeTokensCC1of2vout(EVAL_PEGS,amount,mypk,pegspk)); - if (tokenfunds-amount>0) mtx.vout.push_back(MakeTokensCC1vout(EVAL_TOKENS,tokenfunds-amount,mypk)); - if (funds>txfee+2*CC_MARKER_VALUE) mtx.vout.push_back(MakeCC1vout(EVAL_PEGS,funds-(txfee+2*CC_MARKER_VALUE),pegspk)); - account.first+=amount; - LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "new account [deposit=" << account.first << ",debt=" << account.second << "]" << std::endl); - return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodePegsFundOpRet(tokenid,pegstxid,mypk,amount,account))); - } - } - else - CCERR_RESULT("pegscc",CCLOG_INFO, stream <<"not enough balance in pegs global CC address"); - } - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough balance (" << balance << ") for this amount of tokens " << amount); -} - -UniValue PegsGet(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t amount) -{ - CMutableTransaction burntx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()),mtx; - CTransaction pegstx,tx; int32_t numvouts; int64_t funds=0; uint256 accounttxid=zeroid,hashBlock,pricestxid; char coinaddr[64]; - CPubKey mypk,pegspk,tmppk; struct CCcontract_info *cp,C; std::pair account(0,0); uint8_t mypriv[32]; - std::vector dummyproof; std::vector vouts; std::vector bindtxids; CScript opret; - - cp = CCinit(&C,EVAL_PEGS); - if ( txfee == 0 ) - txfee = 10000; - mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey()); - pegspk = GetUnspendable(cp,0); - if (myGetTransaction(pegstxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find pegstxid " << pegstxid.GetHex()); - if (DecodePegsCreateOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxids)!='C') - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid pegstxid " << pegstxid.GetHex()); - if (PegsFindAccount(cp,mypk,pegstxid,tokenid,accounttxid,account)==0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cannot find account from which to issue coins, fund account first with pegsfund!"); - if (accounttxid!=zeroid && myIsutxo_spentinmempool(ignoretxid,ignorevin,accounttxid,1) != 0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "previous account tx not yet confirmed"); - LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "current accounttxid=" << accounttxid.GetHex() << " [deposit=" << account.first << ",debt=" << account.second << "]" << std::endl); - // spending markers - vouts.push_back(MakeCC1of2vout(EVAL_PEGS,CC_MARKER_VALUE,pegspk,pegspk)); - vouts.push_back(MakeCC1of2vout(EVAL_PEGS,CC_MARKER_VALUE,mypk,pegspk)); - // coin issue - vouts.push_back(CTxOut(amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - account.second+=amount; - if (PegsGetRatio(tokenid,account)>PEGS_ACCOUNT_MAX_DEBT) - { - CCerror = strprintf("not possible to take more than %d%% of the deposit",PEGS_ACCOUNT_MAX_DEBT); - LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl); - return(""); - } - LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "new account [deposit=" << account.first << ",debt=" << account.second << "]" << std::endl); - // burn tx does not exist in pegs method but it must be created in order for import validation to pass - // fictive burntx input of previous account state tx - burntx.vin.push_back(CTxIn(accounttxid,0,CScript())); - // fictive output of coins in burn tx - burntx.vout.push_back(MakeBurnOutput(amount,0xffffffff,"PEGSCC",vouts,dummyproof,pegstxid,tokenid,mypk,amount,account)); - std::vector leaftxids; - BitcoinGetProofMerkleRoot(dummyproof, leaftxids); - MerkleBranch newBranch(0, leaftxids); - TxProof txProof = std::make_pair(burntx.GetHash(), newBranch); - mtx=MakePegsImportCoinTransaction(txProof,burntx,vouts); - Myprivkey(mypriv); - GetCCaddress1of2(cp,coinaddr,mypk,pegspk); - CCaddr1of2set(cp,mypk,pegspk,mypriv,coinaddr); - UniValue retstr = FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,opret); - memset(mypriv,0,sizeof(mypriv)); - return(retstr); -} - -UniValue PegsRedeem(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); std::string coin; - CTransaction pegstx,tx; int32_t numvouts; int64_t totalsupply,pegsfunds=0,funds=0,tokenfunds=0,amount; uint256 accounttxid=zeroid,hashBlock,txid,tmptokenid,oracletxid; - CPubKey mypk,pegspk,tmppk; struct CCcontract_info *cp,*cpTokens,CTokens,C; char depositaddr[64],coinaddr[64]; std::pair account(0,0); - uint8_t M,N,taddr,prefix,prefix2,wiftype,mypriv[32]; std::vector pubkeys; bool found=false; std::vector bindtxids; - - cp = CCinit(&C,EVAL_PEGS); - cpTokens = CCinit(&CTokens,EVAL_TOKENS); - if ( txfee == 0 ) - txfee = 10000; - mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey()); - pegspk = GetUnspendable(cp,0); - if (myGetTransaction(pegstxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find pegstxid " << pegstxid.GetHex()); - if (DecodePegsCreateOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxids)!='C') - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid pegstxid " << pegstxid.GetHex()); - for(auto txid : bindtxids) - { - if (myGetTransaction(txid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find bindtxid " << txid.GetHex()); - if (DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tmptokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype)!='B') - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid bindtxid " << txid.GetHex()); - if (tmptokenid==tokenid) - { - found=true; - break; - } - } - if (!found) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid tokenid " << tokenid.GetHex()); - if (PegsFindAccount(cp,mypk,pegstxid,tokenid,accounttxid,account)==0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cannot find account from which to redeem tokens!"); - if (accounttxid!=zeroid && myIsutxo_spentinmempool(ignoretxid,ignorevin,accounttxid,1) != 0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "previous account tx not yet confirmed"); - LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "current accounttxid=" << accounttxid.GetHex() << " [deposit=" << account.first << ",debt=" << account.second << "]" << std::endl); - if ((funds=AddNormalinputs(mtx,mypk,account.second,64,pk.IsValid()))>=account.second ) - { - if (accounttxid!=zeroid && (pegsfunds=AddPegsInputs(cp,mtx,pegspk,CPubKey(),txfee,1))>=txfee) - { - pegsfunds+=2*CC_MARKER_VALUE; - mtx.vin.push_back(CTxIn(accounttxid,0,CScript())); - mtx.vin.push_back(CTxIn(accounttxid,1,CScript())); - Myprivkey(mypriv); - GetCCaddress1of2(cp,coinaddr,mypk,pegspk); - CCaddr1of2set(cp,mypk,pegspk,mypriv,coinaddr); - amount=account.first; - if ((tokenfunds=AddPegsTokenInputs(cp,mtx,pegstxid,tokenid,mypk,pegspk,amount,64))>=amount) - { - if (pegsfunds>=txfee+2*CC_MARKER_VALUE) - { - mtx.vout.push_back(MakeCC1of2vout(EVAL_PEGS,CC_MARKER_VALUE,pegspk,pegspk)); - mtx.vout.push_back(MakeCC1of2vout(EVAL_PEGS,CC_MARKER_VALUE,mypk,pegspk)); - mtx.vout.push_back(MakeTokensCC1vout(EVAL_TOKENS,amount,mypk)); - mtx.vout.push_back(CTxOut(account.second,CScript() << ParseHex(HexStr(CCtxidaddr(coinaddr,pegstxid))) << OP_CHECKSIG)); - if (pegsfunds>txfee+2*CC_MARKER_VALUE) mtx.vout.push_back(MakeCC1vout(EVAL_PEGS,pegsfunds-(txfee+2*CC_MARKER_VALUE),pegspk)); - account.first=0; - account.second=0; - LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "new account [deposit=" << account.first << ",debt=" << account.second << "]" << std::endl); - UniValue retstr = FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodePegsReedemOpRet(tokenid,pegstxid,mypk,amount,account)); - memset(mypriv,0,32); - return(retstr); - } - else - { - memset(mypriv,0,32); - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough balance in pegs global CC address"); - } - } - memset(mypriv,0,32); - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough tokens in pegs account (" << tokenfunds << ") to redeem this amount of tokens " << account.first); - } - else - { - memset(mypriv,0,32); - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough balance in pegs global CC address"); - } - } - memset(mypriv,0,32); - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "to redeem from account and close it you must redeem full debt ammount " << account.second << " instead of " << funds); -} - - -UniValue PegsExchange(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t amount) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); std::string coin; - CTransaction pegstx,tx; int32_t numvouts; int64_t totalsupply,pegsfunds=0,funds=0,tokenfunds=0,tokenamount,tmpamount; uint256 accounttxid=zeroid,hashBlock,txid,tmptokenid,oracletxid; - CPubKey mypk,pegspk,tmppk; struct CCcontract_info *cp,*cpTokens,CTokens,C; char depositaddr[64],coinaddr[64]; std::pair account(0,0); - uint8_t M,N,taddr,prefix,prefix2,wiftype,mypriv[32]; std::vector pubkeys; bool found=false; std::vector bindtxids; - - cp = CCinit(&C,EVAL_PEGS); - cpTokens = CCinit(&CTokens,EVAL_TOKENS); - if ( txfee == 0 ) - txfee = 10000; - mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey()); - pegspk = GetUnspendable(cp,0); - if (myGetTransaction(pegstxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find pegstxid " << pegstxid.GetHex()); - if (DecodePegsCreateOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxids)!='C') - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid pegstxid " << pegstxid.GetHex()); - for(auto txid : bindtxids) - { - if (myGetTransaction(txid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find bindtxid " << txid.GetHex()); - if (DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tmptokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype)!='B') - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid bindtxid " << txid.GetHex()); - if (tmptokenid==tokenid) - { - found=true; - break; - } - } - if (!found) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid tokenid " << tokenid.GetHex()); - if (PegsFindAccount(cp,mypk,pegstxid,tokenid,accounttxid,account)!=0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "you have active account, please close account first before exchanging other coins!"); - if ((funds=AddNormalinputs(mtx,mypk,amount,64,pk.IsValid()))>=amount ) - { - if ((pegsfunds=AddPegsInputs(cp,mtx,pegspk,CPubKey(),txfee,1))>=txfee) - { - tokenamount=PegsGetTokensAmountPerPrice(amount,tokenid); - tokenfunds=AddPegsTokenInputs(cp,mtx,pegstxid,tokenid,pegspk,CPubKey(),tokenamount,64); - if (tokenfundsCCpriv,coinaddr); - pegsfunds+=2*CC_MARKER_VALUE; - } - if (tokenfunds>=tokenamount) - { - if (accounttxid!=zeroid) - { - mtx.vout.push_back(MakeCC1of2vout(EVAL_PEGS,CC_MARKER_VALUE,pegspk,pegspk)); - mtx.vout.push_back(MakeCC1of2vout(EVAL_PEGS,CC_MARKER_VALUE,tmppk,pegspk)); - } - if ((accounttxid!=zeroid && pegsfunds>=txfee+2*CC_MARKER_VALUE) || pegsfunds>=txfee) - { - mtx.vout.push_back(MakeTokensCC1vout(EVAL_TOKENS,tokenamount,mypk)); - mtx.vout.push_back(CTxOut(amount,CScript() << ParseHex(HexStr(CCtxidaddr(coinaddr,pegstxid))) << OP_CHECKSIG)); - if (tokenfunds>tokenamount) mtx.vout.push_back(MakeTokensCC1of2vout(EVAL_PEGS,tokenfunds-tokenamount,tmppk,pegspk)); - if (accounttxid!=zeroid) - { - if (pegsfunds>txfee+2*CC_MARKER_VALUE) mtx.vout.push_back(MakeCC1vout(EVAL_PEGS,pegsfunds-(txfee+2*CC_MARKER_VALUE),pegspk)); - account.first=account.first-tokenamount; - account.second=account.second-amount; - } - else if (pegsfunds>txfee) mtx.vout.push_back(MakeCC1vout(EVAL_PEGS,pegsfunds-txfee,pegspk)); - LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "modified account [deposit=" << account.first << ",debt=" << account.second << "]" << std::endl); - return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodePegsExchangeOpRet(tokenid,pegstxid,mypk,tmppk,amount,account))); - } - else - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough balance in pegs global CC address"); - } - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough tokens in pegs account (" << tokenfunds << ") to exchange to this amount of tokens " << tokenamount); - } - else - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough balance in pegs global CC address"); - } - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough funds to exchange " << amount << " coins to tokens - balance " << funds); -} - -UniValue PegsLiquidate(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid, uint256 liquidatetxid) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); std::string coin; - CTransaction pegstx,tx; int32_t numvouts; int64_t totalsupply,pegsfunds=0,funds=0,tokenfunds=0,amount,tmpamount,tokenamount,burnamount; - CPubKey mypk,pegspk,tmppk; struct CCcontract_info *cp,*cpTokens,CTokens,C; char depositaddr[64],coinaddr[64]; std::pair account(0,0),myaccount(0,0); - uint8_t M,N,taddr,prefix,prefix2,wiftype; std::vector pubkeys; bool found=false; std::vector bindtxids; - uint256 hashBlock,txid,tmptokenid,oracletxid,accounttxid; - - cp = CCinit(&C,EVAL_PEGS); - cpTokens = CCinit(&CTokens,EVAL_TOKENS); - if ( txfee == 0 ) - txfee = 10000; - mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey()); - pegspk = GetUnspendable(cp,0); - if (myGetTransaction(pegstxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find pegstxid " << pegstxid.GetHex()); - if (DecodePegsCreateOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxids)!='C') - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid pegstxid " << pegstxid.GetHex()); - for(auto txid : bindtxids) - { - if (myGetTransaction(txid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find bindtxid " << txid.GetHex()); - if (DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tmptokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype)!='B') - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid bindtxid " << txid.GetHex()); - if (tmptokenid==tokenid) - { - found=true; - break; - } - } - if (!found) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid tokenid " << tokenid.GetHex()); - if (PegsFindAccount(cp,mypk,pegstxid,tokenid,accounttxid,myaccount)==0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cannot find account, you must have an account to liquidate another account!"); - if (accounttxid!=zeroid && myIsutxo_spentinmempool(ignoretxid,ignorevin,accounttxid,1) != 0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "previous account tx not yet confirmed"); - if (PegsGetAccountRatio(pegstxid,tokenid,liquidatetxid)<(ASSETCHAINS_PEGSCCPARAMS[0]?ASSETCHAINS_PEGSCCPARAMS[0]:PEGS_ACCOUNT_RED_ZONE) || PegsGetGlobalRatio(pegstxid)<(ASSETCHAINS_PEGSCCPARAMS[1]?ASSETCHAINS_PEGSCCPARAMS[1]:PEGS_ACCOUNT_RED_ZONE)) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not able to liquidate account until account ratio > " << (ASSETCHAINS_PEGSCCPARAMS[0]?ASSETCHAINS_PEGSCCPARAMS[0]:PEGS_ACCOUNT_RED_ZONE) << "% and global ratio > " << (ASSETCHAINS_PEGSCCPARAMS[1]?ASSETCHAINS_PEGSCCPARAMS[1]:PEGS_ACCOUNT_RED_ZONE) << "%"); - if (liquidatetxid!=zeroid && myGetTransaction(liquidatetxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0 || PegsDecodeAccountTx(tx,tmppk,amount,account).empty()) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cannot find account to liquidate or invalid tx " << liquidatetxid.GetHex()); - if (liquidatetxid!=zeroid && myIsutxo_spentinmempool(ignoretxid,ignorevin,liquidatetxid,1) != 0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "previous liquidate account tx not yet confirmed"); - LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "current accounttxid=" << accounttxid.GetHex() << " [deposit=" << account.first << ",debt=" << account.second << "]" << std::endl); - tokenamount=account.first; - burnamount=account.second; - tmpamount=PegsGetTokensAmountPerPrice(burnamount,tokenid)*105/100; - amount=tmpamount+((tokenamount-tmpamount)*10/100); - if ((funds=AddNormalinputs(mtx,mypk,account.second,64))>=burnamount) - { - if (liquidatetxid!=zeroid && (pegsfunds=AddPegsInputs(cp,mtx,pegspk,CPubKey(),txfee,1))>=txfee) - { - pegsfunds+=2*CC_MARKER_VALUE; - mtx.vin.push_back(CTxIn(liquidatetxid,0,CScript())); - mtx.vin.push_back(CTxIn(liquidatetxid,1,CScript())); - GetCCaddress1of2(cp,coinaddr,tmppk,pegspk); - CCaddr1of2set(cp,tmppk,pegspk,cp->CCpriv,coinaddr); - if ((tokenfunds=AddPegsTokenInputs(cp,mtx,pegstxid,tokenid,tmppk,pegspk,tokenamount,64))==tokenamount) - { - if (pegsfunds>=txfee+2*CC_MARKER_VALUE) - { - mtx.vout.push_back(MakeCC1of2vout(EVAL_PEGS,CC_MARKER_VALUE,pegspk,pegspk)); - mtx.vout.push_back(MakeCC1of2vout(EVAL_PEGS,CC_MARKER_VALUE,tmppk,pegspk)); - mtx.vout.push_back(MakeTokensCC1vout(EVAL_TOKENS,amount,mypk)); - mtx.vout.push_back(MakeTokensCC1vout(EVAL_PEGS,tokenamount-amount,pegspk)); - mtx.vout.push_back(CTxOut(burnamount,CScript() << ParseHex(HexStr(CCtxidaddr(coinaddr,pegstxid))) << OP_CHECKSIG)); - if (pegsfunds>txfee+2*CC_MARKER_VALUE) mtx.vout.push_back(MakeCC1vout(EVAL_PEGS,pegsfunds-(txfee+2*CC_MARKER_VALUE),pegspk)); - account.first=0; - account.second=0; - LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "new account [deposit=" << account.first << ",debt=" << account.second << "]" << std::endl); - return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodePegsLiquidateOpRet(tokenid,pegstxid,mypk,amount,account))); - } - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough balance in pegs global CC address"); - } - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "tokens amount in pegs account " << tokenfunds << " not matching amount in account " << account.first); // this shouldn't happen - } - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough balance in pegs global CC address"); - } - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough funds to liquidate account, you must liquidate full debt ammount " << txfee+account.second << " instead of " << funds); -} - -UniValue PegsAccountHistory(const CPubKey& pk,uint256 pegstxid) -{ - char coinaddr[64]; int64_t nValue,amount; uint256 txid,accounttxid,hashBlock,tmptokenid,tmppegstxid; - CTransaction tx; int32_t numvouts,vout; char funcid; CPubKey mypk,pegspk,tmppk; std::map> accounts; - std::vector txids; std::pair account; std::vector bindtxids; - UniValue result(UniValue::VOBJ),acc(UniValue::VARR); struct CCcontract_info *cp,C; - - if (myGetTransaction(pegstxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find pegstxid " << pegstxid.GetHex()); - if (DecodePegsCreateOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxids)!='C') - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid pegstxid " << pegstxid.GetHex()); - result.push_back(Pair("result","success")); - result.push_back(Pair("name","pegsaccounthistory")); - cp = CCinit(&C,EVAL_PEGS); - mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey()); - pegspk = GetUnspendable(cp,0); - GetCCaddress1of2(cp,coinaddr,mypk,pegspk); - SetCCtxids(txids,coinaddr,true,EVAL_PEGS,pegstxid,0); - for (std::vector::const_iterator it=txids.begin(); it!=txids.end(); it++) - { - txid = *it; - if (myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts=tx.vout.size())>0 && - (funcid=DecodePegsOpRet(tx,tmppegstxid,tmptokenid))!=0 && pegstxid==tmppegstxid) - { - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("action",PegsDecodeAccountTx(tx,tmppk,amount,account))); - obj.push_back(Pair("amount",amount)); - obj.push_back(Pair("accounttxid",txid.GetHex())); - obj.push_back(Pair("token",PegsGetTokenName(tmptokenid))); - obj.push_back(Pair("deposit",account.first)); - obj.push_back(Pair("debt",account.second)); - acc.push_back(obj); - } - } - result.push_back(Pair("account history",acc)); - return(result); -} - -UniValue PegsAccountInfo(const CPubKey& pk,uint256 pegstxid) -{ - char coinaddr[64]; int64_t nValue,amount; uint256 txid,accounttxid,hashBlock,tmptokenid,tmppegstxid; std::map> accounts; - CTransaction tx; int32_t numvouts,vout; char funcid; CPubKey mypk,pegspk,tmppk; std::vector bindtxids; - std::vector > unspentOutputs; std::pair account; - UniValue result(UniValue::VOBJ),acc(UniValue::VARR); struct CCcontract_info *cp,C; - - if (myGetTransaction(pegstxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find pegstxid " << pegstxid.GetHex()); - if (DecodePegsCreateOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxids)!='C') - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid pegstxid " << pegstxid.GetHex()); - result.push_back(Pair("result","success")); - result.push_back(Pair("name","pegsaccountinfo")); - cp = CCinit(&C,EVAL_PEGS); - mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey()); - pegspk = GetUnspendable(cp,0); - GetCCaddress1of2(cp,coinaddr,mypk,pegspk); - SetCCunspents(unspentOutputs,coinaddr,true); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - nValue = (int64_t)it->second.satoshis; - //LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "txid=" << txid.GetHex() << ", vout=" << vout << ", nValue=" << nValue << std::endl); - if (vout == 1 && nValue == CC_MARKER_VALUE && myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts=tx.vout.size())>0 && - (funcid=DecodePegsOpRet(tx,tmppegstxid,tmptokenid))!=0 && pegstxid==tmppegstxid) - { - //LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "txid=" << txid.GetHex() << ", vout=" << vout << ", nValue=" << nValue << ", tokenid=" << tmptokenid.GetHex() << std::endl); - PegsDecodeAccountTx(tx,tmppk,amount,account); - accounts[tmptokenid].first=account.first; - accounts[tmptokenid].second=account.second; - } - } - for (std::map>::iterator it = accounts.begin(); it != accounts.end(); ++it) - { - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("token",PegsGetTokenName(it->first))); - obj.push_back(Pair("deposit",accounts[it->first].first)); - obj.push_back(Pair("debt",accounts[it->first].second)); - if (accounts[it->first].first==0 || accounts[it->first].second==0 || PegsGetTokenPrice(it->first)<=0) obj.push_back(Pair("ratio",0)); - else obj.push_back(Pair("ratio",strprintf("%.2f%%",PegsGetRatio(it->first,accounts[it->first])))); - acc.push_back(obj); - } - result.push_back(Pair("account info",acc)); - return(result); -} - -UniValue PegsWorstAccounts(uint256 pegstxid) -{ - char coinaddr[64]; int64_t nValue,amount; uint256 txid,accounttxid,hashBlock,tmppegstxid,tokenid,prev; - CTransaction tx; int32_t numvouts,vout; char funcid; CPubKey pegspk,pk; double ratio; std::vector bindtxids; - std::vector > unspentOutputs; std::pair account; - UniValue result(UniValue::VOBJ),acc(UniValue::VARR); struct CCcontract_info *cp,C; std::multimap map; - - if (myGetTransaction(pegstxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find pegstxid " << pegstxid.GetHex()); - if (DecodePegsCreateOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxids)!='C') - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid pegstxid " << pegstxid.GetHex()); - result.push_back(Pair("result","success")); - result.push_back(Pair("name","pegsworstaccounts")); - cp = CCinit(&C,EVAL_PEGS); - pegspk = GetUnspendable(cp,0); - GetCCaddress1of2(cp,coinaddr,pegspk,pegspk); - SetCCunspents(unspentOutputs,coinaddr,true); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - nValue = (int64_t)it->second.satoshis; - if (vout == 0 && nValue == CC_MARKER_VALUE && myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts=tx.vout.size())>0 && - (funcid=DecodePegsOpRet(tx,tmppegstxid,tokenid))!=0 && pegstxid==tmppegstxid) - { - PegsDecodeAccountTx(tx,pk,amount,account); - if (account.first==0 || account.second==0 || PegsGetTokenPrice(tokenid)<=0) ratio=0; - else ratio=PegsGetRatio(tokenid,account); - if (ratio>PEGS_ACCOUNT_RED_ZONE) - { - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("accounttxid",txid.GetHex())); - obj.push_back(Pair("deposit",account.first)); - obj.push_back(Pair("debt",account.second)); - obj.push_back(Pair("ratio",strprintf("%.2f%%",ratio))); - map.insert(std::pair(tokenid,obj)); - } - } - } - std::multimap::iterator it = map.begin(); - for (prev=it->first; it != map.end(); ++it) - { - if (it->first!=prev) - { - result.push_back(Pair(PegsGetTokenName(prev),acc)); - acc.clear(); - prev=it->first; - } - acc.push_back(it->second); - } - result.push_back(Pair(PegsGetTokenName(prev),acc)); - return(result); -} - -UniValue PegsInfo(uint256 pegstxid) -{ - char coinaddr[64]; int64_t nValue,amount; uint256 txid,accounttxid,hashBlock,tmppegstxid,tokenid; - CTransaction tx; int32_t numvouts,vout; char funcid; CPubKey pegspk,pk; std::vector bindtxids; - std::vector > unspentOutputs; std::pair account; - std::map> globalaccounts; double globaldeposit=0; - UniValue result(UniValue::VOBJ),acc(UniValue::VARR); struct CCcontract_info *cp,C; - - if (myGetTransaction(pegstxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0) - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find pegstxid " << pegstxid.GetHex()); - if (DecodePegsCreateOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxids)!='C') - CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid pegstxid " << pegstxid.GetHex()); - result.push_back(Pair("result","success")); - result.push_back(Pair("name","pegsinfo")); - cp = CCinit(&C,EVAL_PEGS); - pegspk = GetUnspendable(cp,0); - GetCCaddress1of2(cp,coinaddr,pegspk,pegspk); - SetCCunspents(unspentOutputs,coinaddr,true); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - nValue = (int64_t)it->second.satoshis; - if (vout == 0 && nValue == CC_MARKER_VALUE && myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts=tx.vout.size())>0 && - (funcid=DecodePegsOpRet(tx,tmppegstxid,tokenid))!=0 && pegstxid==tmppegstxid) - { - PegsDecodeAccountTx(tx,pk,amount,account); - globalaccounts[tokenid].first+=account.first; - globalaccounts[tokenid].second+=account.second; - } - } - unspentOutputs.clear(); - GetTokensCCaddress(cp,coinaddr,pegspk); - SetCCunspents(unspentOutputs,coinaddr,true); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - nValue = (int64_t)it->second.satoshis; - if (myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts=tx.vout.size())>0 && DecodePegsOpRet(tx,tmppegstxid,tokenid)!=0 && pegstxid==tmppegstxid) - { - globalaccounts[tokenid].first+=nValue; - } - } - for (std::map>::iterator it = globalaccounts.begin(); it != globalaccounts.end(); ++it) - { - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("token",PegsGetTokenName(it->first))); - obj.push_back(Pair("total deposit",globalaccounts[it->first].first)); - obj.push_back(Pair("total debt",globalaccounts[it->first].second)); - if (globalaccounts[it->first].first==0 || globalaccounts[it->first].second==0 || PegsGetTokenPrice(it->first)<=0) obj.push_back(Pair("total ratio",0)); - else obj.push_back(Pair("total ratio",strprintf("%.2f%%",PegsGetRatio(it->first,globalaccounts[it->first])))); - acc.push_back(obj); - } - result.push_back(Pair("info",acc)); - result.push_back(Pair("global ratio",strprintf("%.2f%%",PegsGetGlobalRatio(pegstxid)))); - return(result); -} diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp deleted file mode 100644 index 366ad01a56d..00000000000 --- a/src/cc/prices.cpp +++ /dev/null @@ -1,2510 +0,0 @@ -/****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * - * * - * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * - * the top-level directory of this distribution for the individual copyright * - * holder information and the developer policies on copyright and licensing. * - * * - * Unless otherwise agreed in a custom licensing agreement, no part of the * - * SuperNET software, including this file may be copied, modified, propagated * - * or distributed except according to the terms contained in the LICENSE file * - * * - * Removal or modification of this copyright notice is prohibited. * - * * - *****************************************************************************/ - - /* - CBOPRET creates trustless oracles, which can be used for making a synthetic cash settlement system based on real world prices; - - 0.5% fee based on betamount, NOT leveraged betamount!! - 0.1% collected by price basis determinant - 0.2% collected by rekt tx - - PricesBet -> +/-leverage, amount, synthetic -> opreturn includes current price - funds are locked into 1of2 global CC address - for first day, long basis is MAX(correlated,smoothed), short is MIN() - reference price is the smoothed of the previous block - if synthetic value + amount goes negative, then anybody can rekt it to collect a rektfee, proof of rekt must be included to show cost basis, rekt price - original creator can liquidate at anytime and collect (synthetic value + amount) from globalfund - 0.5% of bet -> globalfund - - PricesStatus -> bettxid maxsamples returns initial params, cost basis, amount left, rekt:true/false, rektheight, initial synthetic price, current synthetic price, net gain - - PricesRekt -> bettxid height -> 0.1% to miner, rest to global CC - - PricesClose -> bettxid returns (synthetic value + amount) - - PricesList -> all bettxid -> list [bettxid, netgain] - - */ - -/* -To create payments plan start a chain with the following ac_params: - -ac_snapshot=1440 (or for test chain something smaller, if you like.) - - this enables the payments airdrop cc to work. - -ac_earlytxidcontract=237 (Eval code for prices cc.) - - this allows to know what contract this chain is paying with the scriptpubkey in the earlytxid op_return. - -./komodod -ac_name=TESTPRC -ac_supply=100000000 -ac_reward=1000000000 -ac_nk=96,5 -ac_blocktime=20 -ac_cc=2 -ac_snapshot=50 -ac_sapling=1 -ac_earlytxidcontract=237 -testnode=1 -gen -genproclimit=1 - -Then in very early block < 10 or so, do paymentsairdrop eg. - `./komodo-cli -ac_name=TESTPRC paymentsairdrop '[10,10,0,3999,0,0]' -Once this tx is confirmed, do `paymentsfund` and decode the raw hex. You can edit the source to not send the tx if requried. -Get the full `hex` of the vout[0] that pays to CryptoCondition. then place it on chain with the following command: with the hex you got in place of the hex below. - './komodo-cli -ac_name=TESTPRC opreturn_burn 1 2ea22c8020292ba5c8fd9cc89b12b35bf8f5d00196990ecbb06102b84d9748d11d883ef01e81031210008203000401cc' -copy the hex, and sendrawtransaction, copy the txid returned. -this places the scriptpubkey that pays the plan into an op_return before block 100, allowing us to retreive it, and nobody to change it. -Restart the daemon with -earlytxid= eg: - -./komodod -ac_name=TESTPRC -ac_supply=100000000 -ac_reward=1000000000 -ac_nk=96,5 -ac_blocktime=20 -ac_cc=2 -ac_snapshot=50 -ac_sapling=1 -ac_earlytxidcontract=237 -earlytxid=cf89d17fb11037f65c160d0749dddd74dc44d9893b0bb67fe1f96c1f59786496 -testnode=1 -gen -genproclimit=1 - -mine the chain past block 100, preventing anyone else, creating another payments plan on chain before block 100. - -We call the following in Validation and RPC where the address is needed. -if ( ASSETCHAINS_EARLYTXIDCONTRACT == EVAL_PRICES && KOMODO_EARLYTXID_SCRIPTPUB.size() == 0 ) - GetKomodoEarlytxidScriptPub(); - -This will fetch the op_return, calculate the scriptPubKey and save it to the global. -On daemon restart as soon as validation for BETTX happens the global will be filled, after this the transaction never needs to be looked up again. -GetKomodoEarlytxidScriptPub is on line #2080 of komodo_bitcoind.h - */ - -#include "CCassets.h" -#include "CCPrices.h" - -#include -#include - -#define IS_CHARINSTR(c, str) (std::string(str).find((char)(c)) != std::string::npos) - -#define NVOUT_CCMARKER 1 -#define NVOUT_NORMALMARKER 3 - -typedef struct OneBetData { - int64_t positionsize; - int32_t firstheight; - int64_t costbasis; - int64_t profits; - - OneBetData() { positionsize = 0; firstheight = 0; costbasis = 0; profits = 0; } // it is important to clear costbasis as it will be calculated as minmax from inital value 0 -} onebetdata; - -typedef struct BetInfo { - uint256 txid; - int64_t averageCostbasis, firstprice, lastprice, liquidationprice, equity; - int64_t exitfee; - int32_t lastheight; - int16_t leverage; - bool isOpen, isRekt; - uint256 tokenid; - - std::vector vecparsed; - std::vector bets; - CPubKey pk; - - bool isUp; - - BetInfo() { - averageCostbasis = firstprice = lastprice = liquidationprice = equity = 0; - lastheight = 0; - leverage = 0; - exitfee = 0; - isOpen = isRekt = isUp = false; - } -} BetInfo; - -typedef struct MatchedBookTotal { - - int64_t diffLeveragedPosition; - -} MatchedBookTotal; - -typedef struct TotalFund { - int64_t totalFund; - int64_t totalActiveBets; - int64_t totalCashout; - int64_t totalRekt; - int64_t totalEquity; - - TotalFund() { - totalFund = totalActiveBets = totalCashout = totalRekt = totalEquity = 0; - } - -} TotalFund; - -int32_t prices_syntheticprofits(int64_t &costbasis, int32_t firstheight, int32_t height, int16_t leverage, std::vector vec, int64_t positionsize, int64_t &profits, int64_t &outprice); -static bool prices_isacceptableamount(const std::vector &vecparsed, int64_t amount, int16_t leverage); - -// helpers: - -// returns true if there are only digits and no alphas or slashes in 's' -inline bool is_weight_str(std::string s) { - return - std::count_if(s.begin(), s.end(), [](unsigned char c) { return std::isdigit(c); } ) > 0 && - std::count_if(s.begin(), s.end(), [](unsigned char c) { return std::isalpha(c) || c == '/'; } ) == 0; -} - - -// start of consensus code - -CScript prices_betopret(CPubKey mypk,int32_t height,int64_t amount,int16_t leverage,int64_t firstprice,std::vector vec,uint256 tokenid) -{ - CScript opret; - opret << OP_RETURN << E_MARSHAL(ss << EVAL_PRICES << 'B' << mypk << height << amount << leverage << firstprice << vec << tokenid); - return(opret); -} - -uint8_t prices_betopretdecode(CScript scriptPubKey,CPubKey &pk,int32_t &height,int64_t &amount,int16_t &leverage,int64_t &firstprice,std::vector &vec,uint256 &tokenid) -{ - std::vector vopret; uint8_t e,f; - - GetOpReturnData(scriptPubKey,vopret); - if (vopret.size() > 2 && E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> pk; ss >> height; ss >> amount; ss >> leverage; ss >> firstprice; ss >> vec; ss >> tokenid) != 0 && e == EVAL_PRICES && f == 'B') - { - return(f); - } - return(0); -} - -CScript prices_addopret(uint256 bettxid,CPubKey mypk,int64_t amount) -{ - CScript opret; - opret << OP_RETURN << E_MARSHAL(ss << EVAL_PRICES << 'A' << bettxid << mypk << amount); - return(opret); -} - -uint8_t prices_addopretdecode(CScript scriptPubKey,uint256 &bettxid,CPubKey &pk,int64_t &amount) -{ - std::vector vopret; uint8_t e,f; - GetOpReturnData(scriptPubKey,vopret); - if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> bettxid; ss >> pk; ss >> amount) != 0 && e == EVAL_PRICES && f == 'A' ) - { - return(f); - } - return(0); -} - -CScript prices_costbasisopret(uint256 bettxid,CPubKey mypk,int32_t height,int64_t costbasis) -{ - CScript opret; - opret << OP_RETURN << E_MARSHAL(ss << EVAL_PRICES << 'C' << bettxid << mypk << height << costbasis); - return(opret); -} - -uint8_t prices_costbasisopretdecode(CScript scriptPubKey,uint256 &bettxid,CPubKey &pk,int32_t &height,int64_t &costbasis) -{ - std::vector vopret; uint8_t e,f; - GetOpReturnData(scriptPubKey,vopret); - if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> bettxid; ss >> pk; ss >> height; ss >> costbasis) != 0 && e == EVAL_PRICES && f == 'C' ) - { - return(f); - } - return(0); -} - -CScript prices_finalopret(bool isRekt, uint256 bettxid, CPubKey pk, int32_t lastheight, int64_t costbasis, int64_t lastprice, int64_t liquidationprice, int64_t equity, int64_t exitfee, uint32_t nonce) -{ - CScript opret; - opret << OP_RETURN << E_MARSHAL(ss << EVAL_PRICES << (isRekt ? 'R' : 'F') << bettxid << pk << lastheight << costbasis << lastprice << liquidationprice << equity << exitfee << nonce); - return(opret); -} - -uint8_t prices_finalopretdecode(CScript scriptPubKey, uint256 &bettxid, CPubKey &pk, int32_t &lastheight, int64_t &costbasis, int64_t &lastprice, int64_t &liquidationprice, int64_t &equity, int64_t &exitfee) -{ - std::vector vopret; uint8_t e,f; - uint32_t nonce; - - GetOpReturnData(scriptPubKey,vopret); - if (vopret.size() > 2 && E_UNMARSHAL(vopret, ss >> e; ss >> f; ss >> bettxid; ss >> pk; ss >> lastheight; ss >> costbasis; ss >> lastprice; ss >> liquidationprice; ss >> equity; ss >> exitfee; if (!ss.eof()) ss >> nonce; ) != 0 && e == EVAL_PRICES && (f == 'F' || f == 'R')) - { - return(f); - } - return(0); -} - -// price opret basic validation and retrieval -static uint8_t PricesCheckOpret(const CTransaction & tx, vscript_t &opret) -{ - if (tx.vout.size() > 0 && GetOpReturnData(tx.vout.back().scriptPubKey, opret) && opret.size() > 2 && opret.begin()[0] == EVAL_PRICES && IS_CHARINSTR(opret.begin()[1], "BACFR")) - return opret.begin()[1]; - else - return (uint8_t)0; -} - -// validate bet tx helper -static bool ValidateBetTx(struct CCcontract_info *cp, Eval *eval, const CTransaction & bettx) -{ - uint256 tokenid; - int64_t positionsize, firstprice; - int32_t firstheight; - int16_t leverage; - CPubKey pk, pricespk; - std::vector vec; - - // check payment cc config: - if ( ASSETCHAINS_EARLYTXIDCONTRACT == EVAL_PRICES && KOMODO_EARLYTXID_SCRIPTPUB.size() == 0 ) - GetKomodoEarlytxidScriptPub(); - - if (bettx.vout.size() < 6 || bettx.vout.size() > 7) - return eval->Invalid("incorrect vout number for bet tx"); - - vscript_t opret; - if( prices_betopretdecode(bettx.vout.back().scriptPubKey, pk, firstheight, positionsize, leverage, firstprice, vec, tokenid) != 'B') - return eval->Invalid("cannot decode opreturn for bet tx"); - - pricespk = GetUnspendable(cp, 0); - - if (MakeCC1vout(cp->evalcode, bettx.vout[0].nValue, pk) != bettx.vout[0]) - return eval->Invalid("cannot validate vout0 in bet tx with pk from opreturn"); - if (MakeCC1vout(cp->evalcode, bettx.vout[1].nValue, pricespk) != bettx.vout[1]) - return eval->Invalid("cannot validate vout1 in bet tx with global pk"); - if (MakeCC1vout(cp->evalcode, bettx.vout[2].nValue, pricespk) != bettx.vout[2] ) - return eval->Invalid("cannot validate vout2 in bet tx with pk from opreturn"); - // This should be all you need to verify it, maybe also check amount? - if ( bettx.vout[4].scriptPubKey != KOMODO_EARLYTXID_SCRIPTPUB ) - return eval->Invalid("the fee was paid to wrong address."); - - int64_t betamount = bettx.vout[2].nValue; - if (betamount != PRICES_SUBREVSHAREFEE(positionsize)) { - return eval->Invalid("invalid position size in the opreturn"); - } - - // validate if normal inputs are really signed by originator pubkey (someone not cheating with originator pubkey) - CAmount ccOutputs = 0; - for (auto vout : bettx.vout) - if (vout.scriptPubKey.IsPayToCryptoCondition()) - ccOutputs += vout.nValue; - CAmount normalInputs = TotalPubkeyNormalInputs(bettx, pk); - if (normalInputs < ccOutputs) { - return eval->Invalid("bettx normal inputs not signed with pubkey in opret"); - } - - if (leverage > PRICES_MAXLEVERAGE || leverage < -PRICES_MAXLEVERAGE) { - return eval->Invalid("invalid leverage"); - } - - return true; -} - -// validate add funding tx helper -static bool ValidateAddFundingTx(struct CCcontract_info *cp, Eval *eval, const CTransaction & addfundingtx, const CTransaction & vintx) -{ - uint256 bettxid; - int64_t amount; - CPubKey pk, pricespk; - vscript_t vintxOpret; - - // check payment cc config: - if (ASSETCHAINS_EARLYTXIDCONTRACT == EVAL_PRICES && KOMODO_EARLYTXID_SCRIPTPUB.size() == 0) - GetKomodoEarlytxidScriptPub(); - - if (addfundingtx.vout.size() < 4 || addfundingtx.vout.size() > 5) - return eval->Invalid("incorrect vout number for add funding tx"); - - vscript_t opret; - if (prices_addopretdecode(addfundingtx.vout.back().scriptPubKey, bettxid, pk, amount) != 'A') - return eval->Invalid("cannot decode opreturn for add funding tx"); - - pricespk = GetUnspendable(cp, 0); - uint8_t vintxFuncId = PricesCheckOpret(vintx, vintxOpret); - if (vintxFuncId != 'A' && vintxFuncId != 'B') { // if vintx is bettx - return eval->Invalid("incorrect vintx funcid"); - } - - if (vintxFuncId == 'B' && vintx.GetHash() != bettxid) {// if vintx is bettx - return eval->Invalid("incorrect bet txid in opreturn"); - } - - if (MakeCC1vout(cp->evalcode, addfundingtx.vout[0].nValue, pk) != addfundingtx.vout[0]) - return eval->Invalid("cannot validate vout0 in add funding tx with pk from opreturn"); - if (MakeCC1vout(cp->evalcode, addfundingtx.vout[1].nValue, pricespk) != addfundingtx.vout[1]) - return eval->Invalid("cannot validate vout1 in add funding tx with global pk"); - - // This should be all you need to verify it, maybe also check amount? - if (addfundingtx.vout[2].scriptPubKey != KOMODO_EARLYTXID_SCRIPTPUB) - return eval->Invalid("the fee was paid to wrong address."); - - int64_t betamount = addfundingtx.vout[1].nValue; - if (betamount != PRICES_SUBREVSHAREFEE(amount)) { - return eval->Invalid("invalid bet position size in the opreturn"); - } - - return true; -} - -// validate costbasis tx helper (deprecated) -/* -static bool ValidateCostbasisTx(struct CCcontract_info *cp, Eval *eval, const CTransaction & costbasistx, const CTransaction & bettx) -{ - uint256 bettxid; - int64_t costbasisInOpret; - CPubKey pk, pricespk; - int32_t height; - - return true; //deprecated - - // check basic structure: - if (costbasistx.vout.size() < 3 || costbasistx.vout.size() > 4) - return eval->Invalid("incorrect vout count for costbasis tx"); - - vscript_t opret; - if (prices_costbasisopretdecode(costbasistx.vout.back().scriptPubKey, bettxid, pk, height, costbasisInOpret) != 'C') - return eval->Invalid("cannot decode opreturn for costbasis tx"); - - pricespk = GetUnspendable(cp, 0); - if (CTxOut(costbasistx.vout[0].nValue, CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG) != costbasistx.vout[0]) //might go to any pk who calculated costbasis - return eval->Invalid("cannot validate vout0 in costbasis tx with pk from opreturn"); - if (MakeCC1vout(cp->evalcode, costbasistx.vout[1].nValue, pricespk) != costbasistx.vout[1]) - return eval->Invalid("cannot validate vout1 in costbasis tx with global pk"); - - if (bettx.GetHash() != bettxid) - return eval->Invalid("incorrect bettx id"); - - if (bettx.vout.size() < 1) // for safety and for check encapsulation - return eval->Invalid("incorrect bettx no vouts"); - - // check costbasis rules: - if (costbasistx.vout[0].nValue > bettx.vout[1].nValue / 10) { - return eval->Invalid("costbasis myfee too big"); - } - - uint256 tokenid; - int64_t positionsize, firstprice; - int32_t firstheight; - int16_t leverage; - CPubKey betpk; - std::vector vec; - if (prices_betopretdecode(bettx.vout.back().scriptPubKey, betpk, firstheight, positionsize, leverage, firstprice, vec, tokenid) != 'B') - return eval->Invalid("cannot decode opreturn for bet tx"); - - if (firstheight + PRICES_DAYWINDOW + PRICES_SMOOTHWIDTH > chainActive.Height()) { - return eval->Invalid("cannot calculate costbasis yet"); - } - - int64_t costbasis = 0, profits, lastprice; - int32_t retcode = prices_syntheticprofits(costbasis, firstheight, firstheight + PRICES_DAYWINDOW, leverage, vec, positionsize, profits, lastprice); - if (retcode < 0) - return eval->Invalid("cannot calculate costbasis yet"); - std::cerr << "ValidateCostbasisTx() costbasis=" << costbasis << " costbasisInOpret=" << costbasisInOpret << std::endl; - if (costbasis != costbasisInOpret) { - //std::cerr << "ValidateBetTx() " << "incorrect costbasis value" << std::endl; - return eval->Invalid("incorrect costbasis value"); - } - - return true; -} -*/ - -// validate final tx helper -static bool ValidateFinalTx(struct CCcontract_info *cp, Eval *eval, const CTransaction & finaltx, const CTransaction & bettx) -{ - uint256 bettxid; - int64_t amount; - CPubKey pk, pricespk; - int64_t profits; - int32_t lastheight; - int64_t firstprice, costbasis, lastprice, liquidationprice, equity, fee; - int16_t leverage; - - if (finaltx.vout.size() < 3 || finaltx.vout.size() > 4) { - //std::cerr << "ValidateFinalTx()" << " incorrect vout number for final tx =" << finaltx.vout.size() << std::endl; - return eval->Invalid("incorrect vout number for final tx"); - } - - vscript_t opret; - uint8_t funcId; - if ((funcId = prices_finalopretdecode(finaltx.vout.back().scriptPubKey, bettxid, pk, lastheight, costbasis, lastprice, liquidationprice, equity, fee)) == 0) - return eval->Invalid("cannot decode opreturn for final tx"); - - // check rekt txid mining: -// if( funcId == 'R' && (finaltx.GetHash().begin()[0] != 0 || finaltx.GetHash().begin()[31] != 0) ) -// return eval->Invalid("incorrect rekt txid"); - - if (bettx.GetHash() != bettxid) - return eval->Invalid("incorrect bettx id"); - - pricespk = GetUnspendable(cp, 0); - - if (CTxOut(finaltx.vout[0].nValue, CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG) != finaltx.vout[0]) - return eval->Invalid("cannot validate vout0 in final tx with pk from opreturn"); - - if( finaltx.vout.size() == 3 && MakeCC1vout(cp->evalcode, finaltx.vout[1].nValue, pricespk) != finaltx.vout[1] ) - return eval->Invalid("cannot validate vout1 in final tx with global pk"); - - // TODO: validate exitfee for 'R' - // TODO: validate amount for 'F' - - return true; -} - -// validate prices tx function -// performed checks: -// basic tx structure (vout num) -// basic tx opret structure -// reference to the bet tx vout -// referenced bet txid in tx opret -// referenced bet tx structure -// non-final tx has only 1 cc vin -// cc vouts to self with mypubkey from opret -// cc vouts to global pk with global pk -// for bet tx that normal inputs digned with my pubkey from the opret >= cc outputs - disable betting for other pubkeys (Do we need this rule?) -// TODO: -// opret params (firstprice,positionsize...) -// costbasis calculation -// cashout balance (PricesExactAmounts) -// use the special address for 50% fees -bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) -{ - vscript_t vopret; - - if (strcmp(ASSETCHAINS_SYMBOL, "REKT0") == 0 && chainActive.Height() < 5851) - return true; - // check basic opret rules: - if (PricesCheckOpret(tx, vopret) == 0) - return eval->Invalid("tx has no prices opreturn"); - - uint8_t funcId = vopret.begin()[1]; - - CTransaction firstVinTx; - vscript_t firstVinTxOpret; - bool foundFirst = false; - int32_t ccVinCount = 0; - uint32_t prevCCoutN = 0; - - // check basic rules: - - // find first cc vin and load vintx (might be either bet or add funding tx): - for (auto vin : tx.vin) { - if (cp->ismyvin(vin.scriptSig)) { - CTransaction vintx; - uint256 hashBlock; - vscript_t vintxOpret; - - if (!myGetTransaction(vin.prevout.hash, vintx, hashBlock)) - return eval->Invalid("cannot load vintx"); - - if (PricesCheckOpret(vintx, vintxOpret) == 0) { - //return eval->Invalid("cannot find prices opret in vintx"); - std::cerr << "PricesValidate() " << "cannot find prices opret in vintx" << std::endl; - } - - if (!IS_CHARINSTR(funcId, "FR") && vintxOpret.begin()[1] == 'B' && prevCCoutN == 1) { - //return eval->Invalid("cannot spend bet marker"); - std::cerr << "PricesValidate() " << " non-final tx cannot spend cc marker vout=" << prevCCoutN << std::endl; - } - - if (!foundFirst) { - prevCCoutN = vin.prevout.n; - firstVinTx = vintx; - firstVinTxOpret = vintxOpret; - foundFirst = true; - } - ccVinCount++; - } - } - if (!foundFirst) - return eval->Invalid("prices cc vin not found"); - - if (!IS_CHARINSTR(funcId, "FR") && ccVinCount > 1) {// for all prices tx except final tx only one cc vin is allowed - //return eval->Invalid("only one prices cc vin allowed for this tx"); - std::cerr << "PricesValidate() " << "only one prices cc vin allowed for this tx" << std::endl; - } - - switch (funcId) { - case 'B': // bet - return eval->Invalid("unexpected validate for bet funcid"); - - case 'A': // add funding - // check tx structure: - if (!ValidateAddFundingTx(cp, eval, tx, firstVinTx)) { - std::cerr << "PricesValidate() " << "ValidateAddFundingTx = false " << eval->state.GetRejectReason() << std::endl; - return false; // invalid state is already set in the func - } - - if (firstVinTxOpret.begin()[1] == 'B') { - if (!ValidateBetTx(cp, eval, firstVinTx)) {// check tx structure - std::cerr << "PricesValidate() " << "funcId=A ValidatebetTx = false " << eval->state.GetRejectReason() << std::endl; - return false; // invalid state is already set in the func - } - } - - if (prevCCoutN != 0) { // check spending rules - std::cerr << "PricesValidate() " << "addfunding tx incorrect vout to spend=" << prevCCoutN << std::endl; - return eval->Invalid("incorrect vintx vout to spend"); - } - break; - - /* not used: - case 'C': // set costbasis - if (!ValidateCostbasisTx(cp, eval, tx, firstVinTx)) { - //return false; - std::cerr << "PricesValidate() " << "ValidateCostbasisTx=false " << eval->state.GetRejectReason() << std::endl; - } - if (!ValidateBetTx(cp, eval, firstVinTx)) { - //return false; - std::cerr << "PricesValidate() " << "funcId=C ValidateBetTx=false " << eval->state.GetRejectReason() << std::endl; - } - if (prevoutN != 1) { // check spending rules - // return eval->Invalid("incorrect vout to spend"); - std::cerr << "PricesValidate() " << "costbasis tx incorrect vout to spend=" << prevoutN << std::endl; - } - //return eval->Invalid("test: costbasis is good"); - break; */ - - case 'F': // final tx - case 'R': - if (!ValidateFinalTx(cp, eval, tx, firstVinTx)) { - std::cerr << "PricesValidate() " << "ValidateFinalTx=false " << eval->state.GetRejectReason() << std::endl; - return false; - } - if (!ValidateBetTx(cp, eval, firstVinTx)) { - std::cerr << "PricesValidate() " << "ValidateBetTx=false " << eval->state.GetRejectReason() << std::endl; - return false; - } - if (prevCCoutN != 1) { // check spending rules - std::cerr << "PricesValidate() "<< "final tx incorrect vout to spend=" << prevCCoutN << std::endl; - return eval->Invalid("incorrect vout to spend"); - } - break; - - default: - return eval->Invalid("invalid funcid"); - } - - eval->state = CValidationState(); - return true; -} -// end of consensus code - -// helper functions for rpc calls in rpcwallet.cpp - -int64_t AddPricesInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, char *destaddr, int64_t total, int32_t maxinputs) -{ - int64_t nValue, price, totalinputs = 0; uint256 txid, hashBlock; std::vector origpubkey; CTransaction vintx; int32_t vout, n = 0; - std::vector > unspentOutputs; - - SetCCunspents(unspentOutputs, destaddr); - for (std::vector >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - //if (vout == exclvout && txid == excltxid) // exclude vout which is added directly to vins outside this function - // continue; - if (myGetTransaction(txid, vintx, hashBlock) != 0 && vout < vintx.vout.size()) - { - vscript_t vopret; - uint8_t funcId = PricesCheckOpret(vintx, vopret); - if (funcId == 'B' && vout == 1) // skip cc marker - continue; - - if ((nValue = vintx.vout[vout].nValue) >= total / maxinputs && myIsutxo_spentinmempool(ignoretxid, ignorevin, txid, vout) == 0) - { - if (total != 0 && maxinputs != 0) - mtx.vin.push_back(CTxIn(txid, vout, CScript())); - nValue = it->second.satoshis; - totalinputs += nValue; - n++; - if ((total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs)) - break; - } - } - } - return(totalinputs); -} - -// return min equity percentage depending on leverage value -// for lev=1 2% -// for lev>=100 10% -double prices_minmarginpercent(int16_t leverage) -{ - int16_t absleverage = std::abs(leverage); - if (absleverage < 100) - return (absleverage * 0.080808 + 1.9191919) / 100.0; - else - return 0.1; -} - - -UniValue prices_rawtxresult(UniValue &result, std::string rawtx, int32_t broadcastflag) -{ - CTransaction tx; - if (rawtx.size() > 0) - { - result.push_back(Pair("hex", rawtx)); - if (DecodeHexTx(tx, rawtx) != 0) - { - if (broadcastflag != 0 && myAddtomempool(tx) != 0) - RelayTransaction(tx); - result.push_back(Pair("txid", tx.GetHash().ToString())); - result.push_back(Pair("result", "success")); - } - else - result.push_back(Pair("error", "decode hex")); - } - else - result.push_back(Pair("error", "couldnt finalize CCtx")); - return(result); -} - -static std::string prices_getsourceexpression(const std::vector &vec) { - - std::string expr; - - for (int32_t i = 0; i < vec.size(); i++) - { - char name[65]; - std::string operand; - uint16_t opcode = vec[i]; - int32_t value = (opcode & (KOMODO_MAXPRICES - 1)); // index or weight - - switch (opcode & KOMODO_PRICEMASK) - { - case 0: // indices - komodo_pricename(name, value); - operand = std::string(name); - break; - - case PRICES_WEIGHT: // multiply by weight and consume top of stack by updating price - operand = std::to_string(value); - break; - - case PRICES_MULT: // "*" - operand = std::string("*"); - break; - - case PRICES_DIV: // "/" - operand = std::string("/"); - break; - - case PRICES_INV: // "!" - operand = std::string("!"); - break; - - case PRICES_MDD: // "*//" - operand = std::string("*//"); - break; - - case PRICES_MMD: // "**/" - operand = std::string("**/"); - break; - - case PRICES_MMM: // "***" - operand = std::string("***"); - break; - - case PRICES_DDD: // "///" - operand = std::string("///"); - break; - - default: - return "invalid opcode"; - break; - } - - if (expr.size() > 0) - expr += std::string(", "); - expr += operand; - } - return expr; -} - -// helper functions to get synthetic expression reduced: - -// return s true and needed operand count if string is opcode -static bool prices_isopcode(const std::string &s, int &need) -{ - if (s == "!") { - need = 1; - return true; - } - else if (s == "*" || s == "/") { - need = 2; - return true; - } - else if (s == "***" || s == "///" || s == "*//" || s == "**/") { - need = 3; - return true; - } - else - return false; -} - -// split pair onto two quotes divided by "_" -static void prices_splitpair(const std::string &pair, std::string &upperquote, std::string &bottomquote) -{ - size_t pos = pair.find('_'); // like BTC_USD - if (pos != std::string::npos) { - upperquote = pair.substr(0, pos); - bottomquote = pair.substr(pos + 1); - } - else { - upperquote = pair; - bottomquote = ""; - } - //std::cerr << "prices_splitpair: upperquote=" << upperquote << " bottomquote=" << bottomquote << std::endl; -} - -// invert pair like BTS_USD -> USD_BTC -static std::string prices_invertpair(const std::string &pair) -{ - std::string upperquote, bottomquote; - prices_splitpair(pair, upperquote, bottomquote); - return bottomquote + std::string("_") + upperquote; -} - -// invert pairs in operation accordingly to "/" operator, convert operator to * or *** -static void prices_invertoperation(const std::vector &vexpr, int p, std::vector &voperation) -{ - int need; - - voperation.clear(); - if (prices_isopcode(vexpr[p], need)) { - if (need > 1) { - if (need == 2) { - voperation.push_back(vexpr[p - 2]); - if (vexpr[p] == "/") - voperation.push_back(prices_invertpair(vexpr[p - 1])); - else - voperation.push_back(vexpr[p - 1]); - voperation.push_back("*"); - } - - if (need == 3) { - int i; - std::string::const_iterator c; - for (c = vexpr[p].begin(), i = -3; c != vexpr[p].end(); c++, i++) { - if (*c == '/') - voperation.push_back(prices_invertpair(vexpr[p + i])); - else - voperation.push_back(vexpr[p + i]); - } - voperation.push_back("***"); - } - } - else if (vexpr[p] == "!") { - voperation.push_back(prices_invertpair(vexpr[p - 1])); - // do not add operator - } - } - - //std::cerr << "prices_invert inverted="; - //for (auto v : voperation) std::cerr << v << " "; - //std::cerr << std::endl; -} - -// reduce pairs in the operation, change or remove opcode if reduced -static int prices_reduceoperands(std::vector &voperation) -{ - int opcount = voperation.size() - 1; - int need = opcount; - //std::cerr << "prices_reduceoperands begin need=" << need << std::endl; - - while (true) { - int i; - //std::cerr << "prices_reduceoperands opcount=" << opcount << std::endl; - for (i = 0; i < opcount; i++) { - std::string upperquote, bottomquote; - bool breaktostart = false; - - //std::cerr << "prices_reduceoperands voperation[i]=" << voperation[i] << " i=" << i << std::endl; - prices_splitpair(voperation[i], upperquote, bottomquote); - if (upperquote == bottomquote) { - std::cerr << "prices_reduceoperands erasing i=" << i << std::endl; - voperation.erase(voperation.begin() + i); - opcount--; - //std::cerr << "prices_reduceoperands erased, size=" << voperation.size() << std::endl; - - if (voperation.size() > 0 && voperation.back() == "*") - voperation.pop_back(); - breaktostart = true; - break; - } - - - int j; - for (j = i + 1; j < opcount; j++) { - - //std::cerr << "prices_reduceoperands voperation[j]=" << voperation[j] << " j=" << j << std::endl; - - std::string upperquotej, bottomquotej; - prices_splitpair(voperation[j], upperquotej, bottomquotej); - if (upperquote == bottomquotej || bottomquote == upperquotej) { - if (upperquote == bottomquotej) - voperation[i] = upperquotej + "_" + bottomquote; - else - voperation[i] = upperquote + "_" + bottomquotej; - //std::cerr << "prices_reduceoperands erasing j=" << j << std::endl; - voperation.erase(voperation.begin() + j); - opcount--; - //std::cerr << "prices_reduceoperands erased, size=" << voperation.size() << std::endl; - - need--; - if (voperation.back() == "***") { - voperation.pop_back(); - voperation.push_back("*"); // convert *** to * - } - else if (voperation.back() == "*") { - voperation.pop_back(); // convert * to nothing - } - breaktostart = true; - break; - } - } - if (breaktostart) - break; - } - if (i >= opcount) // all seen - break; - } - - //std::cerr << "prices_reduceoperands end need=" << need << std::endl; - return need; -} - -// substitute reduced operation in vectored expr -static void prices_substitutereduced(std::vector &vexpr, int p, std::vector voperation) -{ - int need; - if (prices_isopcode(vexpr[p], need)) { - vexpr.erase(vexpr.begin() + p - need, vexpr.begin() + p + 1); - vexpr.insert(vexpr.begin() + p - need, voperation.begin(), voperation.end()); - } -} - -// try to reduce synthetic expression by substituting "BTC_USD, BTC_EUR, 30, /" with "EUR_USD, 30" etc -static std::string prices_getreducedexpr(const std::string &expr) -{ - std::string reduced; - - std::vector vexpr; - SplitStr(expr, vexpr); - - for (size_t i = 0; i < vexpr.size(); i++) { - int need; - - if (prices_isopcode(vexpr[i], need)) { - std::vector voperation; - prices_invertoperation(vexpr, i, voperation); - if (voperation.size() > 0) { - int reducedneed = prices_reduceoperands(voperation); - if (reducedneed < need) { - prices_substitutereduced(vexpr, i, voperation); - } - } - } - } - - for (size_t i = 0; i < vexpr.size(); i++) { - if (reduced.size() > 0) - reduced += std::string(", "); - reduced += vexpr[i]; - } - - //std::cerr << "reduced=" << reduced << std::endl; - return reduced; -} - -// parse synthetic expression into vector of codes -int32_t prices_syntheticvec(std::vector &vec, std::vector synthetic) -{ - int32_t i, need, ind, depth = 0; std::string opstr; uint16_t opcode, weight; - if (synthetic.size() == 0) { - std::cerr << "prices_syntheticvec() expression is empty" << std::endl; - return(-1); - } - for (i = 0; i < synthetic.size(); i++) - { - need = 0; - opstr = synthetic[i]; - if (opstr == "*") - opcode = PRICES_MULT, need = 2; - else if (opstr == "/") - opcode = PRICES_DIV, need = 2; - else if (opstr == "!") - opcode = PRICES_INV, need = 1; - else if (opstr == "**/") - opcode = PRICES_MMD, need = 3; - else if (opstr == "*//") - opcode = PRICES_MDD, need = 3; - else if (opstr == "***") - opcode = PRICES_MMM, need = 3; - else if (opstr == "///") - opcode = PRICES_DDD, need = 3; - else if (!is_weight_str(opstr) && (ind = komodo_priceind(opstr.c_str())) >= 0) - opcode = ind, need = 0; - else if ((weight = atoi(opstr.c_str())) > 0 && weight < KOMODO_MAXPRICES) - { - opcode = PRICES_WEIGHT | weight; - need = 1; - } - else { - std::cerr << "prices_syntheticvec() incorrect opcode=" << opstr << std::endl; - return(-2); - } - if (depth < need) { - std::cerr << "prices_syntheticvec() incorrect not enough operands for opcode=" << opstr << std::endl; - return(-3); - } - depth -= need; - ///std::cerr << "prices_syntheticvec() opcode=" << opcode << " opstr=" << opstr << " need=" << need << " depth=" << depth << std::endl; - if ((opcode & KOMODO_PRICEMASK) != PRICES_WEIGHT) { // skip weight - depth++; // increase operands count - ///std::cerr << "depth++=" << depth << std::endl; - } - if (depth > 3) { - std::cerr << "prices_syntheticvec() too many operands, last=" << opstr << std::endl; - return(-4); - } - vec.push_back(opcode); - } - if (depth != 0) - { - fprintf(stderr, "prices_syntheticvec() depth.%d not empty\n", depth); - return(-5); - } - return(0); -} - -// calculates price for synthetic expression -int64_t prices_syntheticprice(std::vector vec, int32_t height, int32_t minmax, int16_t leverage) -{ - int32_t i, value, errcode, depth, retval = -1; - uint16_t opcode; - int64_t *pricedata, pricestack[4], a, b, c; - - mpz_t mpzTotalPrice, mpzPriceValue, mpzDen, mpzA, mpzB, mpzC, mpzResult; - - mpz_init(mpzTotalPrice); - mpz_init(mpzPriceValue); - mpz_init(mpzDen); - - mpz_init(mpzA); - mpz_init(mpzB); - mpz_init(mpzC); - mpz_init(mpzResult); - - pricedata = (int64_t *)calloc(sizeof(*pricedata) * 3, 1 + PRICES_DAYWINDOW * 2 + PRICES_SMOOTHWIDTH); - depth = errcode = 0; - mpz_set_si(mpzTotalPrice, 0); - mpz_set_si(mpzDen, 0); - - for (i = 0; i < vec.size(); i++) - { - opcode = vec[i]; - value = (opcode & (KOMODO_MAXPRICES - 1)); // index or weight - - mpz_set_ui(mpzResult, 0); // clear result to test overflow (see below) - - //std::cerr << "prices_syntheticprice" << " i=" << i << " mpzTotalPrice=" << mpz_get_si(mpzTotalPrice) << " value=" << value << " depth=" << depth << " opcode&KOMODO_PRICEMASK=" << (opcode & KOMODO_PRICEMASK) <= 0) - { - //std::cerr << "prices_syntheticprice" << " pricedata[0]=" << pricedata[0] << " pricedata[1]=" << pricedata[1] << " pricedata[2]=" << pricedata[2] << std::endl; - // push price to the prices stack - /*if (!minmax) - pricestack[depth] = pricedata[2]; // use smoothed value if we are over 24h - else - { - // if we are within 24h use min or max price - if (leverage > 0) - pricestack[depth] = (pricedata[1] > pricedata[2]) ? pricedata[1] : pricedata[2]; // MAX - else - pricestack[depth] = (pricedata[1] < pricedata[2]) ? pricedata[1] : pricedata[2]; // MIN - }*/ - pricestack[depth] = pricedata[2]; - } - else - errcode = -1; - - if (pricestack[depth] == 0) - errcode = -14; - - depth++; - break; - - case PRICES_WEIGHT: // multiply by weight and consume top of stack by updating price - if (depth == 1) { - depth--; - // price += pricestack[0] * value; - mpz_set_si(mpzPriceValue, pricestack[0]); - mpz_mul_si(mpzPriceValue, mpzPriceValue, value); - mpz_add(mpzTotalPrice, mpzTotalPrice, mpzPriceValue); // accumulate weight's value - - // den += value; - mpz_add_ui(mpzDen, mpzDen, (uint64_t)value); // accumulate weight's value - } - else - errcode = -2; - break; - - case PRICES_MULT: // "*" - if (depth >= 2) { - b = pricestack[--depth]; - a = pricestack[--depth]; - // pricestack[depth++] = (a * b) / SATOSHIDEN; - mpz_set_si(mpzA, a); - mpz_set_si(mpzB, b); - mpz_mul(mpzResult, mpzA, mpzB); - mpz_tdiv_q_ui(mpzResult, mpzResult, SATOSHIDEN); - pricestack[depth++] = mpz_get_si(mpzResult); - - } - else - errcode = -3; - break; - - case PRICES_DIV: // "/" - if (depth >= 2) { - b = pricestack[--depth]; - a = pricestack[--depth]; - // pricestack[depth++] = (a * SATOSHIDEN) / b; - mpz_set_si(mpzA, a); - mpz_set_si(mpzB, b); - mpz_mul_ui(mpzResult, mpzA, SATOSHIDEN); - mpz_tdiv_q(mpzResult, mpzResult, mpzB); - pricestack[depth++] = mpz_get_si(mpzResult); - } - else - errcode = -4; - break; - - case PRICES_INV: // "!" - if (depth >= 1) { - a = pricestack[--depth]; - // pricestack[depth++] = (SATOSHIDEN * SATOSHIDEN) / a; - mpz_set_si(mpzA, a); - mpz_set_ui(mpzResult, SATOSHIDEN); - mpz_mul_ui(mpzResult, mpzResult, SATOSHIDEN); - mpz_tdiv_q(mpzResult, mpzResult, mpzA); - pricestack[depth++] = mpz_get_si(mpzResult); - } - else - errcode = -5; - break; - - case PRICES_MDD: // "*//" - if (depth >= 3) { - c = pricestack[--depth]; - b = pricestack[--depth]; - a = pricestack[--depth]; - // pricestack[depth++] = (((a * SATOSHIDEN) / b) * SATOSHIDEN) / c; - mpz_set_si(mpzA, a); - mpz_set_si(mpzB, b); - mpz_set_si(mpzC, c); - mpz_mul_ui(mpzResult, mpzA, SATOSHIDEN); - mpz_tdiv_q(mpzResult, mpzResult, mpzB); - mpz_mul_ui(mpzResult, mpzResult, SATOSHIDEN); - mpz_tdiv_q(mpzResult, mpzResult, mpzC); - pricestack[depth++] = mpz_get_si(mpzResult); - } - else - errcode = -6; - break; - - case PRICES_MMD: // "**/" - if (depth >= 3) { - c = pricestack[--depth]; - b = pricestack[--depth]; - a = pricestack[--depth]; - // pricestack[depth++] = (a * b) / c; - mpz_set_si(mpzA, a); - mpz_set_si(mpzB, b); - mpz_set_si(mpzC, c); - mpz_mul(mpzResult, mpzA, mpzB); - mpz_tdiv_q(mpzResult, mpzResult, mpzC); - pricestack[depth++] = mpz_get_si(mpzResult); - } - else - errcode = -7; - break; - - case PRICES_MMM: // "***" - if (depth >= 3) { - c = pricestack[--depth]; - b = pricestack[--depth]; - a = pricestack[--depth]; - // pricestack[depth++] = (((a * b) / SATOSHIDEN ) * c) / SATOSHIDEN; - mpz_set_si(mpzA, a); - mpz_set_si(mpzB, b); - mpz_set_si(mpzC, c); - mpz_mul(mpzResult, mpzA, mpzB); - mpz_tdiv_q_ui(mpzResult, mpzResult, SATOSHIDEN); - mpz_mul(mpzResult, mpzResult, mpzC); - mpz_tdiv_q_ui(mpzResult, mpzResult, SATOSHIDEN); - pricestack[depth++] = mpz_get_si(mpzResult); - } - else - errcode = -8; - break; - - case PRICES_DDD: // "///" - if (depth >= 3) { - c = pricestack[--depth]; - b = pricestack[--depth]; - a = pricestack[--depth]; - //pricestack[depth++] = (((((SATOSHIDEN * SATOSHIDEN) / a) * SATOSHIDEN) / b) * SATOSHIDEN) / c; - mpz_set_si(mpzA, a); - mpz_set_si(mpzB, b); - mpz_set_si(mpzC, c); - mpz_set_ui(mpzResult, SATOSHIDEN); - mpz_mul_ui(mpzResult, mpzResult, SATOSHIDEN); - mpz_tdiv_q(mpzResult, mpzResult, mpzA); - mpz_mul_ui(mpzResult, mpzResult, SATOSHIDEN); - mpz_tdiv_q(mpzResult, mpzResult, mpzB); - mpz_mul_ui(mpzResult, mpzResult, SATOSHIDEN); - mpz_tdiv_q(mpzResult, mpzResult, mpzC); - pricestack[depth++] = mpz_get_si(mpzResult); - } - else - errcode = -9; - break; - - default: - errcode = -10; - break; - } - - // std::cerr << "prices_syntheticprice test mpzResult=" << mpz_get_si(mpzResult) << std::endl; - // check overflow: - if (mpz_cmp_si(mpzResult, std::numeric_limits::max()) > 0) { - errcode = -13; - break; - } - - if (errcode != 0) - break; - - // if( depth > 0 ) - // std::cerr << "prices_syntheticprice top pricestack[depth-1=" << depth-1 << "]=" << pricestack[depth-1] << std::endl; - // else - // std::cerr << "prices_syntheticprice pricestack empty" << std::endl; - - } - free(pricedata); - mpz_clear(mpzResult); - mpz_clear(mpzA); - mpz_clear(mpzB); - mpz_clear(mpzC); - - if( mpz_get_si(mpzDen) != 0 ) - mpz_tdiv_q(mpzTotalPrice, mpzTotalPrice, mpzDen); // price / den - - int64_t den = mpz_get_si(mpzDen); - int64_t priceIndex = mpz_get_si(mpzTotalPrice); - - mpz_clear(mpzDen); - mpz_clear(mpzTotalPrice); - mpz_clear(mpzPriceValue); - - if (errcode != 0) - std::cerr << "prices_syntheticprice errcode in switch=" << errcode << std::endl; - - if( errcode == -1 ) { - std::cerr << "prices_syntheticprice error getting price (could be end of chain)" << std::endl; - return errcode; - } - - if (errcode == -13) { - std::cerr << "prices_syntheticprice overflow in price" << std::endl; - return errcode; - } - if (errcode == -14) { - std::cerr << "prices_syntheticprice price is zero, not enough historic data yet" << std::endl; - return errcode; - } - if (den == 0) { - std::cerr << "prices_syntheticprice den==0 return err=-11" << std::endl; - return(-11); - } - else if (depth != 0) { - std::cerr << "prices_syntheticprice depth!=0 err=-12" << std::endl; - return(-12); - } - else if (errcode != 0) { - std::cerr << "prices_syntheticprice err=" << errcode << std::endl; - return(errcode); - } -// std::cerr << "prices_syntheticprice priceIndex=totalprice/den=" << priceIndex << " den=" << den << std::endl; - - return priceIndex; -} - -// calculates costbasis and profit/loss for the bet -int32_t prices_syntheticprofits(int64_t &costbasis, int32_t firstheight, int32_t height, int16_t leverage, std::vector vec, int64_t positionsize, int64_t &profits, int64_t &outprice) -{ - int64_t price; -#ifndef TESTMODE - const int32_t COSTBASIS_PERIOD = PRICES_DAYWINDOW; -#else - const int32_t COSTBASIS_PERIOD = 7; -#endif - - - if (height < firstheight) { - fprintf(stderr, "requested height is lower than bet firstheight.%d\n", height); - return -1; - } - - int32_t minmax = (height < firstheight + COSTBASIS_PERIOD); // if we are within 24h then use min or max value - - if ((price = prices_syntheticprice(vec, height, minmax, leverage)) < 0) - { - fprintf(stderr, "error getting synthetic price at height.%d\n", height); - return -1; - } - - // clear lowest positions: - //price /= PRICES_POINTFACTOR; - //price *= PRICES_POINTFACTOR; - outprice = price; - - if (minmax) { // if we are within day window, set temp costbasis to max (or min) price value - if (leverage > 0 && price > costbasis) { - costbasis = price; // set temp costbasis - //std::cerr << "prices_syntheticprofits() minmax costbasis=" << costbasis << std::endl; - } - else if (leverage < 0 && (costbasis == 0 || price < costbasis)) { - costbasis = price; - //std::cerr << "prices_syntheticprofits() minmax costbasis=" << costbasis << std::endl; - } - //else { //-> use the previous value - // std::cerr << "prices_syntheticprofits() unchanged costbasis=" << costbasis << " price=" << price << " leverage=" << leverage << std::endl; - //} - } - else { - //if (height == firstheight + COSTBASIS_PERIOD) { - // if costbasis not set, just set it - //costbasis = price; - - // use calculated minmax costbasis - //std::cerr << "prices_syntheticprofits() use permanent costbasis=" << costbasis << " at height=" << height << std::endl; - //} - } - - // normalize to 10,000,000 to prevent underflow - //profits = costbasis > 0 ? (((price / PRICES_POINTFACTOR * PRICES_NORMFACTOR) / costbasis) - PRICES_NORMFACTOR / PRICES_POINTFACTOR) * PRICES_POINTFACTOR : 0; - //double dprofits = costbasis > 0 ? ((double)price / (double)costbasis - 1) : 0; - - //std::cerr << "prices_syntheticprofits() test value1 (price/PRICES_POINTFACTOR * PRICES_NORMFACTOR)=" << (price / PRICES_POINTFACTOR * PRICES_NORMFACTOR) << std::endl; - //std::cerr << "prices_syntheticprofits() test value2 (price/PRICES_POINTFACTOR * PRICES_NORMFACTOR)/costbasis=" << (costbasis != 0 ? (price / PRICES_POINTFACTOR * PRICES_NORMFACTOR)/costbasis : 0) << std::endl; - - //std::cerr << "prices_syntheticprofits() fractional profits=" << profits << std::endl; - //std::cerr << "prices_syntheticprofits() profits double=" << (double)price / (double)costbasis -1.0 << std::endl; - //double dprofits = (double)price / (double)costbasis - 1.0; - - //profits *= ((int64_t)leverage * (int64_t)positionsize); - //profits /= (int64_t)PRICES_NORMFACTOR; // de-normalize - - //dprofits *= ((double)leverage * (double)positionsize); - - //dprofits *= leverage * positionsize; - // profits = dprofits; - //std::cerr << "prices_syntheticprofits() dprofits=" << dprofits << std::endl; - - if (costbasis > 0) { - mpz_t mpzProfits; - mpz_t mpzCostbasis; - mpz_t mpzPrice; - mpz_t mpzLeverage; - - mpz_init(mpzProfits); - mpz_init(mpzCostbasis); - mpz_init(mpzPrice); - mpz_init(mpzLeverage); - - mpz_set_si(mpzCostbasis, costbasis); - mpz_set_si(mpzPrice, price); - mpz_mul_ui(mpzPrice, mpzPrice, SATOSHIDEN); // (price*SATOSHIDEN) - - mpz_tdiv_q(mpzProfits, mpzPrice, mpzCostbasis); // profits = (price*SATOSHIDEN)/costbasis // normalization - mpz_sub_ui(mpzProfits, mpzProfits, SATOSHIDEN); // profits -= SATOSHIDEN - - mpz_set_si(mpzLeverage, leverage); - mpz_mul(mpzProfits, mpzProfits, mpzLeverage); // profits *= leverage - mpz_mul_ui(mpzProfits, mpzProfits, positionsize); // profits *= positionsize - mpz_tdiv_q_ui(mpzProfits, mpzProfits, SATOSHIDEN); // profits /= SATOSHIDEN // de-normalization - - profits = mpz_get_si(mpzProfits); - - mpz_clear(mpzLeverage); - mpz_clear(mpzProfits); - mpz_clear(mpzCostbasis); - mpz_clear(mpzPrice); - - } - else - profits = 0; - - //std::cerr << "prices_syntheticprofits() profits=" << profits << std::endl; - return 0; // (positionsize + addedbets + profits); -} - -// makes result json object -void prices_betjson(UniValue &result, std::vector bets, int16_t leverage, int32_t endheight, int64_t lastprice) -{ - - UniValue resultbets(UniValue::VARR); - int64_t totalposition = 0; - int64_t totalprofits = 0; - - for (auto b : bets) { - UniValue entry(UniValue::VOBJ); - entry.push_back(Pair("positionsize", ValueFromAmount(b.positionsize))); - entry.push_back(Pair("profits", ValueFromAmount(b.profits))); - entry.push_back(Pair("costbasis", ValueFromAmount(b.costbasis))); - entry.push_back(Pair("firstheight", b.firstheight)); - resultbets.push_back(entry); - totalposition += b.positionsize; - totalprofits += b.profits; - } - int64_t equity = totalposition + totalprofits; - - result.push_back(Pair("bets", resultbets)); - result.push_back(Pair("leverage", (int64_t)leverage)); - result.push_back(Pair("TotalPositionSize", ValueFromAmount(totalposition))); - result.push_back(Pair("TotalProfits", ValueFromAmount(totalprofits))); - result.push_back(Pair("equity", ValueFromAmount(equity))); - result.push_back(Pair("LastPrice", ValueFromAmount(lastprice))); - result.push_back(Pair("LastHeight", endheight)); -} - -// retrieves costbasis from a tx spending bettx vout1 (deprecated) -int64_t prices_costbasis(CTransaction bettx, uint256 &txidCostbasis) -{ - int64_t costbasis = 0; - // if vout1 is spent, follow and extract costbasis from opreturn - //uint8_t prices_costbasisopretdecode(CScript scriptPubKey,uint256 &bettxid,CPubKey &pk,int32_t &height,int64_t &costbasis) - //uint256 txidCostbasis; - int32_t vini; - int32_t height; - txidCostbasis = zeroid; -/* - if (CCgetspenttxid(txidCostbasis, vini, height, bettx.GetHash(), 1) < 0) { - std::cerr << "prices_costbasis() no costbasis txid found" << std::endl; - return 0; - } - - CTransaction txCostbasis; - uint256 hashBlock; - uint256 bettxid; - CPubKey pk; - bool isLoaded = false; - uint8_t funcId = 0; - - if ((isLoaded = myGetTransaction(txidCostbasis, txCostbasis, hashBlock)) && - txCostbasis.vout.size() > 0 && - (funcId = prices_costbasisopretdecode(txCostbasis.vout.back().scriptPubKey, bettxid, pk, height, costbasis)) != 0) { - return costbasis; - } - - std::cerr << "prices_costbasis() cannot load costbasis tx or decode opret" << " isLoaded=" << isLoaded << " funcId=" << (int)funcId << std::endl; */ - return 0; -} - -// enumerates and retrieves added bets, returns the last baton txid -int64_t prices_enumaddedbets(uint256 &batontxid, std::vector &bets, uint256 bettxid) -{ - int64_t addedBetsTotal = 0; - int32_t vini; - int32_t height; - int32_t retcode; - - batontxid = bettxid; // initially set to the source bet tx - uint256 sourcetxid = bettxid; - - // iterate through batons, adding up vout1 -> addedbets - while ((retcode = CCgetspenttxid(batontxid, vini, height, sourcetxid, 0)) == 0) { - - CTransaction txBaton; - CBlockIndex blockIdx; - uint256 bettxidInOpret; - CPubKey pk; - bool isLoaded = false; - uint8_t funcId = 0; - int64_t amount; - EvalRef eval; - - if ((isLoaded = eval->GetTxConfirmed(batontxid, txBaton, blockIdx)) && - blockIdx.IsValid() && - txBaton.vout.size() > 0 && - (funcId = prices_addopretdecode(txBaton.vout.back().scriptPubKey, bettxidInOpret, pk, amount)) != 0) - { - OneBetData added; - - addedBetsTotal += amount; - added.positionsize = amount; - added.firstheight = blockIdx.nHeight; //TODO: check if this is correct (to get height from the block not from the opret) - bets.push_back(added); - //std::cerr << "prices_batontxid() added amount=" << amount << std::endl; - } - else { - std::cerr << "prices_batontxid() cannot load or decode add bet tx, isLoaded=" << isLoaded << " funcId=" << (int)funcId << std::endl; - return -1; - } - sourcetxid = batontxid; - } - - return(addedBetsTotal); -} - -// pricesbet rpc impl: make betting tx -UniValue PricesBet(int64_t txfee, int64_t amount, int16_t leverage, std::vector synthetic) -{ - int32_t nextheight = komodo_nextheight(); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextheight); UniValue result(UniValue::VOBJ); - struct CCcontract_info *cp, C; - CPubKey pricespk, mypk; - int64_t betamount, firstprice = 0; - std::vector vec; - //char myaddr[64]; - std::string rawtx; - - if (leverage > PRICES_MAXLEVERAGE || leverage < -PRICES_MAXLEVERAGE) - { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "leverage too big")); - return(result); - } - cp = CCinit(&C, EVAL_PRICES); - if (txfee == 0) - txfee = PRICES_TXFEE; - mypk = pubkey2pk(Mypubkey()); - pricespk = GetUnspendable(cp, 0); - //GetCCaddress(cp, myaddr, mypk); - if (prices_syntheticvec(vec, synthetic) < 0 || (firstprice = prices_syntheticprice(vec, nextheight - 1, 1, leverage)) < 0 || vec.size() == 0 || vec.size() > 4096) - { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "invalid synthetic")); - return(result); - } - - if (!prices_isacceptableamount(vec, amount, leverage)) { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "too big amount and leverage")); - return(result); - } - - if (AddNormalinputs(mtx, mypk, amount + 4 * txfee, 64) >= amount + 4 * txfee) - { - betamount = PRICES_SUBREVSHAREFEE(amount); - - /*if( amount - betamount < PRICES_REVSHAREDUST) { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "bet amount too small")); - return(result); - }*/ - - - mtx.vout.push_back(MakeCC1vout(cp->evalcode, txfee, mypk)); // vout0 baton for total funding - // mtx.vout.push_back(MakeCC1vout(cp->evalcode, (amount - betamount) + 2 * txfee, pricespk)); // vout1, when spent, costbasis is set - mtx.vout.push_back(MakeCC1vout(cp->evalcode, txfee, pricespk)); // vout1 cc marker (NVOUT_CCMARKER) - mtx.vout.push_back(MakeCC1vout(cp->evalcode, betamount, pricespk)); // vout2 betamount - mtx.vout.push_back(CTxOut(txfee, CScript() << ParseHex(HexStr(pricespk)) << OP_CHECKSIG)); // vout3 normal marker NVOUT_NORMALMARKER - TODO: remove it as we have cc marker now, when move to the new chain - if ( ASSETCHAINS_EARLYTXIDCONTRACT == EVAL_PRICES && KOMODO_EARLYTXID_SCRIPTPUB.size() == 0 ) - { - // Lock here, as in validation we cannot call lock in the function itself. - // may not be needed as the validation call to update the global, is called in a LOCK already, and it can only update there and here. - LOCK(cs_main); - GetKomodoEarlytxidScriptPub(); - } - mtx.vout.push_back(CTxOut(amount-betamount, KOMODO_EARLYTXID_SCRIPTPUB)); - //test: mtx.vout.push_back(CTxOut(amount - betamount, CScript() << ParseHex("037c803ec82d12da939ac04379bbc1130a9065c53d8244a61eece1db942cf0efa7") << OP_CHECKSIG)); // vout4 test revshare fee - - rawtx = FinalizeCCTx(0, cp, mtx, mypk, txfee, prices_betopret(mypk, nextheight - 1, amount, leverage, firstprice, vec, zeroid)); - return(prices_rawtxresult(result, rawtx, 0)); - } - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "not enough funds")); - return(result); -} - -// pricesaddfunding rpc impl: add yet another bet -UniValue PricesAddFunding(int64_t txfee, uint256 bettxid, int64_t amount) -{ - int32_t nextheight = komodo_nextheight(); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextheight); UniValue result(UniValue::VOBJ); - struct CCcontract_info *cp, C; - CTransaction bettx; - CPubKey pricespk, mypk, pk; - int64_t positionsize, betamount, firstprice; - int32_t firstheight; - std::vector vecparsed; - uint256 batontxid, tokenid, hashBlock; - int16_t leverage = 0; - std::string rawtx; - //char myaddr[64]; - - cp = CCinit(&C, EVAL_PRICES); - if (txfee == 0) - txfee = PRICES_TXFEE; - mypk = pubkey2pk(Mypubkey()); - pricespk = GetUnspendable(cp, 0); - - if (!myGetTransaction(bettxid, bettx, hashBlock) || - bettx.vout.size() <= 3 || - hashBlock.IsNull() || - prices_betopretdecode(bettx.vout.back().scriptPubKey, pk, firstheight, positionsize, leverage, firstprice, vecparsed, tokenid) != 'B') { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "invalid bet tx")); - return(result); - } - - if (!prices_isacceptableamount(vecparsed, amount, leverage)) { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "too big amount and leverage")); - return(result); - } - - if (AddNormalinputs(mtx, mypk, amount + 2*txfee, 64) >= amount + 2*txfee) - { - betamount = PRICES_SUBREVSHAREFEE(amount); - /*if (amount - betamount < PRICES_REVSHAREDUST) { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "bet amount too small")); - return(result); - }*/ - - std::vector bets; - if (prices_enumaddedbets(batontxid, bets, bettxid) >= 0) - { - mtx.vin.push_back(CTxIn(batontxid, 0, CScript())); - mtx.vout.push_back(MakeCC1vout(cp->evalcode, txfee, mypk)); // vout0 baton for total funding - mtx.vout.push_back(MakeCC1vout(cp->evalcode, betamount, pricespk)); // vout1 added amount - - if (ASSETCHAINS_EARLYTXIDCONTRACT == EVAL_PRICES && KOMODO_EARLYTXID_SCRIPTPUB.size() == 0) - { - // Lock here, as in validation we cannot call lock in the function itself. - // may not be needed as the validation call to update the global, is called in a LOCK already, and it can only update there and here. - LOCK(cs_main); - GetKomodoEarlytxidScriptPub(); - } - mtx.vout.push_back(CTxOut(amount - betamount, KOMODO_EARLYTXID_SCRIPTPUB)); - // test: mtx.vout.push_back(CTxOut(amount - betamount, CScript() << ParseHex("037c803ec82d12da939ac04379bbc1130a9065c53d8244a61eece1db942cf0efa7") << OP_CHECKSIG)); //vout2 test revshare fee - - rawtx = FinalizeCCTx(0, cp, mtx, mypk, txfee, prices_addopret(bettxid, mypk, amount)); - return(prices_rawtxresult(result, rawtx, 0)); - } - else - { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "couldnt find batonttxid")); - return(result); - } - } - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "not enough funds")); - return(result); -} - -// scan chain from the initial bet's first position upto the chain tip and calculate bet's costbasises and profits, breaks if rekt detected -int32_t prices_scanchain(std::vector &bets, int16_t leverage, std::vector vec, int64_t &lastprice, int32_t &endheight) { - - if (bets.size() == 0) - return -1; - - bool stop = false; - for (int32_t height = bets[0].firstheight+1; ; height++) // the last datum for 24h is the costbasis value - { - int64_t totalposition = 0; - int64_t totalprofits = 0; - - // scan upto the chain tip - for (int i = 0; i < bets.size(); i++) { - - if (height > bets[i].firstheight) { - - int32_t retcode = prices_syntheticprofits(bets[i].costbasis, bets[i].firstheight, height, leverage, vec, bets[i].positionsize, bets[i].profits, lastprice); - if (retcode < 0) { - std::cerr << "prices_scanchain() prices_syntheticprofits returned -1, finishing..." << std::endl; - stop = true; - break; - } - totalposition += bets[i].positionsize; - totalprofits += bets[i].profits; - } - } - - if (stop) - break; - - endheight = height; - int64_t equity = totalposition + totalprofits; - if (equity <= (int64_t)((double)totalposition * prices_minmarginpercent(leverage))) - { // we are in loss - break; - } - } - - return 0; -} - -// pricescostbasis rpc impl: set cost basis (open price) for the bet (deprecated) -UniValue PricesSetcostbasis(int64_t txfee, uint256 bettxid) -{ - int32_t nextheight = komodo_nextheight(); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextheight); - UniValue result(UniValue::VOBJ); - struct CCcontract_info *cp, C; CTransaction bettx; uint256 hashBlock, batontxid, tokenid; - int64_t myfee, positionsize = 0, addedbets, firstprice = 0, lastprice, profits = 0, costbasis = 0, equity; - int32_t i, firstheight = 0, height, numvouts; int16_t leverage = 0; - std::vector vec; - CPubKey pk, mypk, pricespk; std::string rawtx; -/* - cp = CCinit(&C, EVAL_PRICES); - if (txfee == 0) - txfee = PRICES_TXFEE; - - mypk = pubkey2pk(Mypubkey()); - pricespk = GetUnspendable(cp, 0); - if (myGetTransaction(bettxid, bettx, hashBlock) != 0 && (numvouts = bettx.vout.size()) > 3) - { - if (prices_betopretdecode(bettx.vout[numvouts - 1].scriptPubKey, pk, firstheight, positionsize, leverage, firstprice, vec, tokenid) == 'B') - { - if (nextheight <= firstheight + PRICES_DAYWINDOW + 1) { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "cannot calculate costbasis yet")); - return(result); - } - - addedbets = prices_enumaddedbets(batontxid, bettx, bettxid); - mtx.vin.push_back(CTxIn(bettxid, 1, CScript())); // spend vin1 with betamount - //for (i = 0; i < PRICES_DAYWINDOW + 1; i++) // the last datum for 24h is the actual costbasis value - //{ - int32_t retcode = prices_syntheticprofits(costbasis, firstheight, firstheight + PRICES_DAYWINDOW, leverage, vec, positionsize, addedbets, profits, lastprice); - if (retcode < 0) { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "cannot calculate costbasis error getting price")); - return(result); - } - equity = positionsize + addedbets + profits; - //if (equity < 0) - //{ // we are in loss - // result.push_back(Pair("rekt", (int64_t)1)); - // result.push_back(Pair("rektheight", (int64_t)firstheight + i)); - // break; - //} - //} - //if (i == PRICES_DAYWINDOW + 1) - // result.push_back(Pair("rekt", 0)); - - prices_betjson(result, profits, costbasis, positionsize, addedbets, leverage, firstheight, firstprice, lastprice, equity); - - if (AddNormalinputs(mtx, mypk, txfee, 4) >= txfee) - { - myfee = bettx.vout[1].nValue / 10; // fee for setting costbasis - result.push_back(Pair("myfee", myfee)); - - mtx.vout.push_back(CTxOut(myfee, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - mtx.vout.push_back(MakeCC1vout(cp->evalcode, bettx.vout[1].nValue - myfee, pricespk)); - rawtx = FinalizeCCTx(0, cp, mtx, mypk, txfee, prices_costbasisopret(bettxid, mypk, firstheight + PRICES_DAYWINDOW , costbasis)); // -1 - return(prices_rawtxresult(result, rawtx, 0)); - } - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "not enough funds")); - return(result); - } - } */ - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "deprecated")); - return(result); -} - - -// pricesaddfunding rpc impl: add yet another bet -UniValue PricesRefillFund(int64_t amount) -{ - int32_t nextheight = komodo_nextheight(); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextheight); UniValue result(UniValue::VOBJ); - struct CCcontract_info *cp, C; - CPubKey pricespk, mypk, pk; - std::string rawtx; - //char myaddr[64]; - - cp = CCinit(&C, EVAL_PRICES); - const int64_t txfee = PRICES_TXFEE; - mypk = pubkey2pk(Mypubkey()); - pricespk = GetUnspendable(cp, 0); - - if (AddNormalinputs(mtx, mypk, amount + txfee, 64) >= amount + txfee) - { - mtx.vout.push_back(MakeCC1vout(cp->evalcode, amount, pricespk)); // vout1 added amount - rawtx = FinalizeCCTx(0, cp, mtx, mypk, txfee, CScript()); - return(prices_rawtxresult(result, rawtx, 0)); - - } - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "not enough funds")); - return(result); -} - - -int32_t prices_getbetinfo(uint256 bettxid, BetInfo &betinfo) -{ - CTransaction bettx; - uint256 hashBlock, batontxid, tokenid; - - if (myGetTransaction(bettxid, bettx, hashBlock) && bettx.vout.size() > 3) - { - if (hashBlock.IsNull()) - return -2; - - - // TODO: forget old tx - //CBlockIndex *bi = komodo_getblockindex(hashBlock); - //if (bi && bi->nHeight < 5342) - // return -5; - - OneBetData bet1; - if (prices_betopretdecode(bettx.vout.back().scriptPubKey, betinfo.pk, bet1.firstheight, bet1.positionsize, betinfo.leverage, betinfo.firstprice, betinfo.vecparsed, betinfo.tokenid) == 'B') - { - uint256 finaltxid; - int32_t vini; - int32_t finaltxheight; //, endheight; - //std::vector bets; - betinfo.txid = bettxid; - - if (CCgetspenttxid(finaltxid, vini, finaltxheight, bettxid, NVOUT_CCMARKER) == 0) - betinfo.isOpen = false; - else - betinfo.isOpen = true; - - // override with real amount (TODO: check this) - //bet1.positionsize = bettx.vout[2].nValue; - - betinfo.bets.push_back(bet1); - - prices_enumaddedbets(batontxid, betinfo.bets, bettxid); - - if (!betinfo.isOpen) { - CTransaction finaltx; - uint256 hashBlock; - vscript_t vopret; - if (myGetTransaction(finaltxid, finaltx, hashBlock) && finaltx.vout.size() > 0 && PricesCheckOpret(finaltx, vopret) != 0) { - uint8_t funcId = prices_finalopretdecode(finaltx.vout.back().scriptPubKey, betinfo.txid, betinfo.pk, betinfo.lastheight, betinfo.averageCostbasis, betinfo.lastprice, betinfo.liquidationprice, betinfo.equity, betinfo.exitfee); - if (funcId == 0) - return -3; - - betinfo.isRekt = (funcId == 'R'); - - // return 0; - } - else - return -6; - } - - - if (prices_scanchain(betinfo.bets, betinfo.leverage, betinfo.vecparsed, betinfo.lastprice, betinfo.lastheight) < 0) { - return -4; - } - - mpz_t mpzTotalPosition; - mpz_t mpzTotalprofits; - mpz_t mpzTotalcostbasis; - - mpz_init(mpzTotalPosition); - mpz_init(mpzTotalprofits); - mpz_init(mpzTotalcostbasis); - - int64_t totalposition = 0; - int64_t totalprofits = 0; - - for (auto b : betinfo.bets) { - mpz_t mpzProduct; - mpz_t mpzProfits; - - mpz_init(mpzProduct); - mpz_init(mpzProfits); - - //totalprofits += b.profits; - //dcostbasis += b.amount * (double)b.costbasis; - // costbasis += b.amount * (b.costbasis / PRICES_POINTFACTOR); // prevent int64 overflow (but we have underflow for 1/BTC) - // std::cerr << "PricesInfo() acc dcostbasis=" << dcostbasis << " b.amount=" << b.amount << " b.costbasis/PRICES_POINTFACTOR=" << (b.costbasis / PRICES_POINTFACTOR) << std::endl; - //std::cerr << "PricesInfo() acc dcostbasis=" << dcostbasis << " b.amount=" << b.amount << " b.costbasis/PRICES_POINTFACTOR=" << (b.costbasis / PRICES_POINTFACTOR) << std::endl; - mpz_set_ui(mpzProduct, b.costbasis); - mpz_mul_ui(mpzProduct, mpzProduct, (uint64_t)b.positionsize); // b.costbasis * b.amount - mpz_add(mpzTotalcostbasis, mpzTotalcostbasis, mpzProduct); //averageCostbasis += b.costbasis * b.amount; - - mpz_add_ui(mpzTotalPosition, mpzTotalPosition, (uint64_t)b.positionsize); //totalposition += b.amount; - mpz_add(mpzTotalprofits, mpzTotalprofits, mpzProfits); //totalprofits += b.profits; - - totalposition += b.positionsize; - totalprofits += b.profits; - - mpz_clear(mpzProduct); - mpz_clear(mpzProfits); - } - - betinfo.equity = totalposition + totalprofits; - //int64_t averageCostbasis = 0; - - if (mpz_get_ui(mpzTotalPosition) != 0) { //prevent zero div - mpz_t mpzAverageCostbasis; - mpz_init(mpzAverageCostbasis); - - //averageCostbasis = totalcostbasis / totalposition; - mpz_mul_ui(mpzTotalcostbasis, mpzTotalcostbasis, SATOSHIDEN); // profits *= SATOSHIDEN normalization to prevent loss of significance while division - mpz_tdiv_q(mpzAverageCostbasis, mpzTotalcostbasis, mpzTotalPosition); - - mpz_tdiv_q_ui(mpzAverageCostbasis, mpzAverageCostbasis, SATOSHIDEN); // profits /= SATOSHIDEN de-normalization - - betinfo.averageCostbasis = mpz_get_ui(mpzAverageCostbasis); - mpz_clear(mpzAverageCostbasis); - } - - betinfo.liquidationprice = 0; - if (betinfo.leverage != 0) {// prevent zero div - betinfo.liquidationprice = betinfo.averageCostbasis - (betinfo.averageCostbasis * (1 - prices_minmarginpercent(betinfo.leverage))) / betinfo.leverage; - } - - if (!betinfo.isRekt) { // not set by check for final tx - - if (betinfo.equity > (int64_t)((double)totalposition * prices_minmarginpercent(betinfo.leverage))) - betinfo.isRekt = false; - else - { - betinfo.isRekt = true; - betinfo.exitfee = (int64_t)(((double)totalposition * prices_minmarginpercent(betinfo.leverage)) / 10); // was: totalposition / 500 - } - } - - mpz_clear(mpzTotalPosition); - mpz_clear(mpzTotalprofits); - mpz_clear(mpzTotalcostbasis); - return 0; - } - return -3; - } - return (-1); -} - -// pricesrekt rpc: anyone can rekt a bet at some block where losses reached limit, collecting fee -UniValue PricesRekt(int64_t txfee, uint256 bettxid, int32_t rektheight) -{ - int32_t nextheight = komodo_nextheight(); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextheight); UniValue result(UniValue::VOBJ); - struct CCcontract_info *cp, C; - CTransaction bettx; - int64_t myfee = 0; - CPubKey pk, mypk, pricespk; - std::string rawtx; - char destaddr[64]; - - cp = CCinit(&C, EVAL_PRICES); - if (txfee == 0) // TODO: what did we want to do with txfee in prices? - txfee = PRICES_TXFEE; - mypk = pubkey2pk(Mypubkey()); - pricespk = GetUnspendable(cp, 0); - GetCCaddress(cp, destaddr, pricespk); - - BetInfo betinfo; - int32_t retcode = prices_getbetinfo(bettxid, betinfo); - if (retcode < 0) { - if (retcode == -1) { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "cant find bettxid or incorrect")); - } - else if (retcode == -2) { - throw std::runtime_error("tx still in mempool"); - } - else if (retcode == -3) - { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "cant decode opret")); - return(result); - } - else if (retcode == -4) { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "error scanning chain")); - } - return(result); - } - - int64_t totalposition = 0; - int64_t totalprofits = 0; - - for (auto b : betinfo.bets) { - totalposition += b.positionsize; - totalprofits += b.profits; - } - - - if (!betinfo.isOpen) { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "position closed")); - return result; - } - - prices_betjson(result, betinfo.bets, betinfo.leverage, betinfo.lastheight, betinfo.lastprice); // fill output - if (betinfo.isRekt) - { - myfee = betinfo.exitfee; // consolation fee for loss - } - if (myfee != 0) - { - int64_t CCchange = 0, inputsum; - - mtx.vin.push_back(CTxIn(bettxid, NVOUT_CCMARKER, CScript())); // spend cc marker - if ((inputsum = AddPricesInputs(cp, mtx, destaddr, myfee + txfee, 64)) > myfee + txfee) // TODO: why do we take txfee from global addr and not from user's addr? - CCchange = (inputsum - myfee); - mtx.vout.push_back(CTxOut(myfee, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - if (CCchange >= txfee) - mtx.vout.push_back(MakeCC1vout(cp->evalcode, CCchange, pricespk)); - - /// mtx.vout.push_back(MakeCC1vout(cp->evalcode, bettx.vout[2].nValue - myfee - txfee, pricespk)); // change - - // make some PoW to get txid=0x00.....00 to 'faucet' rekts - fprintf(stderr, "start PoW at %u\n", (uint32_t)time(NULL)); - uint32_t nonce = rand() & 0xfffffff; - for (int i = 0; i<1000000; i++, nonce++) - { - CMutableTransaction tmpmtx = mtx; - - rawtx = FinalizeCCTx(0, cp, tmpmtx, mypk, txfee, prices_finalopret(true, bettxid, mypk, betinfo.lastheight, betinfo.averageCostbasis, betinfo.lastprice, betinfo.liquidationprice, betinfo.equity, myfee, nonce)); - uint256 hash = tmpmtx.GetHash(); - if ((hash.begin()[0] & 0xff) == 0 && (hash.begin()[31] & 0xff) == 0) - { - fprintf(stderr, "found valid txid after %d iterations %u\n", i, (uint32_t)time(NULL)); - return(prices_rawtxresult(result, rawtx, 0)); - } - } - fprintf(stderr, "couldnt generate valid txid %u\n", (uint32_t)time(NULL)); - - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "could not generate valid txid")); - return(result); - } - else - { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "position not rekt")); - return(result); - } -} - -// pricescashout rpc impl: bettor can cashout hit bet if it is not rekt -UniValue PricesCashout(int64_t txfee, uint256 bettxid) -{ - int32_t nextheight = komodo_nextheight(); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextheight); - UniValue result(UniValue::VOBJ); - struct CCcontract_info *cp, C; char destaddr[64]; - int64_t CCchange = 0, inputsum; - CPubKey pk, mypk, pricespk; - std::string rawtx; - - cp = CCinit(&C, EVAL_PRICES); - if (txfee == 0) - txfee = PRICES_TXFEE; - - mypk = pubkey2pk(Mypubkey()); - pricespk = GetUnspendable(cp, 0); - GetCCaddress(cp, destaddr, pricespk); - - BetInfo betinfo; - int32_t retcode = prices_getbetinfo(bettxid, betinfo); - if (retcode < 0) { - if (retcode == -1) { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "cant find bettxid or incorrect")); - } - else if (retcode == -2) { - throw std::runtime_error("tx still in mempool"); - } - else if (retcode == -3) - { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "cant decode opret")); - return(result); - } - else if (retcode == -4) { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "error scanning chain")); - } - return(result); - } - - int64_t totalposition = 0; - int64_t totalprofits = 0; - - for (auto b : betinfo.bets) { - totalposition += b.positionsize; - totalprofits += b.profits; - } - - - if (!betinfo.isOpen) { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "position closed")); - return result; - } - - prices_betjson(result, betinfo.bets, betinfo.leverage, betinfo.lastheight, betinfo.lastprice); // fill output json - - if (betinfo.isRekt) - { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "position rekt")); - return(result); - } - - mtx.vin.push_back(CTxIn(bettxid, NVOUT_CCMARKER, CScript())); // spend cc marker - if ((inputsum = AddPricesInputs(cp, mtx, destaddr, betinfo.equity + txfee, 64)) > betinfo.equity + txfee) // TODO: why txfee from the fund? - CCchange = (inputsum - betinfo.equity); - mtx.vout.push_back(CTxOut(betinfo.equity, CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - if (CCchange >= txfee) - mtx.vout.push_back(MakeCC1vout(cp->evalcode, CCchange, pricespk)); - // TODO: what should the opret param be: - rawtx = FinalizeCCTx(0, cp, mtx, mypk, txfee, prices_finalopret(false, bettxid, mypk, nextheight-1, betinfo.averageCostbasis, betinfo.lastprice, betinfo.liquidationprice, betinfo.equity, txfee, 0)); - return(prices_rawtxresult(result, rawtx, 0)); - -} - - -// pricesinfo rpc impl -UniValue PricesInfo(uint256 bettxid, int32_t refheight) -{ - UniValue result(UniValue::VOBJ); -/* CTransaction bettx; - uint256 hashBlock, batontxid, tokenid; - int64_t positionsize = 0, firstprice = 0, lastprice = 0; - int32_t firstheight = 0, endheight; - int16_t leverage = 0; - std::vector vec; - CPubKey pk, mypk, pricespk; - std::string rawtx; */ - - BetInfo betinfo; - int32_t retcode = prices_getbetinfo(bettxid, betinfo); - if (retcode < 0) { - if( retcode == -1 ) { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "cant find bettxid or incorrect")); - } - else if (retcode == -2) { - throw std::runtime_error("tx still in mempool"); - } - else if (retcode == -3) - { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "cant decode opret")); - return(result); - } - else if (retcode == -4) { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", "error scanning chain")); - } - else { - result.push_back(Pair("result", "error")); - result.push_back(Pair("error", retcode)); - } - return(result); - } - - if (!betinfo.isRekt) - result.push_back(Pair("rekt", 0)); - else - { - result.push_back(Pair("rekt", (int64_t)1)); - result.push_back(Pair("rektfee", betinfo.exitfee)); - result.push_back(Pair("rektheight", betinfo.lastheight)); - } - - result.push_back(Pair("open", betinfo.isOpen ? 1 : 0 )); - - std::string expr = prices_getsourceexpression(betinfo.vecparsed); - result.push_back(Pair("expression", expr)); - result.push_back(Pair("reduced", prices_getreducedexpr(expr))); -// result.push_back(Pair("batontxid", batontxid.GetHex())); - result.push_back(Pair("costbasis", ValueFromAmount(betinfo.averageCostbasis))); -#ifdef TESTMODE - result.push_back(Pair("costbasis_test_period", 7)); -#endif - - prices_betjson(result, betinfo.bets, betinfo.leverage, betinfo.lastheight, betinfo.lastprice); - - result.push_back(Pair("LiquidationPrice", ValueFromAmount(betinfo.liquidationprice))); - - return(result); -} - -// priceslist rpc impl -UniValue PricesList(uint32_t filter, CPubKey mypk) -{ - UniValue result(UniValue::VARR); - std::vector > addressIndex, addressIndexCC; - struct CCcontract_info *cp, C; - - cp = CCinit(&C, EVAL_PRICES); - //pricespk = GetUnspendable(cp, 0); - - // filters and outputs prices bet txid - auto AddBetToList = [&](uint256 txid) - { - int64_t amount, firstprice; - int32_t height; - int16_t leverage; - uint256 hashBlock, tokenid; - CPubKey pk, pricespk; - std::vector vec; - CTransaction vintx; - - if (myGetTransaction(txid, vintx, hashBlock) != 0) - { - - // TODO: forget old tx - //CBlockIndex *bi = komodo_getblockindex(hashBlock); - //if (bi && bi->nHeight < 5342) - // return; - - bool bAppend = false; - if (vintx.vout.size() > 0 && prices_betopretdecode(vintx.vout.back().scriptPubKey, pk, height, amount, leverage, firstprice, vec, tokenid) == 'B' && - (mypk == CPubKey() || mypk == pk)) // if only mypubkey to list - { - if (filter == 0) - bAppend = true; - else { - int32_t vini; - int32_t height; - uint256 finaltxid; - - int32_t spent = CCgetspenttxid(finaltxid, vini, height, txid, NVOUT_CCMARKER); - if (filter == 1 && spent < 0 || // open positions - filter == 2 && spent == 0) // closed positions - bAppend = true; - } - if (bAppend) - result.push_back(txid.GetHex()); - } - std::cerr << "PricesList() " << " bettxid=" << txid.GetHex() << " mypk=" << HexStr(mypk) << " opretpk=" << HexStr(pk) << " filter=" << filter << " bAppend=" << bAppend << std::endl; - } - }; - - - SetCCtxids(addressIndex, cp->normaladdr, false); // old normal marker - for (std::vector >::const_iterator it = addressIndex.begin(); it != addressIndex.end(); it++) - { - if( it->first.index == NVOUT_NORMALMARKER ) - AddBetToList(it->first.txhash); - } - - /* for future when switch to cc marker only - SetCCtxids(addressIndexCC, cp->unspendableCCaddr, true); // cc marker - for (std::vector >::const_iterator it = addressIndexCC.begin(); it != addressIndexCC.end(); it++) - { - priceslist(it, 1); - } - */ - return(result); -} - - -static bool prices_addbookentry(uint256 txid, std::vector &book) -{ - BetInfo betinfo; - if (prices_getbetinfo(txid, betinfo) == 0) { - book.push_back(betinfo); - return true; - } - return false; -} - - -static bool prices_ispositionup(const std::vector &vecparsed, int16_t leverage) { - if (vecparsed.size() > 1 && vecparsed.size() <= 3) { - uint16_t opcode = vecparsed[0]; - - int32_t value = (opcode & (KOMODO_MAXPRICES - 1)); // filter index or weight = opcode & (2048-1) - - if ((opcode & KOMODO_PRICEMASK) == 0) { - char name[65]; - if (komodo_pricename(name, value)) { - std::string upperquote, bottomquote; - prices_splitpair(std::string(name), upperquote, bottomquote); - - uint16_t opcode1 = vecparsed[1]; - bool isInverted = ((opcode1 & KOMODO_PRICEMASK) == PRICES_INV); - - //std::cerr << "prices_ispositionup upperquote=" << upperquote << " bottomquote=" << bottomquote << " opcode1=" << opcode1 << " (opcode1 & KOMODO_PRICEMASK)=" << (opcode1 & KOMODO_PRICEMASK) << std::endl; - - if (upperquote == "BTC" || bottomquote == "BTC") { // it is relatively btc - if (upperquote == "BTC" && (leverage > 0 && !isInverted || leverage < 0 && isInverted) || - bottomquote == "BTC" && (leverage < 0 && !isInverted || leverage > 0 && isInverted)) { - std::cerr << "prices_ispositionup returns true for BTC for expr=" << prices_getsourceexpression(vecparsed) << " lev=" << leverage << std::endl; - return true; - } - else { - std::cerr << "prices_ispositionup returns false for BTC for expr=" << prices_getsourceexpression(vecparsed) << " lev=" << leverage << std::endl; - return false; - } - } - - if (upperquote == "USD" || bottomquote == "USD") { // it is relatively usd - if (upperquote == "USD" && (leverage > 0 && !isInverted || leverage < 0 && isInverted) || - bottomquote == "USD" && (leverage < 0 && !isInverted || leverage > 0 && isInverted)) { - std::cerr << "prices_ispositionup returns true for USD for expr=" << prices_getsourceexpression(vecparsed) << " lev=" << leverage << std::endl; - return true; - } - else { - std::cerr << "prices_ispositionup returns false for USD for expr=" << prices_getsourceexpression(vecparsed) << " lev=" << leverage << std::endl; - return false; - } - } - } - } - } - std::cerr << "prices_ispositionup returns false for expr=" << prices_getsourceexpression(vecparsed) << " lev=" << leverage << std::endl; - return false; -} - -static bool prices_isopposite(BetInfo p1, BetInfo p2) { - if (p1.vecparsed.size() <= 3 && p2.vecparsed.size() <= 3) { // simple synthetic exp - - uint16_t opcode1 = p1.vecparsed[0]; - uint16_t opcode2 = p2.vecparsed[0]; - - int32_t value1 = (opcode1 & (KOMODO_MAXPRICES - 1)); // index or weight - int32_t value2 = (opcode2 & (KOMODO_MAXPRICES - 1)); // index or weight - - if ( (opcode1 & KOMODO_PRICEMASK) == 0 && (opcode2 & KOMODO_PRICEMASK) == 0 ) { - char name1[65]; - char name2[65]; - if (komodo_pricename(name1, value1) && komodo_pricename(name2, value2)) { - - uint16_t opcode1 = p1.vecparsed[1]; - uint16_t opcode2 = p2.vecparsed[1]; - - std::string upperquote1, bottomquote1, upperquote2, bottomquote2; - prices_splitpair(std::string(name1), upperquote1, bottomquote1); - prices_splitpair(std::string(name2), upperquote2, bottomquote2); - - bool isInverted1 = ((opcode1 & KOMODO_PRICEMASK) != PRICES_INV); - bool isInverted2 = ((opcode2 & KOMODO_PRICEMASK) != PRICES_INV); - - if (/*upperquote1 == bottomquote2 && bottomquote1 == upperquote2 && (p1.leverage > 0 == p2.leverage > 0 || (opcode1 & KOMODO_PRICEMASK) == PRICES_INV == (opcode2 & KOMODO_PRICEMASK) == PRICES_INV) ||*/ - upperquote1 == upperquote2 && bottomquote1 == bottomquote2 && ((p1.leverage > 0) != (p2.leverage > 0) || isInverted1 != isInverted2) ) - return true; - } - } - } - return false; -} - - - -static std::string findMatchedBook(const std::vector &vecparsed, const std::map > & bookmatched) { - - if (vecparsed.size() > 1 && vecparsed.size() <= 3) { - uint16_t opcode = vecparsed[0]; - - int32_t value = (opcode & (KOMODO_MAXPRICES - 1)); // filter index or weight = opcode & (2048-1) - - if ((opcode & KOMODO_PRICEMASK) == 0) { - char name[65]; - if (komodo_pricename(name, value)) { - auto it = bookmatched.find(std::string(name)); - if (it != bookmatched.end()) - return it->first; - } - } - } - return std::string(""); -} - - -void prices_getorderbook(std::map > & bookmatched, std::map &matchedTotals, TotalFund &fundTotals) -{ - std::vector book; - std::vector > addressIndex; - struct CCcontract_info *cp, C; - - cp = CCinit(&C, EVAL_PRICES); - - // add all bets: - SetCCtxids(addressIndex, cp->normaladdr, false); // old normal marker - for (std::vector >::const_iterator it = addressIndex.begin(); it != addressIndex.end(); it++) - { - if (it->first.index == NVOUT_NORMALMARKER) - prices_addbookentry(it->first.txhash, book); - } - - - // calc total fund amount - fundTotals.totalFund = 0; - fundTotals.totalRekt = 0; - fundTotals.totalEquity = 0; - fundTotals.totalActiveBets = 0; - - std::vector > addressCCunspents; - SetCCunspents(addressCCunspents, cp->unspendableCCaddr, true); // cc marker - for (std::vector >::const_iterator it = addressCCunspents.begin(); it != addressCCunspents.end(); it++) - { - //std::cerr << "totalfund calc txid=" << it->first.txhash.GetHex() << " nvout=" << it->first.index << " satoshis=" << it->second.satoshis << std::endl; - fundTotals.totalFund += it->second.satoshis; - } - - // extract out opposite bets: - while (book.size() > 0) { - - int64_t totalPos = 0; - for (auto bet : book[0].bets) totalPos += bet.positionsize; - - if (book[0].isOpen) { - - fundTotals.totalActiveBets += totalPos; - fundTotals.totalEquity += book[0].equity; - - if (book[0].vecparsed.size() <= 3) { // only short expr check for match: "BTC_USD,1" or "BTC_USD,!,1" - char name[65]; - komodo_pricename(name, (book[0].vecparsed[0] & (KOMODO_MAXPRICES - 1))); - std::string sname = name; - bookmatched[sname].push_back(book[0]); - - for (int j = 1; j < book.size(); j++) { - if (book[0].isOpen && book[j].isOpen) { - if (prices_isopposite(book[0], book[j])) { - - bookmatched[sname].push_back(book[j]); - book.erase(book.begin() + j); - } - } - } - } - else { - // store as is - std::string sname = prices_getsourceexpression(book[0].vecparsed); - bookmatched[sname].push_back(book[0]); - } - } - else { - if( book[0].isRekt ) - fundTotals.totalRekt += (totalPos - book[0].exitfee); - else - fundTotals.totalCashout += (totalPos - book[0].exitfee); - - //TODO: store rekt - } - book.erase(book.begin()); - } - - // calculate cancelling amount - for (auto &m : bookmatched) { // note: use reference &m otherwise isUp will be changed only in a copy - int64_t totalLeveragedPositionUp = 0; - int64_t totalLeveragedPositionDown = 0; - - for (int i = 0; i < m.second.size(); i++) { - int64_t totalPos = 0; - for (auto bet : m.second[i].bets) totalPos += bet.positionsize; - m.second[i].isUp = prices_ispositionup(m.second[i].vecparsed, m.second[i].leverage); - if (m.second[i].isUp) - totalLeveragedPositionUp += totalPos * abs(m.second[i].leverage); - else - totalLeveragedPositionDown += totalPos * abs(m.second[i].leverage); - //std::cerr << "PricesGetOrderbook 0 m.second[i].isUp=" << m.second[i].isUp << " i=" << i << std::endl; - - } - matchedTotals[m.first].diffLeveragedPosition = totalLeveragedPositionUp - totalLeveragedPositionDown; - } -} - -static bool prices_isacceptableamount(const std::vector &vecparsed, int64_t amount, int16_t leverage) { - - std::map > matchedBook; - std::map matchedTotals; - TotalFund fundTotals; - - prices_getorderbook(matchedBook, matchedTotals, fundTotals); - std::string pricename = findMatchedBook(vecparsed, matchedBook); - if (!pricename.empty()) { - std::cerr << "prices_isacceptableamount() found matched book=" << pricename << " diffLeveragedPosition=" << matchedTotals[pricename].diffLeveragedPosition << " expr=" << prices_getsourceexpression(vecparsed) << std::endl; - // could fit into leveraged amount - if (prices_ispositionup(vecparsed, leverage) && amount*abs(leverage) + matchedTotals[pricename].diffLeveragedPosition <= 0) { - std::cerr << "prices_isacceptableamount() could fit into opposite negative lev amount" << std::endl; - return true; - } - if (!prices_ispositionup(vecparsed, leverage) && -amount*abs(leverage) + matchedTotals[pricename].diffLeveragedPosition >= 0) { - std::cerr << "prices_isacceptableamount() could fit into opposite positive lev amount" << std::endl; - return true; - } - } - - std::cerr << "prices_isacceptableamount() amount=" << amount << " leverage=" << leverage << " fundTotals.totalFund=" << fundTotals.totalFund << " fundTotals.totalEquity=" << fundTotals.totalEquity << std::endl; - // if not fit to matched = allow to bet for leveraged amount no more than 10% from free fund - if (amount * leverage < (fundTotals.totalFund - fundTotals.totalEquity) * PRICES_MINAVAILFUNDFRACTION) - return true; - - return false; -} - - -// walk through uxtos on the global address -// calculate the balance: -// + rekt positions -// = opposite positions -// - unbalanced positions -UniValue PricesGetOrderbook() -{ - UniValue result(UniValue::VOBJ); - std::map > matchedBook; - std::map matchedTotals; - TotalFund fundTotals; - - prices_getorderbook(matchedBook, matchedTotals, fundTotals); - - /*UniValue resbook (UniValue::VARR); - for (int i = 0; i < book.size(); i++) { - UniValue entry(UniValue::VOBJ); - entry.push_back(Pair("expression", prices_getsourceexpression(book[i].vecparsed))); - entry.push_back(Pair("costbasis", book[i].averageCostbasis)); - entry.push_back(Pair("leverage", book[i].leverage)); - entry.push_back(Pair("equity", book[i].equity)); - resbook.push_back(entry); - } - result.push_back(Pair("unmatched", resbook)); */ - - // copy to rpc UniResult - for (auto &m : matchedBook) { - UniValue resheader(UniValue::VOBJ); - UniValue resbook(UniValue::VARR); - for (int i = 0; i < m.second.size(); i++) { - UniValue entry(UniValue::VOBJ); - - int64_t totalPos = 0; - for (auto bet : m.second[i].bets) totalPos += bet.positionsize; - entry.push_back(Pair("isOpen", (m.second[i].isOpen ? 1 : 0 ))); - entry.push_back(Pair("expression", prices_getsourceexpression(m.second[i].vecparsed))); - entry.push_back(Pair("positionsize", totalPos)); - entry.push_back(Pair("leverage", m.second[i].leverage)); - entry.push_back(Pair("costbasis", m.second[i].averageCostbasis)); - entry.push_back(Pair("lastprice", m.second[i].lastprice)); - entry.push_back(Pair("equity", m.second[i].equity)); - entry.push_back(Pair("isUpPosition", (m.second[i].isUp ? 1 : 0))); - resbook.push_back(entry); - } - resheader.push_back(Pair("positions", resbook)); - resheader.push_back(Pair("DiffLeveragedPosition", matchedTotals[m.first].diffLeveragedPosition)); - result.push_back(Pair(m.first, resheader)); - } - - //int64_t totalLiabilities = 0; - /* empty - for (int i = 0; i < book.size(); i++) { - if (book[i].isOpen) { - int64_t t = 0; - for (auto b : book[i].bets) t += b.positionsize; - std::cerr << "book[i].txid=" << book[i].txid.GetHex() << " exp=" << prices_getsourceexpression(book[i].vecparsed) << " totalpos=" << t << " equity=" << book[i].equity << std::endl; - totalLiabilities += book[i].equity; - } - } */ - - result.push_back(Pair("TotalFund", ValueFromAmount(fundTotals.totalFund))); - result.push_back(Pair("TotalEquity", ValueFromAmount(fundTotals.totalEquity))); - result.push_back(Pair("TotalRekt", ValueFromAmount(fundTotals.totalRekt))); - result.push_back(Pair("TotalBets", ValueFromAmount(fundTotals.totalActiveBets))); - result.push_back(Pair("TotalCashoutBets", ValueFromAmount(fundTotals.totalCashout))); - -// result.push_back(Pair("TotalLiabilities", ValueFromAmount(totalLiabilities))); - return result; -} diff --git a/src/cc/rewards.cpp b/src/cc/rewards.cpp index 2be54628d3f..e4dedf8ba3d 100644 --- a/src/cc/rewards.cpp +++ b/src/cc/rewards.cpp @@ -14,6 +14,8 @@ ******************************************************************************/ #include "CCrewards.h" +#include "komodo_bitcoind.h" +#include /* The rewards CC contract is initially for OOT, which needs this functionality. However, many of the attributes can be parameterized to allow different rewards programs to run. Multiple rewards plans could even run on the same blockchain, though the user would need to choose which one to lock funds into. @@ -68,11 +70,11 @@ /// the following are compatible with windows /// mpz_set_lli sets a long long singed int to a big num mpz_t for very large integer math -extern void mpz_set_lli( mpz_t rop, long long op ); +void mpz_set_lli( mpz_t rop, long long op ); // mpz_get_si2 gets a mpz_t and returns a signed long long int -extern int64_t mpz_get_si2( mpz_t op ); +int64_t mpz_get_si2( mpz_t op ); // mpz_get_ui2 gets a mpz_t and returns a unsigned long long int -extern uint64_t mpz_get_ui2( mpz_t op ); +uint64_t mpz_get_ui2( mpz_t op ); uint64_t RewardsCalc(int64_t amount, uint256 txid, int64_t APR, int64_t minseconds, int64_t maxseconds, uint32_t timestamp) { @@ -294,7 +296,7 @@ bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t if ( (*cp->ismyvin)(tx.vin[i].scriptSig) == 0 ) return eval->Invalid("unexpected normal vin for unlock"); } - if ( !CheckTxFee(tx, txfee, chainActive.LastTip()->nHeight, chainActive.LastTip()->nTime, dummy) ) + if ( !CheckTxFee(tx, txfee, chainActive.Tip()->nHeight, chainActive.Tip()->nTime, dummy) ) return eval->Invalid("txfee is too high"); amount = vinTx.vout[0].nValue; reward = RewardsCalc((int64_t)amount,tx.vin[0].prevout.hash,(int64_t)APR,(int64_t)minseconds,(int64_t)maxseconds,GetLatestTimestamp(eval->GetCurrentHeight())); diff --git a/src/cc/rogue/main.c b/src/cc/rogue/main.c index c3adbedd8ba..d6bf1356e14 100644 --- a/src/cc/rogue/main.c +++ b/src/cc/rogue/main.c @@ -93,9 +93,6 @@ char *clonestr(char *str) if ( str == 0 || str[0] == 0 ) { printf("warning cloning nullstr.%p\n",str); -#ifdef __APPLE__ - while ( 1 ) sleep(1); -#endif str = (char *)""; } clone = (char *)malloc(strlen(str)+16); @@ -547,44 +544,7 @@ uint16_t _komodo_userpass(char *username, char *password, FILE *fp) return(port); } -/*void komodo_statefname(char *fname,char *symbol,char *str) -{ - int32_t n,len; - sprintf(fname,"%s",getDataDir()); - if ( (n= (int32_t)strlen(ASSETCHAINS_SYMBOL)) != 0 ) - { - len = (int32_t)strlen(fname); - if ( strcmp(ASSETCHAINS_SYMBOL,&fname[len - n]) == 0 ) - fname[len - n] = 0; - else - { - printf("unexpected fname.(%s) vs %s [%s] n.%d len.%d (%s)\n",fname,symbol,ASSETCHAINS_SYMBOL,n,len,&fname[len - n]); - return; - } - } - else - { -#ifdef _WIN32 - strcat(fname,"\\"); -#else - strcat(fname,"/"); -#endif - } - if ( symbol != 0 && symbol[0] != 0 && strcmp("KMD",symbol) != 0 ) - { - strcat(fname,symbol); - //printf("statefname.(%s) -> (%s)\n",symbol,fname); -#ifdef _WIN32 - strcat(fname,"\\"); -#else - strcat(fname,"/"); -#endif - } - strcat(fname,str); - //printf("test.(%s) -> [%s] statename.(%s) %s\n",test,ASSETCHAINS_SYMBOL,symbol,fname); -}*/ - -uint16_t komodo_userpass(char *userpass,char *symbol) +uint16_t komodo_userpass(char *userpass,const char *symbol) { FILE *fp; uint16_t port = 0; char fname[512],username[512],password[512],confname[KOMODO_ASSETCHAIN_MAXLEN]; userpass[0] = 0; @@ -597,7 +557,6 @@ uint16_t komodo_userpass(char *userpass,char *symbol) #endif } else sprintf(confname,"%s.conf",symbol); - //komodo_statefname(fname,symbol,confname); if ( (fp= fopen(confname,"rb")) != 0 ) { port = _komodo_userpass(username,password,fp); @@ -621,9 +580,7 @@ char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port) { sprintf(url,(char *)"http://%s:%u",IPADDRESS,port); sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params); - //printf("[%s] (%s) postdata.(%s) params.(%s) USERPASS.(%s)\n",ASSETCHAINS_SYMBOL,url,postdata,params,USERPASS); retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,userpass,method,params); - //retstr = curl_post(&cHandle,url,USERPASS,postdata,0,0,0,0); } return(retstr2); } diff --git a/src/cc/rogue_rpc.cpp b/src/cc/rogue_rpc.cpp index 9277c673724..4f9e6d00a1b 100644 --- a/src/cc/rogue_rpc.cpp +++ b/src/cc/rogue_rpc.cpp @@ -16,6 +16,7 @@ #include "cJSON.h" #include "CCinclude.h" +#include "komodo_bitcoind.h" #define ROGUE_REGISTRATION 5 #define ROGUE_REGISTRATIONSIZE (100 * 10000) @@ -162,8 +163,8 @@ CScript rogue_keystrokesopret(uint256 gametxid,uint256 batontxid,CPubKey pk,std: CScript rogue_highlanderopret(uint8_t funcid,uint256 gametxid,int32_t regslot,CPubKey pk,std::vectorplayerdata,std::string pname) { - CScript opret; uint8_t evalcode = EVAL_ROGUE; std::string symbol(ASSETCHAINS_SYMBOL); - opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << gametxid << symbol << pname << regslot << pk << playerdata ); + CScript opret; uint8_t evalcode = EVAL_ROGUE; + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << gametxid << chainName.symbol() << pname << regslot << pk << playerdata ); return(opret); } @@ -701,7 +702,7 @@ uint64_t rogue_gamefields(UniValue &obj,int64_t maxplayers,int64_t buyin,uint256 obj.push_back(Pair("seed",(int64_t)seed)); if ( rogue_iamregistered(maxplayers,gametxid,tx,myrogueaddr) > 0 ) sprintf(cmd,"cc/rogue/rogue %llu %s",(long long)seed,gametxid.ToString().c_str()); - else sprintf(cmd,"./komodo-cli -ac_name=%s cclib register %d \"[%%22%s%%22]\"",ASSETCHAINS_SYMBOL,EVAL_ROGUE,gametxid.ToString().c_str()); + else sprintf(cmd,"./komodo-cli -ac_name=%s cclib register %d \"[%%22%s%%22]\"",chainName.symbol().c_str(),EVAL_ROGUE,gametxid.ToString().c_str()); obj.push_back(Pair("run",cmd)); } } @@ -1513,7 +1514,7 @@ UniValue rogue_setname(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) bool rogue_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx) { CScript scriptPubKey; std::vector vopret; uint8_t *script,e,f,funcid,tokentx=0; int32_t i,maxplayers,enabled = 0,decoded=0,regslot,ind,err,dispflag,gameheight,score,numvouts; CTransaction vintx,gametx; CPubKey pk; uint256 hashBlock,gametxid,txid,tokenid,batontxid,playertxid,ptxid; int64_t buyin,cashout; std::vector playerdata,keystrokes; std::string symbol,pname; - if ( strcmp(ASSETCHAINS_SYMBOL,"ROGUE") == 0 ) + if ( chainName.isSymbol("ROGUE") ) { if (height < 21274 ) return(true); diff --git a/src/cc/sudoku.cpp b/src/cc/sudoku.cpp index 816e8763708..64abc0d96df 100644 --- a/src/cc/sudoku.cpp +++ b/src/cc/sudoku.cpp @@ -200,6 +200,7 @@ /* 1.11 2006-03-23 WD More simple speed optimizations, cleanup, bug fixes */ /* */ /************************************************************************************/ +#include "komodo_bitcoind.h" #include #include @@ -2537,7 +2538,7 @@ int32_t sudoku_captcha(int32_t dispflag,uint32_t timestamps[81],int32_t height) printf("list[0] %u vs list[%d-1] %u\n",list[0],n,list[n-1]); retval = -1; } - else if ( list[n-1] > chainActive.LastTip()->nTime+200 ) + else if ( list[n-1] > chainActive.Tip()->nTime+200 ) retval = -2; else if ( solvetime >= 777 ) retval = 0; @@ -2658,7 +2659,7 @@ UniValue sudoku_generate(uint64_t txfee,struct CCcontract_info *cp,cJSON *params result.push_back(Pair("result","success")); result.push_back(Pair("name","sudoku")); result.push_back(Pair("method","gen")); - hash = chainActive.LastTip()->GetBlockHash(); + hash = chainActive.Tip()->GetBlockHash(); memcpy(&srandi,&hash,sizeof(srandi)); srandi ^= (uint32_t)time(NULL); while ( 1 ) @@ -2968,7 +2969,7 @@ bool sudoku_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const strcpy(laststr,str); fprintf(stderr,"%s\n",str); } - if ( strcmp(ASSETCHAINS_SYMBOL,"SUDOKU") != 0 || height > 2000 ) + if ( !chainName.isSymbol("SUDOKU") || height > 2000 ) return eval->Invalid("mismatched sudoku value vs score"); else return(true); } else return(true); @@ -3000,41 +3001,24 @@ bool sudoku_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const { if ( dispflag != 0 ) fprintf(stderr,"ht.%d errflag.%d %s\n",height,errflag,unsolved); - if ( (height != 1220 && height != 1383) || strcmp(ASSETCHAINS_SYMBOL,"SUDOKU") != 0 ) + if ( (height != 1220 && height != 1383) || !chainName.isSymbol("SUDOKU") ) return eval->Invalid("invalid timestamp vs unsolved"); } if ( dupree_solver(0,&score,unsolved) != 1 ) { if ( dispflag != 0 ) fprintf(stderr,"non-unique sudoku at ht.%d\n",height); - if ( strcmp(ASSETCHAINS_SYMBOL,"SUDOKU") != 0 ) + if ( !chainName.isSymbol("SUDOKU") ) return eval->Invalid("invalid sudoku with multiple solutions"); } if ( dispflag != 0 ) fprintf(stderr,"%s score.%d %s\n",solution,score,unsolved); if ( sudoku_captcha(dispflag,timestamps,height) < 0 ) return eval->Invalid("failed captcha"); - /*for (i=lasttime=0; i<81; i++) - { - if ( (ind= sudoku_minval(timestamps)) >= 0 ) - { - unsolved[ind] = solution[ind]; - if ( lasttime == 0 ) - lasttime = timestamps[ind]; - if ( dupree_solver(0,&score,unsolved) != 1 ) - fprintf(stderr,"i.%d ind.%d non-unique\n",i,ind); - if ( dispflag != 0 ) - fprintf(stderr,"%d.%d ",score,timestamps[ind]-lasttime); - lasttime = timestamps[ind]; - timestamps[ind] = 0; - } else break; - } - if ( dispflag != 0 ) - fprintf(stderr,"scores convergence\n");*/ return(true); } else return eval->Invalid("invalid solution opret"); } - else if ( strcmp(ASSETCHAINS_SYMBOL,"SUDOKU") == 0 && height == 236 ) + else if ( chainName.isSymbol("SUDOKU") && height == 236 ) return(true); else return eval->Invalid("invalid solution vin"); } diff --git a/src/chain.cpp b/src/chain.cpp index c93dd30ead7..7ab394240f5 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2017-2022 The Zcash developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -19,6 +20,13 @@ ******************************************************************************/ #include "chain.h" +#include "komodo_defs.h" +#include "komodo_globals.h" +#include "notaries_staked.h" +#include "komodo_hardfork.h" + +#include "main.h" +#include "txdb.h" using namespace std; @@ -26,7 +34,7 @@ using namespace std; * CChain implementation */ void CChain::SetTip(CBlockIndex *pindex) { - lastTip = pindex; + AssertLockHeld(cs_main); if (pindex == NULL) { vChain.clear(); return; @@ -39,6 +47,7 @@ void CChain::SetTip(CBlockIndex *pindex) { } CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const { + AssertLockHeld(cs_main); int nStep = 1; std::vector vHave; vHave.reserve(32); @@ -67,6 +76,7 @@ CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const { } const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const { + AssertLockHeld(cs_main); if ( pindex == 0 ) return(0); if (pindex->nHeight > Height()) @@ -76,6 +86,48 @@ const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const { return pindex; } +void CBlockIndex::TrimSolution() +{ + AssertLockHeld(cs_main); + + // We can correctly trim a solution as soon as the block index entry has been added + // to leveldb. Updates to the block index entry (to update validity status) will be + // handled by re-reading the solution from the existing db entry. It does not help to + // try to avoid these reads by gating trimming on the validity status: the re-reads are + // efficient anyway because of caching in leveldb, and most of them are unavoidable. + if (HasSolution()) { + std::vector empty; + nSolution.swap(empty); + } +} + +CBlockHeader CBlockIndex::GetBlockHeader() const +{ + AssertLockHeld(cs_main); + + CBlockHeader header; + header.nVersion = nVersion; + if (pprev) { + header.hashPrevBlock = pprev->GetBlockHash(); + } + header.hashMerkleRoot = hashMerkleRoot; + header.hashFinalSaplingRoot = hashFinalSaplingRoot; + header.nTime = nTime; + header.nBits = nBits; + header.nNonce = nNonce; + if (HasSolution()) { + header.nSolution = nSolution; + } else { + CDiskBlockIndex dbindex; + if (!pblocktree->ReadDiskBlockIndex(GetBlockHash(), dbindex)) { + LogPrintf("%s: Failed to read index entry", __func__); + throw std::runtime_error("Failed to read index entry"); + } + header.nSolution = dbindex.GetSolution(); + } + return header; +} + /** Turn the lowest '1' bit in the binary representation of a number into a '0'. */ int static inline InvertLowestOne(int n) { return n & (n - 1); } @@ -127,3 +179,13 @@ void CBlockIndex::BuildSkip() if (pprev) pskip = pprev->GetAncestor(GetSkipHeight(nHeight)); } + +bool CDiskBlockIndex::isStakedAndNotaryPay() const +{ + return is_STAKED(chainName.symbol()) != 0 && ASSETCHAINS_NOTARY_PAY[0] != 0; +} + +bool CDiskBlockIndex::isStakedAndAfterDec2019(unsigned int nTime) const +{ + return ASSETCHAINS_STAKED != 0 && (nTime > nStakedDecemberHardforkTimestamp || is_STAKED(chainName.symbol()) != 0); +} diff --git a/src/chain.h b/src/chain.h index 8e61fe0214d..6e2b19c47c8 100644 --- a/src/chain.h +++ b/src/chain.h @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2016-2022 The Zcash developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -26,19 +27,27 @@ #include "pow.h" #include "tinyformat.h" #include "uint256.h" +#include "sync.h" +#include "assetchain.h" #include #include + +extern CCriticalSection cs_main; + static const int SPROUT_VALUE_VERSION = 1001400; static const int SAPLING_VALUE_VERSION = 1010100; -extern char ASSETCHAINS_SYMBOL[65]; -extern uint64_t ASSETCHAINS_NOTARY_PAY[]; + +// These 5 are declared here to avoid circular dependencies +// code used this moved into .cpp +/*extern assetchain chainName; +extern uint64_t ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS+1]; extern int32_t ASSETCHAINS_STAKED; extern const uint32_t nStakedDecemberHardforkTimestamp; //December 2019 hardfork extern const int32_t nDecemberHardforkHeight; //December 2019 hardfork -extern int8_t is_STAKED(const char *chain_name); +uint8_t is_STAKED(const std::string& symbol);*/ struct CDiskBlockPos { @@ -209,8 +218,14 @@ class CBlockIndex unsigned int nTime; unsigned int nBits; uint256 nNonce; + +protected: + // The Equihash solution, if it is stored. Once we know that the block index + // entry is present in leveldb, this field can be cleared via the TrimSolution + // method to save memory. std::vector nSolution; +public: //! (memory only) Sequential id assigned to distinguish order in which blocks are received. uint32_t nSequenceId; @@ -284,23 +299,15 @@ class CBlockIndex return ret; } - CBlockHeader GetBlockHeader() const - { - CBlockHeader block; - block.nVersion = nVersion; - if (pprev) - block.hashPrevBlock = pprev->GetBlockHash(); - block.hashMerkleRoot = hashMerkleRoot; - block.hashFinalSaplingRoot = hashFinalSaplingRoot; - block.nTime = nTime; - block.nBits = nBits; - block.nNonce = nNonce; - block.nSolution = nSolution; - return block; - } + //! Get the block header for this block index. Requires cs_main. + CBlockHeader GetBlockHeader() const; + + //! Clear the Equihash solution to save memory. Requires cs_main. + void TrimSolution(); uint256 GetBlockHash() const { + assert(phashBlock); return *phashBlock; } @@ -311,12 +318,19 @@ class CBlockIndex enum { nMedianTimeSpan=11 }; + /*** + * @note times are stored as a 4 byte int. Although this returns int64_t, it will be at + * 32 bit resolution. + * @note storing this as 32 bits can cause a "Year 2038" problem. + * @returns the median time (uinx epoch) of the last nMedianTimeSpan (currently 11) blocks + */ int64_t GetMedianTimePast() const { int64_t pmedian[nMedianTimeSpan]; int64_t* pbegin = &pmedian[nMedianTimeSpan]; int64_t* pend = &pmedian[nMedianTimeSpan]; + // grab the times of the last 11 blocks const CBlockIndex* pindex = this; for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev) *(--pbegin) = pindex->GetBlockTime(); @@ -327,10 +341,11 @@ class CBlockIndex std::string ToString() const { - return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)", + return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s, HasSolution=%s)", pprev, nHeight, hashMerkleRoot.ToString(), - GetBlockHash().ToString()); + phashBlock ? GetBlockHash().ToString() : "(nil)", + HasSolution()); } //! Check whether this block index entry is valid up to the passed validity level. @@ -342,6 +357,12 @@ class CBlockIndex return ((nStatus & BLOCK_VALID_MASK) >= nUpTo); } + //! Is the Equihash solution stored? + bool HasSolution() const + { + return !nSolution.empty(); + } + //! Raise the validity level of this block index entry. //! Returns true if the validity was changed. bool RaiseValidity(enum BlockStatus nUpTo) @@ -374,8 +395,11 @@ class CDiskBlockIndex : public CBlockIndex hashPrev = uint256(); } - explicit CDiskBlockIndex(const CBlockIndex* pindex) : CBlockIndex(*pindex) { + explicit CDiskBlockIndex(const CBlockIndex* pindex, std::function()> getSolution) : CBlockIndex(*pindex) { hashPrev = (pprev ? pprev->GetBlockHash() : uint256()); + if (!HasSolution()) { + nSolution = getSolution(); + } } ADD_SERIALIZE_METHODS; @@ -432,36 +456,51 @@ class CDiskBlockIndex : public CBlockIndex } // leave the existing LABS exemption here for segid and notary pay, but also add a timestamp activated segid for non LABS PoS64 chains. - if ( (s.GetType() & SER_DISK) && is_STAKED(ASSETCHAINS_SYMBOL) != 0 && ASSETCHAINS_NOTARY_PAY[0] != 0 ) + if ( (s.GetType() & SER_DISK) && isStakedAndNotaryPay() /*is_STAKED(chainName.symbol()) != 0 && ASSETCHAINS_NOTARY_PAY[0] != 0*/ ) { READWRITE(nNotaryPay); } - if ( (s.GetType() & SER_DISK) && ASSETCHAINS_STAKED != 0 && (nTime > nStakedDecemberHardforkTimestamp || is_STAKED(ASSETCHAINS_SYMBOL) != 0) ) //December 2019 hardfork + if ( (s.GetType() & SER_DISK) && isStakedAndAfterDec2019(nTime) /*ASSETCHAINS_STAKED != 0 && (nTime > nStakedDecemberHardforkTimestamp || is_STAKED(chainName.symbol()) != 0)*/ ) //December 2019 hardfork { READWRITE(segid); } - - /*if ( (s.GetType() & SER_DISK) && (is_STAKED(ASSETCHAINS_SYMBOL) != 0) && ASSETCHAINS_NOTARY_PAY[0] != 0 ) - { - READWRITE(nNotaryPay); - READWRITE(segid); - }*/ } +private: + bool isStakedAndNotaryPay() const; + bool isStakedAndAfterDec2019(unsigned int nTime) const; + //! This method should not be called on a CDiskBlockIndex. + void TrimSolution() + { + assert(!"called CDiskBlockIndex::TrimSolution"); + } + +public: uint256 GetBlockHash() const { - CBlockHeader block; - block.nVersion = nVersion; - block.hashPrevBlock = hashPrev; - block.hashMerkleRoot = hashMerkleRoot; - block.hashFinalSaplingRoot = hashFinalSaplingRoot; - block.nTime = nTime; - block.nBits = nBits; - block.nNonce = nNonce; - block.nSolution = nSolution; - return block.GetHash(); + return GetBlockHeader().GetHash(); + } + + //! Get the block header for this block index. + CBlockHeader GetBlockHeader() const + { + CBlockHeader header; + header.nVersion = nVersion; + header.hashPrevBlock = hashPrev; + header.hashMerkleRoot = hashMerkleRoot; + header.hashFinalSaplingRoot = hashFinalSaplingRoot; + header.nTime = nTime; + header.nBits = nBits; + header.nNonce = nNonce; + header.nSolution = nSolution; + return header; } + std::vector GetSolution() const + { + assert(HasSolution()); + return nSolution; + } std::string ToString() const { @@ -476,46 +515,49 @@ class CDiskBlockIndex : public CBlockIndex /** An in-memory indexed chain of blocks. */ class CChain { -private: +protected: std::vector vChain; - CBlockIndex *lastTip; - + CBlockIndex *at(int nHeight) const REQUIRES(cs_main) + { + if (nHeight < 0 || nHeight >= (int)vChain.size()) + return NULL; + return vChain[nHeight]; + } public: /** Returns the index entry for the genesis block of this chain, or NULL if none. */ - CBlockIndex *Genesis() const { + CBlockIndex *Genesis() const REQUIRES(cs_main) { + AssertLockHeld(cs_main); return vChain.size() > 0 ? vChain[0] : NULL; } /** Returns the index entry for the tip of this chain, or NULL if none. */ - CBlockIndex *Tip() const { - return vChain.size() > 0 ? vChain[vChain.size() - 1] : NULL; + CBlockIndex *Tip() const REQUIRES(cs_main) { + AssertLockHeld(cs_main); + return vChain.size() > 0 ? vChain[vChain.size() - 1] : nullptr; } - /** Returns the last tip of the chain, or NULL if none. */ - CBlockIndex *LastTip() const { - return vChain.size() > 0 ? lastTip : NULL; - } - /** Returns the index entry at a particular height in this chain, or NULL if no such height exists. */ - CBlockIndex *operator[](int nHeight) const { - if (nHeight < 0 || nHeight >= (int)vChain.size()) - return NULL; - return vChain[nHeight]; + CBlockIndex *operator[](int nHeight) const REQUIRES(cs_main) { + AssertLockHeld(cs_main); + return at(nHeight); } /** Compare two chains efficiently. */ - friend bool operator==(const CChain &a, const CChain &b) { - return a.vChain.size() == b.vChain.size() && - a.vChain[a.vChain.size() - 1] == b.vChain[b.vChain.size() - 1]; + friend bool operator==(const CChain &a, const CChain &b) REQUIRES(cs_main) { + AssertLockHeld(cs_main); + return a.Height() == b.Height() && + a.Tip() == b.Tip(); } /** Efficiently check whether a block is present in this chain. */ - bool Contains(const CBlockIndex *pindex) const { + bool Contains(const CBlockIndex *pindex) const REQUIRES(cs_main) { + AssertLockHeld(cs_main); return (*this)[pindex->nHeight] == pindex; } /** Find the successor of a block in this chain, or NULL if the given index is not found or is the tip. */ - CBlockIndex *Next(const CBlockIndex *pindex) const { + CBlockIndex *Next(const CBlockIndex *pindex) const REQUIRES(cs_main) { + AssertLockHeld(cs_main); if (Contains(pindex)) return (*this)[pindex->nHeight + 1]; else @@ -523,18 +565,19 @@ class CChain { } /** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */ - int Height() const { + int Height() const REQUIRES(cs_main) { + AssertLockHeld(cs_main); return vChain.size() - 1; } /** Set/initialize a chain with a given tip. */ - void SetTip(CBlockIndex *pindex); + void SetTip(CBlockIndex *pindex) REQUIRES(cs_main); /** Return a CBlockLocator that refers to a block in this chain (by default the tip). */ - CBlockLocator GetLocator(const CBlockIndex *pindex = NULL) const; + CBlockLocator GetLocator(const CBlockIndex *pindex = NULL) const REQUIRES(cs_main); /** Find the last common block between this chain and a block index entry. */ - const CBlockIndex *FindFork(const CBlockIndex *pindex) const; + const CBlockIndex *FindFork(const CBlockIndex *pindex) const REQUIRES(cs_main); }; #endif // BITCOIN_CHAIN_H diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 7d54ffc4269..d53dcfdb567 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -21,12 +21,11 @@ #include "key_io.h" #include "main.h" #include "crypto/equihash.h" - +#include "komodo_globals.h" #include "util.h" #include "utilstrencodings.h" #include - #include #include "chainparamsseeds.h" @@ -134,9 +133,6 @@ class CMainParams : public CChainParams { consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nProtocolVersion = 170007; consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; - // The best chain should have at least this much work. - consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000000281b32ff3198a1"); - /** * The message start string is designed to be unlikely to occur in normal data. * The characters are rarely used upper ASCII, not valid as UTF-8, and produce @@ -197,11 +193,11 @@ class CMainParams : public CChainParams { */ // TODO: we need more seed crawlers from other community members - base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,60); - base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,85); - base58Prefixes[SECRET_KEY] = std::vector(1,188); - base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x88)(0xB2)(0x1E).convert_to_container >(); - base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x88)(0xAD)(0xE4).convert_to_container >(); + base58Prefixes[PUBKEY_ADDRESS] = {60}; + base58Prefixes[SCRIPT_ADDRESS] = {85}; + base58Prefixes[SECRET_KEY] = {188}; + base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x88, 0xb2, 0x1e}; + base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x88, 0xad, 0xe4}; // guarantees the first two characters, when base58 encoded, are "zc" base58Prefixes[ZCPAYMENT_ADDRRESS] = {22,154}; // guarantees the first 4 characters, when base58 encoded, are "ZiVK" @@ -221,7 +217,105 @@ class CMainParams : public CChainParams { fRequireStandard = true; fMineBlocksOnDemand = false; fTestnetToBeDeprecatedFieldRPC = false; - } + + checkpointData = { + boost::assign::map_list_of + + (0, consensus.hashGenesisBlock) + ( 50000, uint256S("0x00076e16d3fa5194da559c17cf9cf285e21d1f13154ae4f7c7b87919549345aa")) + ( 100000, uint256S("0x0f02eb1f3a4b89df9909fec81a4bd7d023e32e24e1f5262d9fc2cc36a715be6f")) + ( 150000, uint256S("0x0a817f15b9da636f453a7a01835cfc534ed1a55ce7f08c566471d167678bedce")) + ( 200000, uint256S("0x000001763a9337328651ca57ac487cc0507087be5838fb74ca4165ff19f0e84f")) + ( 250000, uint256S("0x0dd54ef5f816c7fde9d2b1c8c1a26412b3c761cc5dd3901fa5c4cd1900892fba")) + ( 300000, uint256S("0x000000fa5efd1998959926047727519ed7de06dcf9f2cd92a4f71e907e1312dc")) + ( 350000, uint256S("0x0000000228ef321323f81dae00c98d7960fc7486fb2d881007fee60d1e34653f")) + ( 400000, uint256S("0x036d294c5be96f4c0efb28e652eb3968231e87204a823991a85c5fdab3c43ae6")) + ( 450000, uint256S("0x0906ef1e8dc194f1f03bd4ce1ac8c6992fd721ef2c5ccbf4871ec8cdbb456c18")) + ( 500000, uint256S("0x0bebdb417f7a51fe0c36fcf94e2ed29895a9a862eaa61601272866a7ecd6391b")) + ( 550000, uint256S("0x06df52fc5f9ba03ccc3a7673b01ab47990bd5c4947f6e1bc0ba14d21cd5bcccd")) + ( 600000, uint256S("0x00000005080d5689c3b4466e551cd1986e5d2024a62a79b1335afe12c42779e4")) + ( 650000, uint256S("0x039a3cb760cc6e564974caf69e8ae621c14567f3a36e4991f77fd869294b1d52")) + ( 700000, uint256S("0x00002285be912b2b887a5bb42d2f1aa011428c565b0ffc908129c47b5ce87585")) + ( 750000, uint256S("0x04cff4c26d185d591bed3613ce15e1d15d9c91dd8b98a6729f89c58ce4bd1fd6")) + ( 800000, uint256S("0x0000000617574d402fca8e6570f0845bd5fe449398b318b4e1f65bc69cdd6606")) + ( 850000, uint256S("0x044199301f37194f20ba7b498fc72ed742f6c0ba6e476f28d6c81d225e58d5ce")) + ( 900000, uint256S("0x08bdbe4de2a65ac89fd2913192d05362c900e3af476a0c99d9f311875067451e")) + ( 950000, uint256S("0x0000000aa9a44b593e6138f247bfae75bd43b9396ef9ff0a6a3ebd852f131806")) + ( 1000000, uint256S("0x0cb1d2457eaa58af5028e86e27ac54578fa09558206e7b868ebd35e7005ed8bb")) + ( 1050000, uint256S("0x044d49bbc3bd9d32b6288b768d4f7e0afe3cbeda606f3ac3579a076e4bddf6ae")) + ( 1100000, uint256S("0x000000050cad04887e170059dd2556d85bbd20390b04afb9b07fb62cafd647b4")) + ( 1150000, uint256S("0x0c85501c759d957dd1ccc5f7fdfcc415c89c7f2a26471fffc75b75f79e63c16a")) + ( 1200000, uint256S("0x0763cbf43ed7227988081c29d9e9fc7ab2450216e6d0354cc4596c86689702d4")) + ( 1250000, uint256S("0x0489640207f8c343a56a10e45d987516059ea82a3c6859a771b3a9cf94f5c3bb")) + ( 1300000, uint256S("0x000000012a01709b254b4f75e2b9ed772d8fe558655c8c859892ca8c9d625e87")) + ( 1350000, uint256S("0x075a1a5c66a68b47d9848ca6986687ed2665b1852457051bf142208e62f98a60")) + ( 1400000, uint256S("0x055f73dd9b20650c3d6e6dbb606af8d9479e4c81d89430867abff5329f167bb2")) + ( 1450000, uint256S("0x014c2926e07e9712211c5e82f05df1b802c59cc8bc24e3cc9b09942017080f2d")) + ( 1500000, uint256S("0x0791f892210ce3c513ab607d689cd1e8907a27f3dfeb58dec21ae299b7981cb7")) + ( 1550000, uint256S("0x08fcbaffb7164b161a25efc6dd5c70b679498ee637d663fe201a55c7decc37a3")) + ( 1600000, uint256S("0x0e577dcd49319a67fe2acbb39ae6d46afccd3009d3ba9d1bcf6c624708e12bac")) + ( 1650000, uint256S("0x091ac57a0f786a9526b2224a10b62f1f464b9ffc0afc2240d86264439e6ad3d0")) + ( 1700000, uint256S("0x0d0be6ab4a5083ce9d2a7ea2549b03cfc9770427b7d51c0bf0c603399a60d037")) + ( 1750000, uint256S("0x0a019d830157db596eeb678787279908093fd273a4e022b5e052f3a9f95714ca")) + ( 1800000, uint256S("0x0390779f6c615620391f9dd7df7f3f4947523bd6350b26625c0315571c616076")) + ( 1850000, uint256S("0x000000007ca2de1bd9cb7b52fe0accca4874143822521d955e58c73e304279e0")) + ( 1900000, uint256S("0x04c6589d5703f8237bf215c4e3e881c1c77063ef079cea5dc132a0e7f7a0cbd9")) + ( 1950000, uint256S("0x00000000386795b9fa21f14782ee1b9176763d6a544d7e0511d1860c62d540aa")) + ( 2000000, uint256S("0x0b0403fbe3c5742bbd0e3fc643049534e50c4a49bbc4a3b284fc0ecedf15c044")) + ( 2050000, uint256S("0x0c7923957469864d49a0be56b5ffbee7f21c1b6d00acc7374f60f1c1c7b87e14")) + ( 2100000, uint256S("0x05725ed166ae796529096ac2a42e85a3bdd0d69dbb2f69e620c08219fda1130a")) + ( 2150000, uint256S("0x0edb94f5a5501fc8dd72a455cdaccf0af0215b914dd3d8d4ae5d644e27ef562c")) + ( 2200000, uint256S("0x08b92203aa4a3b09001a75e8eebe8e64434259ae7ed7a31384203924d1ab03b8")) + ( 2250000, uint256S("0x0127d1ed5cd6f261631423275b6b17728c392583177e1151a6e638a4b0dea985")) + ( 2300000, uint256S("0x07df8af646bc30c71d068b146d9ea2c8b25b27a180e9537d5aef859efcfc41f7")) + ( 2350000, uint256S("0x0b8028dbfcd92fe34496953872cba2d256923e3e52b4abbdcbe9911071e929e5")) + ( 2395555, uint256S("0x0a09f16d886ed8152aaa2e2fcdf6ab4bb142ff8ce5abac131c5eda385a5d712f")), + 1621188001, // * UNIX timestamp of last checkpoint block + 13903562, // * total number of transactions between genesis and last checkpoint + // (the tx=... number in the SetBestChain debug.log lines) + 2777 // * estimated number of transactions per day after checkpoint + // total number of tx / (checkpoint block height / (24 * 24)) + }; + + genesisNotaries = { + { "jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, + { "jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" }, + { "pondsea_SH", "02209073bc0943451498de57f802650311b1f12aa6deffcd893da198a544c04f36" }, + { "crackers_EU", "0340c66cf2c41c41efb420af57867baa765e8468c12aa996bfd816e1e07e410728" }, + { "pondsea_EU", "0225aa6f6f19e543180b31153d9e6d55d41bc7ec2ba191fd29f19a2f973544e29d" }, + { "locomb_EU", "025c6d26649b9d397e63323d96db42a9d3caad82e1d6076970efe5056c00c0779b" }, + { "fullmoon_AE", "0204a908350b8142698fdb6fabefc97fe0e04f537adc7522ba7a1e8f3bec003d4a" }, + { "movecrypto_EU", "021ab53bc6cf2c46b8a5456759f9d608966eff87384c2b52c0ac4cc8dd51e9cc42" }, + { "badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, + { "crackers_NA", "029e1c01131974f4cd3f564cc0c00eb87a0f9721043fbc1ca60f9bd0a1f73f64a1" }, + { "proto_EU", "03681ffdf17c8f4f0008cefb7fa0779c5e888339cdf932f0974483787a4d6747c1" }, // 10 + { "jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, + { "farl4web_EU", "035caa40684ace968677dca3f09098aa02b70e533da32390a7654c626e0cf908e1" }, + { "nxtswe_EU", "032fb104e5eaa704a38a52c126af8f67e870d70f82977e5b2f093d5c1c21ae5899" }, + { "traderbill_EU", "03196e8de3e2e5d872f31d79d6a859c8704a2198baf0af9c7b21e29656a7eb455f" }, + { "vanbreuk_EU", "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" }, // 15 + { "titomane_EU", "03517fcac101fed480ae4f2caf775560065957930d8c1facc83e30077e45bdd199" }, + { "supernet_AE", "029d93ef78197dc93892d2a30e5a54865f41e0ca3ab7eb8e3dcbc59c8756b6e355" }, + { "supernet_EU", "02061c6278b91fd4ac5cab4401100ffa3b2d5a277e8f71db23401cc071b3665546" }, + { "supernet_NA", "033c073366152b6b01535e15dd966a3a8039169584d06e27d92a69889b720d44e1" }, + { "yassin_EU", "033fb7231bb66484081952890d9a03f91164fb27d392d9152ec41336b71b15fbd0" }, // 20 + { "durerus_EU", "02bcbd287670bdca2c31e5d50130adb5dea1b53198f18abeec7211825f47485d57" }, + { "badass_SH", "026b49dd3923b78a592c1b475f208e23698d3f085c4c3b4906a59faf659fd9530b" }, + { "badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, + { "pondsea_NA", "031bcfdbb62268e2ff8dfffeb9ddff7fe95fca46778c77eebff9c3829dfa1bb411" }, + { "rnr_EU", "0287aa4b73988ba26cf6565d815786caf0d2c4af704d7883d163ee89cd9977edec" }, + { "crackers_SH", "02313d72f9a16055737e14cfc528dcd5d0ef094cfce23d0348fe974b6b1a32e5f0" }, + { "grewal_SH", "03212a73f5d38a675ee3cdc6e82542a96c38c3d1c79d25a1ed2e42fcf6a8be4e68" }, + { "polycryptoblock_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, + { "titomane_NA", "0387046d9745414fb58a0fa3599078af5073e10347e4657ef7259a99cb4f10ad47" }, + { "titomane_AE", "03cda6ca5c2d02db201488a54a548dbfc10533bdc275d5ea11928e8d6ab33c2185" }, + { "kolo_EU", "03f5c08dadffa0ffcafb8dd7ffc38c22887bd02702a6c9ac3440deddcf2837692b" }, + { "artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, + { "eclips_EU", "0339369c1f5a2028d44be7be6f8ec3b907fdec814f87d2dead97cab4edb71a42e9" }, + { "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" }, + }; + + } // ctor }; static CMainParams mainParams; @@ -256,7 +350,7 @@ class CTestNetParams : public CChainParams { public: CTestNetParams() { strNetworkID = "test"; - strCurrencyUnits = "TAZ"; + strCurrencyUnits = "TKMD"; bip44CoinType = 1; consensus.fCoinbaseMustBeProtected = true; consensus.nSubsidySlowStartInterval = 20000; @@ -264,8 +358,8 @@ class CTestNetParams : public CChainParams { consensus.nMajorityEnforceBlockUpgrade = 51; consensus.nMajorityRejectBlockOutdated = 75; consensus.nMajorityWindow = 400; - consensus.powLimit = uint256S("07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); - consensus.powAlternate = uint256S("07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + consensus.powLimit = uint256S("0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"); + consensus.powAlternate = uint256S("0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"); consensus.nPowAveragingWindow = 17; assert(maxUint/UintToArith256(consensus.powLimit) >= consensus.nPowAveragingWindow); consensus.nMaxFutureBlockTime = 7 * 60; @@ -291,9 +385,6 @@ class CTestNetParams : public CChainParams { consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nProtocolVersion = 170007; consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = 280000; - // The best chain should have at least this much work. - consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000000000001d0c4d9cd"); - pchMessageStart[0] = 0x5A; pchMessageStart[1] = 0x1F; pchMessageStart[2] = 0x7E; @@ -308,22 +399,20 @@ class CTestNetParams : public CChainParams { nEquihashK = K; //! Modify the testnet genesis block so the timestamp is valid for a later start. - genesis.nTime = 1296688602; - genesis.nBits = KOMODO_MINDIFF_NBITS; - genesis.nNonce = uint256S("0x0000000000000000000000000000000000000000000000000000000000000009"); - genesis.nSolution = ParseHex("003423da3e41f916bf3ff0ee770eb844a240361abe08a8c9d46bd30226e2ad411a4047b6ddc230d173c60537e470e24f764120f5a2778b2a1285b0727bf79a0b085ad67e6266fb38fd72ef17f827315c42f921720248c983d4100e6ebd1c4b5e8762a973bac3bec7f7153b93752ebbb465f0fc9520bcfc30f9abfe303627338fed6ede9cf1b9173a736cf270cf4d9c6999ff4c3a301a78fd50dab6ccca67a0c5c2e41f216a1f3efd049a74bbe6252f9773bc309d3f9e554d996913ce8e1cec672a1fa4ea59726b61ea9e75d5ce9aa5dbfa96179a293810e02787f26de324fe7c88376ff57e29574a55faff7c2946f3e40e451861c32bf67da7377de3136858a18f34fab1bc8da37726ca2c25fc7b312a5427554ec944da81c7e27255d6c94ade9987ff7daedc2d1cc63d7d4cf93e691d13326fb1c7ee72ccdc0b134eb665fc6a9821e6fef6a6d45e4aac6dca6b505a0100ad56ea4f6fa4cdc2f0d1b65f730104a515172e34163bdb422f99d083e6eb860cf6b3f66642c4dbaf0d0fa1dca1b6166f1d1ffaa55a9d6d6df628afbdd14f1622c1c8303259299521a253bc28fcc93676723158067270fc710a09155a1e50c533e9b79ed5edba4ab70a08a9a2fc0eef0ddae050d75776a9804f8d6ad7e30ccb66c6a98d86710ca7a4dfb4feb159484796b9a015c5764aa3509051c87f729b9877ea41f8b470898c01388ed9098b1e006d3c30fc6e7c781072fa3f75d918505ee8ca75840fc62f67c57060666aa42578a2dd022eda62e3f1e447d7364074d34fd60ad9b138f60422afa6cfcb913fd6c213b496144dbfda7bfc7c24540cfe40ad0c0fd5a8c0902127f53d3178ba1b2a87bf1224d53d3a15e49ccdf121ae872a011c996d1b9793153cdcd4c0a7e99f8a35669788551cca2b62769eda24b6b55e2f4e0ac0d30aa50ecf33c6cdb24adfc922006a7bf434ced800fefe814c94c6fc8caa37b372d5088bb31d2f6b11a7a67ad3f70abbac0d5c256b637828de6cc525978cf151a2e50798e0c591787639a030291272c9ced3ab7d682e03f8c7db51f60163baa85315789666ea8c5cd6f789a7f4a5de4f8a9dfefce20f353cec606492fde8eab3e3b487b3a3a57434f8cf252a4b643fc125c8a5948b06744f5dc306aa587bdc85364c7488235c6edddd78763675e50a9637181519be06dd30c4ba0d845f9ba320d01706fd6dd64d1aa3cd4211a4a7d1d3f2c1ef2766d27d5d2cdf8e7f5e3ea309d4f149bb737305df1373a7f5313abe5986f4aa620bec4b0065d48aafac3631de3771f5c4d2f6eec67b09d9c70a3c1969fecdb014cb3c69832b63cc9d6efa378bff0ef95ffacdeb1675bb326e698f022c1a3a2e1c2b0f05e1492a6d2b7552388eca7ee8a2467ef5d4207f65d4e2ae7e33f13eb473954f249d7c20158ae703e1accddd4ea899f026618695ed2949715678a32a153df32c08922fafad68b1895e3b10e143e712940104b3b352369f4fe79bd1f1dbe03ea9909dbcf5862d1f15b3d1557a6191f54c891513cdb3c729bb9ab08c0d4c35a3ed67d517ffe1e2b7a798521aed15ff9822169c0ec860d7b897340bc2ef4c37f7eb73bd7dafef12c4fd4e6f5dd3690305257ae14ed03df5e3327b68467775a90993e613173fa6650ffa2a26e84b3ce79606bf234eda9f4053307f344099e3b10308d3785b8726fd02d8e94c2759bebd05748c3fe7d5fe087dc63608fb77f29708ab167a13f32da251e249a544124ed50c270cfc6986d9d1814273d2f0510d0d2ea335817207db6a4a23ae9b079967b63b25cb3ceea7001b65b879263f5009ac84ab89738a5b8b71fd032beb9f297326f1f5afa630a5198d684514e242f315a4d95fa6802e82799a525bb653b80b4518ec610a5996403b1391"); + genesis = CreateGenesisBlock(1296688602, + uint256S("0x000000000000000000000000000000000000000000000000000000000000000a"), + ParseHex("008b6bd48ca3ef23bfa3d34885483158e089ad887539fd33950f2d78d5720e39769165aa7b2c679b65060e209249f54e3279e8bf31ec13781184b109aaee6e3db57260b466ce8182122b564ce43ca77b011ea1fa038f0139e98e923b0eb1929a80b622cdb72cd5505f275b7cf0e89892ff37f53b010f5ba1fb78bedead4a0c4d39f8319605d358e36a0a0e5e5cdb25a2ffff9320f57569f7270857e2d87287fa71c24d36611b2ac502ffffdbbe425ca71b09b1f0255a66f26356fae7f210227d79e3ea9fe99f7d5e5b05febdf3a54dfec02507bdb85ff409773ce56441191734059a11d9d4c481554fbe6c93b1a93be2cfc707d146e4c28966de5ced066fc85f548fd146c9cd086fafdbf982c3c099394e0a25a5e4670dea2673e84886f5fa765a8a5f1ff3a307680a20e520b1f3d21714eb3efca769f182106a6d193aae881461a64b55d98668eb7f7b92c3527eb75b044d01ffff427d9157c301e5b69fa09776009f53c30551484020fabbb3d664c106d72844b540c133bc67048ad4ca0082ad42848e146dac76b55e3ba51937c412c817034e1e67fb3d909347d42d198599f28df8ee0fa9bd9c180beb0fad03f265a8bbbfb6ce1bff1d8223c9ea28748983393fbf1b8364e449d331b8ffb8363dfab5728c5f34b1e4cd03e3a758c3e5280994a44a47fed5f84b13bc67df9074dac4b7288d927e1b8ef50a7afc01ea4b798d6025415f26d15dc506c96896b530af775fb3648ddf983f59bb10536e1e74a6bee4640ed3275bbdceb79520ec81618ac7087e06baba12432671e185b6e1706523edd26d07435bf5289c5f703f0b6703fbfc56e46b421ca9ca325e281387353daa33274925b44ea4a7c939ef13ec6f38941ed13c7a9ae5253dba2119a0b8b1401f73d503e2c7252dd9507d305cf9dcb5f3db29214bb6c7be8b5654421baefbdc7701408f5ab4d652879d54e4e4ad6dc3c1b49835ae7e2ca806e302d33657ada2c8b86b716a239d409fafdb05a547952f6aafd5d9dd60f76070b0ee12605815ad36fca1c3bc231b15428ce6412fd37d2f27255eb19b060aadf47e0c1b67b0911459505bc9fdfd1875fdac31362dd434ab4e297b9478b74f5efdaac35e7b3deb07b2125aaf07483dd104d6e43161506a0e1b14fd7a13b729f771ca5e2a5e53c2d6eb96f66a66a4581c87018fa98856630ab1dead01afbe62c280c697d96e6d056afb94a4cca2e6d63bc866f5dceb9a5d2a38b3bb11e109de75d17e6116aad2514b5ababe09f99ddf2c130cdd7866129fa103cdb2ec9d2a44853c8bf9c31201ec1b89cca7f31542da558f57645c4e897e9e9d1038be3a796eaf1cafa8f6d69897426c5e7b8f3933c004eb3113898ac5295fb31245494b63fdf5227ece5714a13469fd86ec944b8b9924cc67ab86561f73fdb3060c8acf9a255ca96834038ef1383f69733876bc7f2524ebe92eb01049bc6863835220a555e496bb17e7067d3427f209fb00a46e48082a549af2fdd23cc7cc0b96923fd695642389a1db1a457ac5874f7c5c62e407ba7a7248f04807c516c0ba5c08194d3f1b1fa78f0841f062529d5d9354091d8fb9fecb777df7bd3508174f66a13f1d7d272cd4145762b25841ae9c3e9351209ac43d2dcb542d4ccd64b19367b56d7772fed9b00630fe9567036fd4bb1d67d2665c12c2547fd4a112128512ea4bf1d9d1f68d421c3bde90d8c22cde1aa40a257a8a0089b9b4e8aff50fb2d41cf152be7ecc892ffaa22d162a50e1f24be74207756c46370531cf9f07094d789c8758f9260214cbe6463376cc6f5fb26211740a59a68a97d27bb7e152f91d0ff8f431d3569e08420d79e957df36d4e2c601406046df386abf944f19730acd2b4bbd715cd321c7f54c8e61bf2cf73019"), + KOMODO_MINDIFF_NBITS, 1, COIN); consensus.hashGenesisBlock = genesis.GetHash(); - //assert(consensus.hashGenesisBlock == uint256S("0x05a60a92d99d85997cce3b87616c089f6124d7342af37106edc76126334a2c38")); vFixedSeeds.clear(); vSeeds.clear(); - //vSeeds.push_back(CDNSSeedData("z.cash", "dns.testnet.z.cash")); // Komodo - base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,0); - base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,5); - base58Prefixes[SECRET_KEY] = std::vector(1,128); - base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container >(); - base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container >(); + base58Prefixes[PUBKEY_ADDRESS] = {0}; + base58Prefixes[SCRIPT_ADDRESS] = {5}; + base58Prefixes[SECRET_KEY] = {128}; + base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF}; + base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94}; base58Prefixes[ZCPAYMENT_ADDRRESS] = {20,81}; // guarantees the first 4 characters, when base58 encoded, are "ZiVt" base58Prefixes[ZCVIEWING_KEY] = {0xA8,0xAC,0x0C}; @@ -343,15 +432,8 @@ class CTestNetParams : public CChainParams { fMineBlocksOnDemand = false; fTestnetToBeDeprecatedFieldRPC = true; - - checkpointData = (CCheckpointData) { - boost::assign::map_list_of - (0, consensus.hashGenesisBlock) - (38000, uint256S("0x001e9a2d2e2892b88e9998cf7b079b41d59dd085423a921fe8386cecc42287b8")), - 1486897419, // * UNIX timestamp of last checkpoint block - 47163, // * total number of transactions between genesis and last checkpoint - // (the tx=... number in the SetBestChain debug.log lines) - 715 // total number of tx / (checkpoint block height / (24 * 24)) + genesisNotaries = { + { "jmj_testA", "037c032430fd231b5797cb4a637dae3eadf87b10274fd84be31670bd2a02c4fbc5" } }; } }; @@ -396,9 +478,7 @@ class CRegTestParams : public CChainParams { consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nProtocolVersion = 170006; consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; - - // The best chain should have at least this much work. - consensus.nMinimumChainWork = uint256S("0x00"); + coinbaseMaturity = 1; pchMessageStart[0] = 0xaa; pchMessageStart[1] = 0x8e; @@ -416,8 +496,6 @@ class CRegTestParams : public CChainParams { 1296688602, uint256S("0x0000000000000000000000000000000000000000000000000000000000000009"), ParseHex("01936b7db1eb4ac39f151b8704642d0a8bda13ec547d54cd5e43ba142fc6d8877cab07b3"), - - KOMODO_MINDIFF_NBITS, 4, 0); consensus.hashGenesisBlock = genesis.GetHash(); assert(consensus.hashGenesisBlock == uint256S("0x029f11d80ef9765602235e1bc9727e3eb6ba20839319f761fee920d63401e327")); @@ -436,8 +514,9 @@ class CRegTestParams : public CChainParams { fTestnetToBeDeprecatedFieldRPC = false; checkpointData = (CCheckpointData){ - boost::assign::map_list_of - ( 0, uint256S("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")), + MapCheckpoints { + {0, uint256S("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")} + }, 0, 0, 0 @@ -572,10 +651,8 @@ void komodo_setactivation(int32_t height) void *chainparams_commandline() { - fprintf(stderr,"chainparams_commandline called\n"); CChainParams::CCheckpointData checkpointData; - //fprintf(stderr,">>>>>>>> port.%u\n",ASSETCHAINS_P2PPORT); - if ( ASSETCHAINS_SYMBOL[0] != 0 ) + if ( !chainName.isKMD() ) { if ( ASSETCHAINS_BLOCKTIME != 60 ) { @@ -585,7 +662,6 @@ void *chainparams_commandline() pCurrentParams->SetDefaultPort(ASSETCHAINS_P2PPORT); if ( ASSETCHAINS_NK[0] != 0 && ASSETCHAINS_NK[1] != 0 ) { - //BOOST_STATIC_ASSERT(equihash_parameters_acceptable(ASSETCHAINS_NK[0], ASSETCHAINS_NK[1])); pCurrentParams->SetNValue(ASSETCHAINS_NK[0]); pCurrentParams->SetKValue(ASSETCHAINS_NK[1]); } @@ -597,82 +673,25 @@ void *chainparams_commandline() pCurrentParams->pchMessageStart[1] = (ASSETCHAINS_MAGIC >> 8) & 0xff; pCurrentParams->pchMessageStart[2] = (ASSETCHAINS_MAGIC >> 16) & 0xff; pCurrentParams->pchMessageStart[3] = (ASSETCHAINS_MAGIC >> 24) & 0xff; - fprintf(stderr,">>>>>>>>>> %s: p2p.%u rpc.%u magic.%08x %u %u coins\n",ASSETCHAINS_SYMBOL,ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,ASSETCHAINS_MAGIC,ASSETCHAINS_MAGIC,(uint32_t)ASSETCHAINS_SUPPLY); + fprintf(stderr,">>>>>>>>>> %s: p2p.%u rpc.%u magic.%08x %u %u coins\n",chainName.symbol().c_str(),ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,ASSETCHAINS_MAGIC,ASSETCHAINS_MAGIC,(uint32_t)ASSETCHAINS_SUPPLY); pCurrentParams->consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = ASSETCHAINS_SAPLING; pCurrentParams->consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = ASSETCHAINS_OVERWINTER; - checkpointData = //(Checkpoints::CCheckpointData) + checkpointData = { - boost::assign::map_list_of - (0, pCurrentParams->consensus.hashGenesisBlock), + MapCheckpoints { + { 0, pCurrentParams->consensus.hashGenesisBlock } + }, (int64_t)1231006505, (int64_t)1, - (double)2777 // * estimated number of transactions per day after checkpoint + (double)2777 // * estimated number of transactions per day after checkpoint // total number of tx / (checkpoint block height / (24 * 24)) }; } else { - checkpointData = // (Checkpoints::CCheckpointData) - { - boost::assign::map_list_of - - (0, pCurrentParams->consensus.hashGenesisBlock) - ( 50000, uint256S("0x00076e16d3fa5194da559c17cf9cf285e21d1f13154ae4f7c7b87919549345aa")) - ( 100000, uint256S("0x0f02eb1f3a4b89df9909fec81a4bd7d023e32e24e1f5262d9fc2cc36a715be6f")) - ( 150000, uint256S("0x0a817f15b9da636f453a7a01835cfc534ed1a55ce7f08c566471d167678bedce")) - ( 200000, uint256S("0x000001763a9337328651ca57ac487cc0507087be5838fb74ca4165ff19f0e84f")) - ( 250000, uint256S("0x0dd54ef5f816c7fde9d2b1c8c1a26412b3c761cc5dd3901fa5c4cd1900892fba")) - ( 300000, uint256S("0x000000fa5efd1998959926047727519ed7de06dcf9f2cd92a4f71e907e1312dc")) - ( 350000, uint256S("0x0000000228ef321323f81dae00c98d7960fc7486fb2d881007fee60d1e34653f")) - ( 400000, uint256S("0x036d294c5be96f4c0efb28e652eb3968231e87204a823991a85c5fdab3c43ae6")) - ( 450000, uint256S("0x0906ef1e8dc194f1f03bd4ce1ac8c6992fd721ef2c5ccbf4871ec8cdbb456c18")) - ( 500000, uint256S("0x0bebdb417f7a51fe0c36fcf94e2ed29895a9a862eaa61601272866a7ecd6391b")) - ( 550000, uint256S("0x06df52fc5f9ba03ccc3a7673b01ab47990bd5c4947f6e1bc0ba14d21cd5bcccd")) - ( 600000, uint256S("0x00000005080d5689c3b4466e551cd1986e5d2024a62a79b1335afe12c42779e4")) - ( 650000, uint256S("0x039a3cb760cc6e564974caf69e8ae621c14567f3a36e4991f77fd869294b1d52")) - ( 700000, uint256S("0x00002285be912b2b887a5bb42d2f1aa011428c565b0ffc908129c47b5ce87585")) - ( 750000, uint256S("0x04cff4c26d185d591bed3613ce15e1d15d9c91dd8b98a6729f89c58ce4bd1fd6")) - ( 800000, uint256S("0x0000000617574d402fca8e6570f0845bd5fe449398b318b4e1f65bc69cdd6606")) - ( 850000, uint256S("0x044199301f37194f20ba7b498fc72ed742f6c0ba6e476f28d6c81d225e58d5ce")) - ( 900000, uint256S("0x08bdbe4de2a65ac89fd2913192d05362c900e3af476a0c99d9f311875067451e")) - ( 950000, uint256S("0x0000000aa9a44b593e6138f247bfae75bd43b9396ef9ff0a6a3ebd852f131806")) - ( 1000000, uint256S("0x0cb1d2457eaa58af5028e86e27ac54578fa09558206e7b868ebd35e7005ed8bb")) - ( 1050000, uint256S("0x044d49bbc3bd9d32b6288b768d4f7e0afe3cbeda606f3ac3579a076e4bddf6ae")) - ( 1100000, uint256S("0x000000050cad04887e170059dd2556d85bbd20390b04afb9b07fb62cafd647b4")) - ( 1150000, uint256S("0x0c85501c759d957dd1ccc5f7fdfcc415c89c7f2a26471fffc75b75f79e63c16a")) - ( 1200000, uint256S("0x0763cbf43ed7227988081c29d9e9fc7ab2450216e6d0354cc4596c86689702d4")) - ( 1250000, uint256S("0x0489640207f8c343a56a10e45d987516059ea82a3c6859a771b3a9cf94f5c3bb")) - ( 1300000, uint256S("0x000000012a01709b254b4f75e2b9ed772d8fe558655c8c859892ca8c9d625e87")) - ( 1350000, uint256S("0x075a1a5c66a68b47d9848ca6986687ed2665b1852457051bf142208e62f98a60")) - ( 1400000, uint256S("0x055f73dd9b20650c3d6e6dbb606af8d9479e4c81d89430867abff5329f167bb2")) - ( 1450000, uint256S("0x014c2926e07e9712211c5e82f05df1b802c59cc8bc24e3cc9b09942017080f2d")) - ( 1500000, uint256S("0x0791f892210ce3c513ab607d689cd1e8907a27f3dfeb58dec21ae299b7981cb7")) - ( 1550000, uint256S("0x08fcbaffb7164b161a25efc6dd5c70b679498ee637d663fe201a55c7decc37a3")) - ( 1600000, uint256S("0x0e577dcd49319a67fe2acbb39ae6d46afccd3009d3ba9d1bcf6c624708e12bac")) - ( 1650000, uint256S("0x091ac57a0f786a9526b2224a10b62f1f464b9ffc0afc2240d86264439e6ad3d0")) - ( 1700000, uint256S("0x0d0be6ab4a5083ce9d2a7ea2549b03cfc9770427b7d51c0bf0c603399a60d037")) - ( 1750000, uint256S("0x0a019d830157db596eeb678787279908093fd273a4e022b5e052f3a9f95714ca")) - ( 1800000, uint256S("0x0390779f6c615620391f9dd7df7f3f4947523bd6350b26625c0315571c616076")) - ( 1850000, uint256S("0x000000007ca2de1bd9cb7b52fe0accca4874143822521d955e58c73e304279e0")) - ( 1900000, uint256S("0x04c6589d5703f8237bf215c4e3e881c1c77063ef079cea5dc132a0e7f7a0cbd9")) - ( 1950000, uint256S("0x00000000386795b9fa21f14782ee1b9176763d6a544d7e0511d1860c62d540aa")) - ( 2000000, uint256S("0x0b0403fbe3c5742bbd0e3fc643049534e50c4a49bbc4a3b284fc0ecedf15c044")) - ( 2050000, uint256S("0x0c7923957469864d49a0be56b5ffbee7f21c1b6d00acc7374f60f1c1c7b87e14")) - ( 2100000, uint256S("0x05725ed166ae796529096ac2a42e85a3bdd0d69dbb2f69e620c08219fda1130a")) - ( 2150000, uint256S("0x0edb94f5a5501fc8dd72a455cdaccf0af0215b914dd3d8d4ae5d644e27ef562c")) - ( 2200000, uint256S("0x08b92203aa4a3b09001a75e8eebe8e64434259ae7ed7a31384203924d1ab03b8")) - ( 2250000, uint256S("0x0127d1ed5cd6f261631423275b6b17728c392583177e1151a6e638a4b0dea985")) - ( 2300000, uint256S("0x07df8af646bc30c71d068b146d9ea2c8b25b27a180e9537d5aef859efcfc41f7")) - ( 2350000, uint256S("0x0b8028dbfcd92fe34496953872cba2d256923e3e52b4abbdcbe9911071e929e5")) - ( 2395555, uint256S("0x0a09f16d886ed8152aaa2e2fcdf6ab4bb142ff8ce5abac131c5eda385a5d712f")), - 1621188001, // * UNIX timestamp of last checkpoint block - 13903562, // * total number of transactions between genesis and last checkpoint - // (the tx=... number in the SetBestChain debug.log lines) - 2777 // * estimated number of transactions per day after checkpoint - // total number of tx / (checkpoint block height / (24 * 24)) - }; + checkpointData = pCurrentParams->Checkpoints(); } pCurrentParams->SetCheckpointData(checkpointData); diff --git a/src/chainparams.h b/src/chainparams.h index daa16af8c40..30eb9f56572 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -30,11 +30,17 @@ #include +/**** + * DNS seed info + */ struct CDNSSeedData { std::string name, host; CDNSSeedData(const std::string &strName, const std::string &strHost) : name(strName), host(strHost) {} }; +/**** + * IPv6 seed info + */ struct SeedSpec6 { uint8_t addr[16]; uint16_t port; @@ -82,62 +88,151 @@ class CChainParams MAX_BECH32_TYPES }; + /**** + * @returns parameters that influence chain consensus + */ const Consensus::Params& GetConsensus() const { return consensus; } + /*** + * Message header start bytes + * @returns 4 bytes + */ const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; } + /**** + * @returns bytes of public key that signs broadcast alert messages + */ const std::vector& AlertKey() const { return vAlertPubKey; } + /*** + * @returns default TCP port for P2P connections + */ int GetDefaultPort() const { return nDefaultPort; } + /*** + * @returns the first block of the chain + */ const CBlock& GenesisBlock() const { return genesis; } - /** Make miner wait to have peers to avoid wasting work */ + /** + * Make miner wait to have peers to avoid wasting work + * @returns true if peers are required before mining begins + */ bool MiningRequiresPeers() const { return fMiningRequiresPeers; } - /** Default value for -checkmempool and -checkblockindex argument */ + /** + * Default value for -checkmempool and -checkblockindex argument + * @returns true if mempool and indexes should be checked by default + */ bool DefaultConsistencyChecks() const { return fDefaultConsistencyChecks; } - /** Policy: Filter transactions that do not match well-defined patterns */ + /** + * Policy: Filter transactions that do not match well-defined patterns + * @returns true to filter, false to be permissive + */ bool RequireStandard() const { return fRequireStandard; } + /**** + * @returns height where pruning should happen + */ int64_t PruneAfterHeight() const { return nPruneAfterHeight; } + /**** + * @returns N value for equihash algo + */ unsigned int EquihashN() const { return nEquihashN; } + /*** + * @returns K value for equihash algo + */ unsigned int EquihashK() const { return nEquihashK; } + /**** + * @returns currency units (i.e. "KMD", "REG", "TAZ" + */ std::string CurrencyUnits() const { return strCurrencyUnits; } + /**** + * @ref https://github.com/satoshilabs/slips/blob/master/slip-0044.md + * @returns coin identifier for this chain + */ uint32_t BIP44CoinType() const { return bip44CoinType; } - /** Make miner stop after a block is found. In RPC, don't return until nGenProcLimit blocks are generated */ + /** + * Make miner stop after a block is found. In RPC, don't return until nGenProcLimit blocks are generated + * @returns true if on-demand block mining is allowed (true for RegTest, should probably be false for all others) + */ bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; } - /** In the future use NetworkIDString() for RPC fields */ + /** + * Deprecated. Use NetworkIDString() to identify the network + * @returns true if testnet + */ bool TestnetToBeDeprecatedFieldRPC() const { return fTestnetToBeDeprecatedFieldRPC; } - /** Return the BIP70 network string (main, test or regtest) */ + /** + * Return the BIP70 network string ("main", "test" or "regtest") + * @returns the network ID + */ std::string NetworkIDString() const { return strNetworkID; } + /**** + * @returns a vector of DNS entries to get seed data + */ const std::vector& DNSSeeds() const { return vSeeds; } + /*** + * @param the type (i.e. PUBKEY_ADDRESS, SCRIPT_ADDRESS) + * @returns prefix bytes to common encoded strings + */ const std::vector& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; } + /**** + * @returns the Human Readable Part of a particular type of Bech32 data + */ const std::string& Bech32HRP(Bech32Type type) const { return bech32HRPs[type]; } + /**** + * Use in case of problems with DNS + * @returns hard-coded IPv6 addresses of seed nodes + */ const std::vector& FixedSeeds() const { return vFixedSeeds; } + const std::vector > GenesisNotaries() const { return genesisNotaries; } const CCheckpointData& Checkpoints() const { return checkpointData; } - /** Return the founder's reward address and script for a given block height */ + /** + * @returns the founder's reward address for a given block height + */ std::string GetFoundersRewardAddressAtHeight(int height) const; + /*** + * @returns the founder's reward script for a given block height + */ CScript GetFoundersRewardScriptAtHeight(int height) const; + /*** + * @param i the index + * @returns the founder's reward address + */ std::string GetFoundersRewardAddressAtIndex(int i) const; - /** Enforce coinbase consensus rule in regtest mode */ + /** + * Enforce coinbase consensus rule in regtest mode + */ void SetRegTestCoinbaseMustBeProtected() { consensus.fCoinbaseMustBeProtected = true; } + /*** + * Set the default P2P IP port + * @param port the new port + */ void SetDefaultPort(uint16_t port) { nDefaultPort = port; } + /*** + * @param checkpointData the new data + */ void SetCheckpointData(CCheckpointData checkpointData); + /*** + * @param n the new N value for equihash + */ void SetNValue(uint64_t n) { nEquihashN = n; } + /**** + * @param k the new K value for equihash + */ void SetKValue(uint64_t k) { nEquihashK = k; } + /**** + * @param flag true to require connected peers before mining can begin + */ void SetMiningRequiresPeers(bool flag) { fMiningRequiresPeers = flag; } + uint32_t CoinbaseMaturity() const { return coinbaseMaturity; } + void SetCoinbaseMaturity(uint32_t in) const { coinbaseMaturity = in; } - //void setnonce(uint32_t nonce) { memcpy(&genesis.nNonce,&nonce,sizeof(nonce)); } - //void settimestamp(uint32_t timestamp) { genesis.nTime = timestamp; } - //void setgenesis(CBlock &block) { genesis = block; } - //void recalc_genesis(uint32_t nonce) { genesis = CreateGenesisBlock(ASSETCHAINS_TIMESTAMP, nonce, GENESIS_NBITS, 1, COIN); }; - CMessageHeader::MessageStartChars pchMessageStart; // jl777 moved - Consensus::Params consensus; + CMessageHeader::MessageStartChars pchMessageStart; // message header start bytes + Consensus::Params consensus; // parameters that influence consensus protected: CChainParams() {} - //! Raw pub key bytes for the broadcast alert signing key. - std::vector vAlertPubKey; - int nMinerThreads = 0; + std::vector vAlertPubKey; // Raw pub key bytes for the broadcast alert signing key + int nMinerThreads = 0; // number of mining threads long nMaxTipAge = 0; - int nDefaultPort = 0; + int nDefaultPort = 0; // p2p uint64_t nPruneAfterHeight = 0; unsigned int nEquihashN = 0; unsigned int nEquihashK = 0; @@ -156,29 +251,42 @@ class CChainParams bool fTestnetToBeDeprecatedFieldRPC = false; CCheckpointData checkpointData; std::vector vFoundersRewardAddress; + mutable uint32_t coinbaseMaturity = 100; // allow to modify by -ac_cbmaturity + std::vector< std::pair > genesisNotaries; }; /** - * Return the currently selected parameters. This won't change after app - * startup, except for unit tests. + * NOTE: This won't change after app startup (except for unit tests) + * @returns the currently selected parameters for this chain */ const CChainParams &Params(); -/** Return parameters for the given network. */ +/** + * @param network the network + * @returns parameters for the given network. + */ CChainParams &Params(CBaseChainParams::Network network); -/** Sets the params returned by Params() to those for the given network. */ +/** + * Sets the params returned by Params() to those for the given network. + * @param network the network to use + */ void SelectParams(CBaseChainParams::Network network); /** * Looks for -regtest or -testnet and then calls SelectParams as appropriate. - * Returns false if an invalid combination is given. + * @returns false if an invalid combination is given. */ bool SelectParamsFromCommandLine(); /** * Allows modifying the network upgrade regtest parameters. + * @param idx the index of the new parameters + * @param nActivationHeight when to activate */ void UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex idx, int nActivationHeight); +void komodo_setactivation(int32_t height); +int32_t MAX_BLOCK_SIZE(int32_t height); + #endif // BITCOIN_CHAINPARAMS_H diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h index 94e3a42380d..0d6df592a66 100644 --- a/src/chainparamsbase.h +++ b/src/chainparamsbase.h @@ -38,7 +38,14 @@ class CBaseChainParams MAX_NETWORK_TYPES }; + /*** + * @brief returns the subdirectory for the network + * @return the data subdirectory ( nothing, or "testnet3" or "regtest" ) + */ const std::string& DataDir() const { return strDataDir; } + /**** + * @returns the port used for RPC calls + */ int RPCPort() const { return nRPCPort; } protected: @@ -49,29 +56,31 @@ class CBaseChainParams }; /** - * Return the currently selected parameters. This won't change after app - * startup, except for unit tests. + * NOTE: These params should not change after startup (except for unit tests) + * @returns the currently selected parameters */ const CBaseChainParams& BaseParams(); -/** Sets the params returned by Params() to those for the given network. */ +/** + * Sets the params returned by Params() to those for the given network. + * @param network the network you wish to use + */ void SelectBaseParams(CBaseChainParams::Network network); /** * Looks for -regtest or -testnet and returns the appropriate Network ID. - * Returns MAX_NETWORK_TYPES if an invalid combination is given. + * @returns Network ID or MAX_NETWORK_TYPES if an invalid combination is given */ CBaseChainParams::Network NetworkIdFromCommandLine(); /** * Calls NetworkIdFromCommandLine() and then calls SelectParams as appropriate. - * Returns false if an invalid combination is given. + * @returns false if an invalid combination is given. */ bool SelectBaseParamsFromCommandLine(); /** - * Return true if SelectBaseParamsFromCommandLine() has been called to select - * a network. + * @returns true if SelectBaseParamsFromCommandLine() has been called */ bool AreBaseParamsConfigured(); diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index 026475f8855..9ec509a260f 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -18,13 +18,9 @@ ******************************************************************************/ #include "checkpoints.h" - -#include "chainparams.h" #include "main.h" -#include "uint256.h" #include - #include namespace Checkpoints { @@ -38,17 +34,33 @@ namespace Checkpoints { * fast multicore CPU, it won't be much higher than 1. */ static const double SIGCHECK_VERIFICATION_FACTOR = 5.0; + + /****** + * @param data the collection of checkpoints + * @param nHeight the height + * @param hash the expected hash at nHight + * @returns true if the checkpoint at nHeight is not found or hash matches the found checkpoint + */ bool CheckBlock(const CChainParams::CCheckpointData& data, int nHeight, const uint256& hash) { const MapCheckpoints& checkpoints = data.mapCheckpoints; MapCheckpoints::const_iterator i = checkpoints.find(nHeight); - if (i == checkpoints.end()) return true; + if (i == checkpoints.end()) + return true; return hash == i->second; } - //! Guess how far we are in the verification process at the given block index - double GuessVerificationProgress(const CChainParams::CCheckpointData& data, CBlockIndex *pindex, bool fSigchecks) { + /****** + * @brief Guess how far we are in the verification process at the given block index + * @param data the checkpoint collection + * @param pindex the block index + * @param fsigchecks true to include signature checks in the calculation + * @returns + */ + double GuessVerificationProgress(const CChainParams::CCheckpointData& data, + CBlockIndex *pindex, bool fSigchecks) + { if (pindex==NULL) return 0.0; @@ -77,6 +89,11 @@ namespace Checkpoints { return std::min(fWorkBefore / (fWorkBefore + fWorkAfter), 1.0); } + /***** + * @brief Return conservative estimate of total number of blocks, 0 if unknown + * @param data the collection of checkpoints + * @returns the number of blocks + */ int GetTotalBlocksEstimate(const CChainParams::CCheckpointData& data) { const MapCheckpoints& checkpoints = data.mapCheckpoints; @@ -87,6 +104,10 @@ namespace Checkpoints { return checkpoints.rbegin()->first; } + /****** + * @param data the collection of checkpoints + * @returns last CBlockIndex* in mapBlockIndex that is a checkpoint (can be nullptr) + */ CBlockIndex* GetLastCheckpoint(const CChainParams::CCheckpointData& data) { const MapCheckpoints& checkpoints = data.mapCheckpoints; @@ -98,7 +119,7 @@ namespace Checkpoints { if (t != mapBlockIndex.end()) return t->second; } - return NULL; + return nullptr; } } // namespace Checkpoints diff --git a/src/checkpoints.h b/src/checkpoints.h index 1b21755f034..92ed70201cb 100644 --- a/src/checkpoints.h +++ b/src/checkpoints.h @@ -34,26 +34,36 @@ struct CCheckpointData; */ namespace Checkpoints { - - typedef std::map MapCheckpoints; - -struct CCheckpointData { - MapCheckpoints mapCheckpoints; - int64_t nTimeLastCheckpoint; - int64_t nTransactionsLastCheckpoint; - double fTransactionsPerDay; -}; + /****** + * @param data the collection of checkpoints + * @param nHeight the height + * @param hash the expected hash at nHight + * @returns true if the checkpoint at nHeight is not found or hash matches the found checkpoint + */ bool CheckBlock(const CChainParams::CCheckpointData& data, int nHeight, const uint256& hash); - -//! Return conservative estimate of total number of blocks, 0 if unknown + /***** + * @brief Return conservative estimate of total number of blocks, 0 if unknown + * @param data the collection of checkpoints + * @returns the total number of blocks + */ int GetTotalBlocksEstimate(const CChainParams::CCheckpointData& data); -//! Returns last CBlockIndex* in mapBlockIndex that is a checkpoint + /****** + * @param data the collection of checkpoints + * @returns last CBlockIndex* in mapBlockIndex that is a checkpoint (can be nullptr) + */ CBlockIndex* GetLastCheckpoint(const CChainParams::CCheckpointData& data); -double GuessVerificationProgress(const CChainParams::CCheckpointData& data, CBlockIndex* pindex, bool fSigchecks = true); + /****** + * @brief Guess how far we are in the verification process at the given block index + * @param data the checkpoint collection + * @param pindex the block index + * @param fsigchecks true to include signature checks in the calculation + * @returns + */ + double GuessVerificationProgress(const CChainParams::CCheckpointData& data, CBlockIndex* pindex, bool fSigchecks = true); -} //namespace Checkpoints +} // namespace Checkpoints #endif // BITCOIN_CHECKPOINTS_H diff --git a/src/clientversion.h b/src/clientversion.h index b8e6b4e7eec..17e0cce1f5f 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -31,8 +31,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 7 -#define CLIENT_VERSION_REVISION 2 +#define CLIENT_VERSION_MINOR 8 +#define CLIENT_VERSION_REVISION 0 #define CLIENT_VERSION_BUILD 0 //! Set to true for release, false for prerelease or test build @@ -42,7 +42,7 @@ * Copyright year (2009-this) * Todo: update this when changing our copyright comments in the source */ -#define COPYRIGHT_YEAR 2022 +#define COPYRIGHT_YEAR 2023 #endif //HAVE_CONFIG_H diff --git a/src/coins.cpp b/src/coins.cpp index eac89c030be..c2e7ff4c64a 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -25,6 +25,9 @@ #include "policy/fees.h" #include "komodo_defs.h" #include "importcoin.h" +#include "komodo_utils.h" +#include "komodo_bitcoind.h" +#include "komodo_interest.h" #include @@ -565,10 +568,6 @@ const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input) const return coins->vout[input.prevout.n]; } -//uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); -uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; - const CScript &CCoinsViewCache::GetSpendFor(const CCoins *coins, const CTxIn& input) { assert(coins); @@ -581,35 +580,39 @@ const CScript &CCoinsViewCache::GetSpendFor(const CTxIn& input) const return GetSpendFor(coins, input); } -CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t *interestp,const CTransaction& tx,uint32_t tiptime) const +/** + * @brief get amount of bitcoins coming in to a transaction + * @note lightweight clients may not know anything besides the hash of previous transactions, + * so may not be able to calculate this. + * @param[in] nHeight the chain height + * @param[out] interestp the interest found + * @param[in] tx transaction for which we are checking input total + * @returns Sum of value of all inputs (scriptSigs), (positive valueBalance or zero) and JoinSplit vpub_new + */ +CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t &interestp,const CTransaction& tx) const { CAmount value,nResult = 0; - if ( interestp != 0 ) - *interestp = 0; + interestp = 0; if ( tx.IsCoinImport() ) return GetCoinImportValue(tx); if ( tx.IsCoinBase() != 0 ) return 0; for (unsigned int i = 0; i < tx.vin.size(); i++) { - if (tx.IsPegsImport() && i==0) - { - nResult = GetCoinImportValue(tx); - continue; - } value = GetOutputFor(tx.vin[i]).nValue; nResult += value; #ifdef KOMODO_ENABLE_INTEREST - if ( ASSETCHAINS_SYMBOL[0] == 0 && nHeight >= 60000 ) + if ( chainName.isKMD() && nHeight >= 60000 ) { if ( value >= 10*COIN ) { - int64_t interest; int32_t txheight; uint32_t locktime; - interest = komodo_accrued_interest(&txheight,&locktime,tx.vin[i].prevout.hash,tx.vin[i].prevout.n,0,value,(int32_t)nHeight); - //printf("nResult %.8f += val %.8f interest %.8f ht.%d lock.%u tip.%u\n",(double)nResult/COIN,(double)value/COIN,(double)interest/COIN,txheight,locktime,tiptime); - //fprintf(stderr,"nResult %.8f += val %.8f interest %.8f ht.%d lock.%u tip.%u\n",(double)nResult/COIN,(double)value/COIN,(double)interest/COIN,txheight,locktime,tiptime); + int64_t interest; + int32_t txheight; + uint32_t locktime; + interest = komodo_accrued_interest(&txheight,&locktime,tx.vin[i].prevout.hash, + tx.vin[i].prevout.n,0,value,nHeight); nResult += interest; - (*interestp) += interest; + interestp += interest; } } #endif @@ -668,7 +671,6 @@ bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const { if (!tx.IsMint()) { for (unsigned int i = 0; i < tx.vin.size(); i++) { - if (tx.IsPegsImport() && i==0) continue; const COutPoint &prevout = tx.vin[i].prevout; const CCoins* coins = AccessCoins(prevout.hash); if (!coins || !coins->IsAvailable(prevout.n)) { @@ -690,7 +692,7 @@ double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight) const // use the maximum priority for all (partially or fully) shielded transactions. // (Note that coinbase transactions cannot contain JoinSplits, or Sapling shielded Spends or Outputs.) - if (tx.vjoinsplit.size() > 0 || tx.vShieldedSpend.size() > 0 || tx.vShieldedOutput.size() > 0 || tx.IsCoinImport() || tx.IsPegsImport()) { + if (tx.vjoinsplit.size() > 0 || tx.vShieldedSpend.size() > 0 || tx.vShieldedOutput.size() > 0 || tx.IsCoinImport()) { return MAX_PRIORITY; } diff --git a/src/coins.h b/src/coins.h index 0aace435f5c..d26dd792de7 100644 --- a/src/coins.h +++ b/src/coins.h @@ -470,7 +470,9 @@ class CTransactionExceptionData CTransactionExceptionData() : scriptPubKey(), voutMask() {} }; -/** CCoinsView that adds a memory cache for transactions to another CCoinsView */ +/** + * CCoinsView that adds a memory cache in front of another CCoinsView + */ class CCoinsViewCache : public CCoinsViewBacked { protected: @@ -555,14 +557,15 @@ class CCoinsViewCache : public CCoinsViewBacked size_t DynamicMemoryUsage() const; /** - * Amount of bitcoins coming in to a transaction - * Note that lightweight clients may not know anything besides the hash of previous transactions, + * @brief get amount of bitcoins coming in to a transaction + * @note lightweight clients may not know anything besides the hash of previous transactions, * so may not be able to calculate this. - * - * @param[in] tx transaction for which we are checking input total - * @return Sum of value of all inputs (scriptSigs), (positive valueBalance or zero) and JoinSplit vpub_new + * @param[in] nHeight the chain height + * @param[out] interestp the interest found + * @param[in] tx transaction for which we are checking input total + * @returns Sum of value of all inputs (scriptSigs), (positive valueBalance or zero) and JoinSplit vpub_new */ - CAmount GetValueIn(int32_t nHeight,int64_t *interestp,const CTransaction& tx,uint32_t prevblocktime) const; + CAmount GetValueIn(int32_t nHeight,int64_t &interestp,const CTransaction& tx) const; //! Check whether all prevouts of the transaction are present in the UTXO set represented by this view bool HaveInputs(const CTransaction& tx) const; diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index eba39b64422..32b340325ae 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -40,8 +40,6 @@ extern unsigned int MAX_BLOCK_SIGOPS; /** The maximum size of a transaction (network rule) */ static const unsigned int MAX_TX_SIZE_BEFORE_SAPLING = 100000; static const unsigned int MAX_TX_SIZE_AFTER_SAPLING = (2 * MAX_TX_SIZE_BEFORE_SAPLING); //MAX_BLOCK_SIZE; -/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */ -extern int COINBASE_MATURITY; /** The minimum value which is invalid for expiry height, used by CTransaction and CMutableTransaction */ static constexpr uint32_t TX_EXPIRY_HEIGHT_THRESHOLD = 500000000; diff --git a/src/consensus/params.h b/src/consensus/params.h index ba122098fba..e6566d21193 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -109,33 +109,40 @@ struct Params { NetworkUpgrade vUpgrades[MAX_NETWORK_UPGRADES]; /** Proof of work parameters */ - uint256 powLimit; - uint256 powAlternate; + uint256 powLimit; // minimum dificulty limit if EQUIHASH used + uint256 powAlternate; // minimum dificulty limit if EQUIHASH not used boost::optional nPowAllowMinDifficultyBlocksAfterHeight; boost::optional nHF22Height; uint32_t nHF22NotariesPriorityRotateDelta; - int64_t nPowAveragingWindow; - int64_t nPowMaxAdjustDown; - int64_t nPowMaxAdjustUp; - int64_t nPowTargetSpacing; - int64_t nLwmaAjustedWeight; + int64_t nPowAveragingWindow; // lookback window to determine block production speed averages + int64_t nPowMaxAdjustDown; // max percentage difficulty level should be lowered + int64_t nPowMaxAdjustUp; // max percentage difficulty level should be raised + int64_t nPowTargetSpacing; // the target block production speed (in seconds) /* Proof of stake parameters */ uint256 posLimit; int64_t nPOSAveragingWindow; // can be completely different than POW and initially trying a relatively large number, like 100 int64_t nPOSTargetSpacing; // spacing is 1000 units per block to get better resolution, (100 % = 1000, 50% = 2000, 10% = 10000) - int64_t nLwmaPOSAjustedWeight; /* applied to all block times */ int64_t nMaxFutureBlockTime; + /***** + * @returns How long the entire lookback window should take given target values + */ int64_t AveragingWindowTimespan() const { return nPowAveragingWindow * nPowTargetSpacing; } + /**** + * @returns the minimum time the lookback window should take before difficulty should be raised + */ int64_t MinActualTimespan() const { return (AveragingWindowTimespan() * (100 - nPowMaxAdjustUp )) / 100; } + /***** + * @returns the maximum time the lookback window should take before the difficulty should be lowered + */ int64_t MaxActualTimespan() const { return (AveragingWindowTimespan() * (100 + nPowMaxAdjustDown)) / 100; } void SetSaplingHeight(int32_t height) { vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = height; } void SetOverwinterHeight(int32_t height) { vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = height; } - uint256 nMinimumChainWork; }; + } // namespace Consensus #endif // BITCOIN_CONSENSUS_PARAMS_H diff --git a/src/consensus/upgrades.cpp b/src/consensus/upgrades.cpp index b75e0c002c1..79d337e4d30 100644 --- a/src/consensus/upgrades.cpp +++ b/src/consensus/upgrades.cpp @@ -18,16 +18,6 @@ ******************************************************************************/ #include "consensus/upgrades.h" -extern int32_t KOMODO_NSPV; -#define NSPV_BRANCHID 0x76b809bb - -#ifndef KOMODO_NSPV_FULLNODE -#define KOMODO_NSPV_FULLNODE (KOMODO_NSPV <= 0) -#endif // !KOMODO_NSPV_FULLNODE - -#ifndef KOMODO_NSPV_SUPERLITE -#define KOMODO_NSPV_SUPERLITE (KOMODO_NSPV > 0) -#endif // !KOMODO_NSPV_SUPERLITE /** * General information about each network upgrade. @@ -107,6 +97,12 @@ int CurrentEpoch(int nHeight, const Consensus::Params& params) { return Consensus::BASE_SPROUT; } +#define NSPV_BRANCHID 0x76b809bb +extern int32_t KOMODO_NSPV; +#ifndef KOMODO_NSPV_SUPERLITE +#define KOMODO_NSPV_SUPERLITE (KOMODO_NSPV > 0) +#endif + uint32_t CurrentEpochBranchId(int nHeight, const Consensus::Params& params) { if ( KOMODO_NSPV_SUPERLITE ) diff --git a/src/crosschain.cpp b/src/crosschain.cpp index 094451f69d7..28076221db3 100644 --- a/src/crosschain.cpp +++ b/src/crosschain.cpp @@ -17,11 +17,13 @@ #include "crosschain.h" #include "importcoin.h" #include "main.h" -#include "notarisationdb.h" #include "merkleblock.h" #include "hex.h" - +#include "komodo_bitcoind.h" #include "cc/CCinclude.h" +#include "komodo_notary.h" +#include "notarisationdb.h" +#include "cc/import.h" /* * The crosschain workflow. @@ -44,11 +46,80 @@ int NOTARISATION_SCAN_LIMIT_BLOCKS = 1440; -CBlockIndex *komodo_getblockindex(uint256 hash); +/**** + * Determine the type of crosschain + * @param symbol the asset chain to check + * @returns the type of chain + */ +CrosschainType CrossChain::GetSymbolAuthority(const std::string& symbol) +{ + if (symbol.find("TXSCL") == 0) + return CROSSCHAIN_TXSCL; + + if (is_STAKED(symbol.c_str()) != 0) + return CROSSCHAIN_STAKED; + + return CROSSCHAIN_KOMODO; +} + +/*** + * @param tx the transaction to check + * @param auth the authority object + * @returns true on success + */ +bool CrossChain::CheckTxAuthority(const CTransaction &tx, CrosschainAuthority auth) +{ + if (tx.vin.size() < auth.requiredSigs) + return false; + + uint8_t seen[64] = {0}; + for(const CTxIn &txIn : tx.vin) // check each vIn + { + // Get notary pubkey + CTransaction tx; + uint256 hashBlock; + EvalRef eval; + if (!eval->GetTxUnconfirmed(txIn.prevout.hash, tx, hashBlock)) + return false; + if (tx.vout.size() < txIn.prevout.n) + return false; + CScript spk = tx.vout[txIn.prevout.n].scriptPubKey; + if (spk.size() != 35) + return false; + const unsigned char *pk = &spk[0]; + if (pk++[0] != 33) + return false; + if (pk[33] != OP_CHECKSIG) + return false; + + // Check it's a notary + for (int i=0; i &moms, uint256 &destNotarisationTxid) { /* @@ -68,12 +139,11 @@ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeigh if (kmdHeight < 0 || kmdHeight > chainActive.Height()) return uint256(); - int seenOwnNotarisations = 0, i = 0; - - int authority = GetSymbolAuthority(symbol); + int seenOwnNotarisations = 0; + CrosschainType authority = GetSymbolAuthority(symbol); std::set tmp_moms; - for (i=0; i kmdHeight) break; NotarisationsInBlock notarisations; uint256 blockHash = *chainActive[kmdHeight-i]->phashBlock; @@ -81,7 +151,7 @@ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeigh continue; // See if we have an own notarisation in this block - BOOST_FOREACH(Notarisation& nota, notarisations) { + for(Notarisation& nota : notarisations) { if (strcmp(nota.second.symbol, symbol) == 0) { seenOwnNotarisations++; @@ -94,7 +164,7 @@ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeigh } if (seenOwnNotarisations >= 1) { - BOOST_FOREACH(Notarisation& nota, notarisations) { + for(Notarisation& nota : notarisations) { if (GetSymbolAuthority(nota.second.symbol) == authority) if (nota.second.ccId == targetCCid) { tmp_moms.insert(nota.second.MoM); @@ -113,15 +183,17 @@ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeigh // add set to vector. Set makes sure there are no dupes included. moms.clear(); std::copy(tmp_moms.begin(), tmp_moms.end(), std::back_inserter(moms)); - //fprintf(stderr, "SeenOwnNotarisations.%i moms.size.%li blocks scanned.%i\n",seenOwnNotarisations, moms.size(), i); return GetMerkleRoot(moms); } -/* - * Get a notarisation from a given height - * - * Will scan notarisations leveldb up to a limit +/***** + * @brief Get a notarisation from a given height + * @note Will scan notarisations leveldb up to a limit + * @param[in] nHeight the height + * @param[in] f + * @param[out] found + * @returns the height of the notarisation */ template int ScanNotarisationsFromHeight(int nHeight, const IsTarget f, Notarisation &found) @@ -135,8 +207,9 @@ int ScanNotarisationsFromHeight(int nHeight, const IsTarget f, Notarisation &fou if (!GetBlockNotarisations(*chainActive[h]->phashBlock, notarisations)) continue; - BOOST_FOREACH(found, notarisations) { - if (f(found)) { + for(auto entry : notarisations) { + if (f(entry)) { + found = entry; return h; } } @@ -144,9 +217,17 @@ int ScanNotarisationsFromHeight(int nHeight, const IsTarget f, Notarisation &fou return 0; } - -/* On KMD */ -TxProof GetCrossChainProof(const uint256 txid, const char* targetSymbol, uint32_t targetCCid, +/****** + * @brief + * @note this happens on the KMD chain + * @param txid + * @param targetSymbol + * @param targetCCid + * @param assetChainProof + * @param offset + * @returns a pair of target chain notarisation txid and the merkle branch + */ +TxProof CrossChain::GetCrossChainProof(const uint256 txid, const char* targetSymbol, uint32_t targetCCid, const TxProof assetChainProof, int32_t offset) { /* @@ -227,62 +308,53 @@ TxProof GetCrossChainProof(const uint256 txid, const char* targetSymbol, uint32_ } -/* - * Takes an importTx that has proof leading to assetchain root - * and extends proof to cross chain root +/***** + * @brief Takes an importTx that has proof leading to assetchain root and extends proof to cross chain root + * @param importTx + * @param offset */ -void CompleteImportTransaction(CTransaction &importTx, int32_t offset) +void CrossChain::CompleteImportTransaction(CTransaction &importTx, int32_t offset) { - ImportProof proof; CTransaction burnTx; std::vector payouts; std::vector rawproof; + ImportProof proof; + CTransaction burnTx; + std::vector payouts; + if (!UnmarshalImportTx(importTx, proof, burnTx, payouts)) throw std::runtime_error("Couldn't unmarshal importTx"); std::string targetSymbol; uint32_t targetCCid; uint256 payoutsHash; + std::vector rawproof; if (!UnmarshalBurnTx(burnTx, targetSymbol, &targetCCid, payoutsHash, rawproof)) throw std::runtime_error("Couldn't unmarshal burnTx"); TxProof merkleBranch; if( !proof.IsMerkleBranch(merkleBranch) ) throw std::runtime_error("Incorrect import tx proof"); - TxProof newMerkleBranch = GetCrossChainProof(burnTx.GetHash(), targetSymbol.data(), targetCCid, merkleBranch, offset); + TxProof newMerkleBranch = GetCrossChainProof(burnTx.GetHash(), targetSymbol.data(), + targetCCid, merkleBranch, offset); ImportProof newProof(newMerkleBranch); importTx = MakeImportCoinTransaction(newProof, burnTx, payouts); } +/***** + * @param nota the notarisation + * @returns true if the notarization belongs to this chain + */ bool IsSameAssetChain(const Notarisation ¬a) { - return strcmp(nota.second.symbol, ASSETCHAINS_SYMBOL) == 0; + return chainName.isSymbol(nota.second.symbol); }; - -/* On assetchain */ -bool GetNextBacknotarisation(uint256 kmdNotarisationTxid, Notarisation &out) -{ - /* - * Here we are given a txid, and a proof. - * We go from the KMD notarisation txid to the backnotarisation, - * then jump to the next backnotarisation, which contains the corresponding MoMoM. - */ - Notarisation bn; - if (!GetBackNotarisation(kmdNotarisationTxid, bn)) - return false; - - // Need to get block height of that backnotarisation - EvalRef eval; - CBlockIndex block; - CTransaction tx; - if (!eval->GetTxConfirmed(bn.first, tx, block)){ - fprintf(stderr, "Can't get height of backnotarisation, this should not happen\n"); - return false; - } - - return (bool) ScanNotarisationsFromHeight(block.nHeight+1, &IsSameAssetChain, out); -} - - -bool CheckMoMoM(uint256 kmdNotarisationHash, uint256 momom) +/**** + * @brief Check MoMoM + * @note on Assetchain + * @param kmdNotarisationHash the hash + * @param momom what to check + * @returns true on success + */ +bool CrossChain::CheckMoMoM(uint256 kmdNotarisationHash, uint256 momom) { /* * Given a notarisation hash and an MoMoM. Backnotarisations may arrive out of order @@ -313,14 +385,14 @@ bool CheckMoMoM(uint256 kmdNotarisationHash, uint256 momom) } -/* -* Check notaries approvals for the txoutproofs of burn tx -* (alternate check if MoMoM check has failed) -* Params: -* burntxid - txid of burn tx on the source chain -* rawproof - array of txids of notaries' proofs +/***** +* @brief Check notaries approvals for the txoutproofs of burn tx +* @note alternate check if MoMoM check has failed +* @param burntxid - txid of burn tx on the source chain +* @param notaryTxids txids of notaries' proofs +* @returns true on success */ -bool CheckNotariesApproval(uint256 burntxid, const std::vector & notaryTxids) +bool CrossChain::CheckNotariesApproval(uint256 burntxid, const std::vector & notaryTxids) { int count = 0; @@ -419,13 +491,14 @@ bool CheckNotariesApproval(uint256 burntxid, const std::vector & notary } -/* - * On assetchain - * in: txid - * out: pair +/***** + * @brief get the proof + * @note On assetchain + * @param hash + * @param burnTx + * @returns a pair containing the notarisation tx hash and the merkle branch */ - -TxProof GetAssetchainProof(uint256 hash,CTransaction burnTx) +TxProof CrossChain::GetAssetchainProof(uint256 hash,CTransaction burnTx) { int nIndex; CBlockIndex* blockIndex; diff --git a/src/crosschain.h b/src/crosschain.h index 25763c01b37..934ebc72a66 100644 --- a/src/crosschain.h +++ b/src/crosschain.h @@ -1,3 +1,4 @@ +#pragma once /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * @@ -12,15 +13,16 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - -#ifndef CROSSCHAIN_H -#define CROSSCHAIN_H - +/***** + * transfer or migrate assets from one chain to another + */ #include "cc/eval.h" -const int CROSSCHAIN_KOMODO = 1; -const int CROSSCHAIN_TXSCL = 2; -const int CROSSCHAIN_STAKED = 3; +enum CrosschainType { + CROSSCHAIN_KOMODO = 1, + CROSSCHAIN_TXSCL = 2, + CROSSCHAIN_STAKED = 3 +}; typedef struct CrosschainAuthority { uint8_t notaries[64][33]; @@ -28,21 +30,81 @@ typedef struct CrosschainAuthority { int8_t requiredSigs; } CrosschainAuthority; -int GetSymbolAuthority(const char* symbol); -bool CheckTxAuthority(const CTransaction &tx, CrosschainAuthority auth); +class CrossChain +{ +public: + /**** + * Determine the type of crosschain + * @param symbol the asset chain to check + * @returns the type of chain + */ + static CrosschainType GetSymbolAuthority(const std::string& symbol); + + /*** + * @param tx the transaction to check + * @param auth the authority object + * @returns true on success + */ + static bool CheckTxAuthority(const CTransaction &tx, CrosschainAuthority auth); + + /***** + * @brief get the proof + * @note On assetchain + * @param hash + * @param burnTx + * @returns a pair containing the notarisation tx hash and the merkle branch + */ + static TxProof GetAssetchainProof(uint256 hash,CTransaction burnTx); + + /***** + * @brief Calculate the proof root + * @note this happens on the KMD chain + * @param symbol the chain symbol + * @param targetCCid + * @param kmdHeight + * @param moms collection of MoMs + * @param destNotarisationTxid + * @returns the proof root, or 0 on error + */ + static uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeight, + std::vector &moms, uint256 &destNotarisationTxid); -/* On assetchain */ -TxProof GetAssetchainProof(uint256 hash,CTransaction burnTx); + /***** + * @brief Takes an importTx that has proof leading to assetchain root and extends proof to cross chain root + * @param importTx + * @param offset + */ + static void CompleteImportTransaction(CTransaction &importTx,int32_t offset); -/* On KMD */ -uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeight, - std::vector &moms, uint256 &destNotarisationTxid); -TxProof GetCrossChainProof(const uint256 txid, const char* targetSymbol, uint32_t targetCCid, - const TxProof assetChainProof,int32_t offset); -void CompleteImportTransaction(CTransaction &importTx,int32_t offset); + /**** + * @brief check the MoMoM + * @note on Assetchain + * @param kmdNotarisationHash the hash + * @param momom what to check + * @returns true on success + */ + static bool CheckMoMoM(uint256 kmdNotarisationHash, uint256 momom); -/* On assetchain */ -bool CheckMoMoM(uint256 kmdNotarisationHash, uint256 momom); -bool CheckNotariesApproval(uint256 burntxid, const std::vector & notaryTxids); + /***** + * @brief Check notaries approvals for the txoutproofs of burn tx + * @note alternate check if MoMoM check has failed + * @param burntxid - txid of burn tx on the source chain + * @param notaryTxids txids of notaries' proofs + * @returns true on success + */ + static bool CheckNotariesApproval(uint256 burntxid, const std::vector & notaryTxids); -#endif /* CROSSCHAIN_H */ +private: + /****** + * @brief + * @note this happens on the KMD chain + * @param txid + * @param targetSymbol + * @param targetCCid + * @param assetChainProof + * @param offset + * @returns a pair of target chain notarisation txid and the merkle branch + */ + static TxProof GetCrossChainProof(const uint256 txid, const char* targetSymbol, uint32_t targetCCid, + const TxProof assetChainProof,int32_t offset); +}; \ No newline at end of file diff --git a/src/crosschain_authority.cpp b/src/crosschain_authority.cpp deleted file mode 100644 index 7487e4879b5..00000000000 --- a/src/crosschain_authority.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "cc/eval.h" -#include "crosschain.h" -#include "notarisationdb.h" -#include "notaries_staked.h" - -int GetSymbolAuthority(const char* symbol) -{ - if (strncmp(symbol, "TXSCL", 5) == 0) - return CROSSCHAIN_TXSCL; - if (is_STAKED(symbol) != 0) { - //printf("RETURNED CROSSCHAIN STAKED AS TRUE\n"); - return CROSSCHAIN_STAKED; - } - //printf("RETURNED CROSSCHAIN KOMODO AS TRUE\n"); - return CROSSCHAIN_KOMODO; -} - - -bool CheckTxAuthority(const CTransaction &tx, CrosschainAuthority auth) -{ - EvalRef eval; - - if (tx.vin.size() < auth.requiredSigs) return false; - - uint8_t seen[64] = {0}; - - BOOST_FOREACH(const CTxIn &txIn, tx.vin) - { - // Get notary pubkey - CTransaction tx; - uint256 hashBlock; - if (!eval->GetTxUnconfirmed(txIn.prevout.hash, tx, hashBlock)) return false; - if (tx.vout.size() < txIn.prevout.n) return false; - CScript spk = tx.vout[txIn.prevout.n].scriptPubKey; - if (spk.size() != 35) return false; - const unsigned char *pk = &spk[0]; - if (pk++[0] != 33) return false; - if (pk[33] != OP_CHECKSIG) return false; - - // Check it's a notary - for (int i=0; i and it should be used (not on Ultrix). - */ -#undef HAVE_ALLOCA_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_ARPA_INET_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_DLFCN_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_FLOAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_INTTYPES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_LIMITS_H - -/* Define to 1 if you have the `localeconv' function. */ -#undef HAVE_LOCALECONV - -/* Define to 1 if you have the header file. */ -#undef HAVE_LOCALE_H - -/* Define to 1 if your system has a GNU libc compatible `malloc' function, and - to 0 otherwise. */ -#undef HAVE_MALLOC - -/* Define to 1 if you have the header file. */ -#undef HAVE_MALLOC_H - -/* Define to 1 if you have the `memchr' function. */ -#undef HAVE_MEMCHR - -/* Define to 1 if you have the header file. */ -#undef HAVE_MEMORY_H - -/* Define to 1 if you have the `memset' function. */ -#undef HAVE_MEMSET - -/* Define to 1 if you have the header file. */ -#undef HAVE_NETINET_IN_H - -/* Define to 1 if the system has the type `ptrdiff_t'. */ -#undef HAVE_PTRDIFF_T - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDDEF_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRING_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define to 1 if the system has the type `_Bool'. */ -#undef HAVE__BOOL - -/* Define to the sub-directory where libtool stores uninstalled libraries. */ -#undef LT_OBJDIR - -/* Name of package */ -#undef PACKAGE - -/* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#undef PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#undef PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME - -/* Define to the home page for this package. */ -#undef PACKAGE_URL - -/* Define to the version of this package. */ -#undef PACKAGE_VERSION - -/* If using the C implementation of alloca, define if you know the - direction of stack growth for your system; otherwise it will be - automatically deduced at runtime. - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ -#undef STACK_DIRECTION - -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* Version number of package */ -#undef VERSION - -/* Define for Solaris 2.5.1 so the uint32_t typedef from , - , or is not used. If the typedef were allowed, the - #define below would cause a syntax error. */ -#undef _UINT32_T - -/* Define for Solaris 2.5.1 so the uint64_t typedef from , - , or is not used. If the typedef were allowed, the - #define below would cause a syntax error. */ -#undef _UINT64_T - -/* Define for Solaris 2.5.1 so the uint8_t typedef from , - , or is not used. If the typedef were allowed, the - #define below would cause a syntax error. */ -#undef _UINT8_T - -/* Define to the type of a signed integer type of width exactly 16 bits if - such a type exists and the standard includes do not define it. */ -#undef int16_t - -/* Define to the type of a signed integer type of width exactly 32 bits if - such a type exists and the standard includes do not define it. */ -#undef int32_t - -/* Define to the type of a signed integer type of width exactly 8 bits if such - a type exists and the standard includes do not define it. */ -#undef int8_t - -/* Define to rpl_malloc if the replacement function should be used. */ -#undef malloc - -/* Define to `unsigned int' if does not define. */ -#undef size_t - -/* Define to `int' if does not define. */ -#undef ssize_t - -/* Define to the type of an unsigned integer type of width exactly 16 bits if - such a type exists and the standard includes do not define it. */ -#undef uint16_t - -/* Define to the type of an unsigned integer type of width exactly 32 bits if - such a type exists and the standard includes do not define it. */ -#undef uint32_t - -/* Define to the type of an unsigned integer type of width exactly 64 bits if - such a type exists and the standard includes do not define it. */ -#undef uint64_t - -/* Define to the type of an unsigned integer type of width exactly 8 bits if - such a type exists and the standard includes do not define it. */ -#undef uint8_t diff --git a/src/dbwrapper.h b/src/dbwrapper.h index 21f57d094e0..8dc5d69c071 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -154,6 +154,9 @@ class CDBIterator }; +/**** + * A wrapper around the leveldb database + */ class CDBWrapper { private: @@ -184,10 +187,19 @@ class CDBWrapper * @param[in] nCacheSize Configures various leveldb cache settings. * @param[in] fMemory If true, use leveldb's memory environment. * @param[in] fWipe If true, remove all existing data. + * @param[in] compression + * @param[in] maxOpenFiles */ - CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false, bool compression = false, int maxOpenFiles = 64); + CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory = false, + bool fWipe = false, bool compression = false, int maxOpenFiles = 64); ~CDBWrapper(); + /**** + * Retrieve the value for the given key + * @param key the key + * @param value where the results will be stored + * @returns true on success + */ template bool Read(const K& key, V& value) const { @@ -213,6 +225,13 @@ class CDBWrapper return true; } + /**** + * Write a value to a key + * @param key the key + * @param value the value + * @param fSync true to use sync option instead of just write + * @returns true on success + */ template bool Write(const K& key, const V& value, bool fSync = false) { @@ -221,6 +240,11 @@ class CDBWrapper return WriteBatch(batch, fSync); } + /*** + * Check to see if a key exists + * @param key the key + * @returns true if key exists + */ template bool Exists(const K& key) const { @@ -240,6 +264,12 @@ class CDBWrapper return true; } + /*** + * Erase a key from the db + * @param key the key + * @param fSync true to use sync option instead of just write + * @returns true on success + */ template bool Erase(const K& key, bool fSync = false) { @@ -248,27 +278,45 @@ class CDBWrapper return WriteBatch(batch, fSync); } + /*** + * Write a batch of transactions to the db + * @param batch the transactions + * @param fSync true to use sync option instead of just write + * @returns true on success + */ bool WriteBatch(CDBBatch& batch, bool fSync = false); - // not available for LevelDB; provide for compatibility with BDB + /**** + * not available for LevelDB; provided for compatibility with BDB + * @returns true always + */ bool Flush() { return true; } + /**** + * Synchronize the db + * @returns true on success + */ bool Sync() { CDBBatch batch(*this); return WriteBatch(batch, true); } + /*** + * Get a new iterator + * NOTE: you are responsible for deletion of the returned iterator + * @returns an iterator + */ CDBIterator *NewIterator() { return new CDBIterator(*this, pdb->NewIterator(iteroptions)); } /** - * Return true if the database managed by this class contains no entries. + * @returns true if the database managed by this class contains no entries. */ bool IsEmpty(); }; diff --git a/src/deprecation.cpp b/src/deprecation.cpp index 6005918ec66..93c1d8c76ea 100644 --- a/src/deprecation.cpp +++ b/src/deprecation.cpp @@ -25,9 +25,9 @@ #include "ui_interface.h" #include "util.h" #include "chainparams.h" +#include "komodo_globals.h" static const std::string CLIENT_VERSION_STR = FormatVersion(CLIENT_VERSION); -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; void EnforceNodeDeprecation(int nHeight, bool forceLogging, bool fThread) { @@ -35,7 +35,8 @@ void EnforceNodeDeprecation(int nHeight, bool forceLogging, bool fThread) { std::string networkID = Params().NetworkIDString(); std::string msg; - if (networkID != "main" || ASSETCHAINS_SYMBOL[0] != 0 ) return; + if (networkID != "main" || !chainName.isKMD() ) + return; int blocksToDeprecation = DEPRECATION_HEIGHT - nHeight; if (blocksToDeprecation <= 0) { diff --git a/src/deprecation.h b/src/deprecation.h index 387d23aecc2..25a0a6afdbc 100644 --- a/src/deprecation.h +++ b/src/deprecation.h @@ -24,7 +24,7 @@ // * Shut down WEEKS_UNTIL_DEPRECATION weeks' worth of blocks after the estimated release block height. // * A warning is shown during the DEPRECATION_WARN_LIMIT worth of blocks prior to shut down. static const int WEEKS_UNTIL_DEPRECATION = 52; -static const int DEPRECATION_HEIGHT = 3600000; //TODO: use [last_season_array_item - 1] + 650.000 for automagic update +static const int DEPRECATION_HEIGHT = 4320000; //TODO: use [last_season_array_item - 1] + 650.000 for automagic update static const int APPROX_RELEASE_HEIGHT = DEPRECATION_HEIGHT - (WEEKS_UNTIL_DEPRECATION * 7 * 24 * 60); // Number of blocks before deprecation to warn users diff --git a/src/gtest/test_block.cpp b/src/gtest/test_block.cpp deleted file mode 100644 index a0cdc11622b..00000000000 --- a/src/gtest/test_block.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include - -#include "primitives/block.h" - - -TEST(block_tests, header_size_is_expected) { - // Dummy header with an empty Equihash solution. - CBlockHeader header; - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << header; - - ASSERT_EQ(ss.size(), CBlockHeader::HEADER_SIZE); -} diff --git a/src/importcoin.cpp b/src/importcoin.cpp index c3da613c8a7..dfb80d6e240 100644 --- a/src/importcoin.cpp +++ b/src/importcoin.cpp @@ -23,15 +23,21 @@ #include "core_io.h" #include "script/sign.h" #include "wallet/wallet.h" - #include "cc/CCinclude.h" +#include "komodo_bitcoind.h" -int32_t komodo_nextheight(); -// makes import tx for either coins or tokens -CTransaction MakeImportCoinTransaction(const ImportProof proof, const CTransaction burnTx, const std::vector payouts, uint32_t nExpiryHeightOverride) +/****** + * @brief makes import tx for either coins or tokens + * @param proof the proof + * @param burnTx the inputs + * @param payouts the outputs + * @param nExpiryHeightOverride if an actual height (!= 0) makes a tx for validating int import tx + * @returns the generated import transaction + */ +CTransaction MakeImportCoinTransaction(const ImportProof proof, const CTransaction burnTx, + const std::vector payouts, uint32_t nExpiryHeightOverride) { - //std::vector payload = E_MARSHAL(ss << EVAL_IMPORTCOIN); CScript scriptSig; CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); @@ -75,20 +81,17 @@ CTransaction MakeImportCoinTransaction(const ImportProof proof, const CTransacti return CTransaction(mtx); } -CTransaction MakePegsImportCoinTransaction(const ImportProof proof, const CTransaction burnTx, const std::vector payouts, uint32_t nExpiryHeightOverride) -{ - CMutableTransaction mtx; uint256 accounttxid,pegstxid,tokenid; CScript opret; CScript scriptSig; - - mtx=MakeImportCoinTransaction(proof,burnTx,payouts); - // for spending markers in import tx - to track account state - accounttxid=burnTx.vin[0].prevout.hash; - mtx.vin.push_back(CTxIn(accounttxid,0,CScript())); - mtx.vin.push_back(CTxIn(accounttxid,1,CScript())); - return (mtx); -} - - -CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, const std::string targetSymbol, const std::vector payouts, const std::vector rawproof) +/****** + * @brief make a burn output + * @param value the amount + * @param targetCCid the ccid + * @param targetSymbol + * @param payouts the outputs + * @param rawproof the proof in binary form + * @returns the txout + */ +CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, const std::string& targetSymbol, + const std::vector payouts, const std::vector rawproof) { std::vector opret; opret = E_MARSHAL(ss << (uint8_t)EVAL_IMPORTCOIN; // should mark burn opret to differentiate it from token opret @@ -99,8 +102,28 @@ CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, const std::string targ return CTxOut(value, CScript() << OP_RETURN << opret); } -CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector payouts,std::vector rawproof, - uint256 bindtxid,std::vector publishers,std::vector txids,uint256 burntxid,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub, int64_t amount) +/****** + * @brief make a burn output + * @param value + * @param targetCCid the target ccid + * @param targetSymbol the target symbol + * @param payouts the outputs + * @param rawproof the proof in binary form + * @param bindtxid + * @param publishers + * @param txids + * @param burntxid + * @param height + * @param burnvout + * @param rawburntx + * @param destpub + * @param amount + * @returns the txout + */ +CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, const std::string& targetSymbol, + const std::vector payouts,std::vector rawproof, uint256 bindtxid, + std::vector publishers,std::vector txids,uint256 burntxid, + int32_t height,int32_t burnvout, const std::string& rawburntx,CPubKey destpub, int64_t amount) { std::vector opret; opret = E_MARSHAL(ss << (uint8_t)EVAL_IMPORTCOIN; @@ -121,8 +144,20 @@ CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymb return CTxOut(value, CScript() << OP_RETURN << opret); } -CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector payouts,std::vector rawproof,std::string srcaddr, - std::string receipt) +/****** + * @brief make a burn output + * @param value the amount + * @param targetCCid the ccid + * @param targetSymbol + * @param payouts the outputs + * @param rawproof the proof in binary form + * @param srcaddr the source address + * @param receipt + * @returns the txout + */ +CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, const std::string& targetSymbol, + const std::vector payouts,std::vector rawproof,const std::string& srcaddr, + const std::string& receipt) { std::vector opret; opret = E_MARSHAL(ss << (uint8_t)EVAL_IMPORTCOIN; @@ -135,30 +170,21 @@ CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymb return CTxOut(value, CScript() << OP_RETURN << opret); } -CTxOut MakeBurnOutput(CAmount value,uint32_t targetCCid,std::string targetSymbol,const std::vector payouts,std::vector rawproof,uint256 pegstxid, - uint256 tokenid,CPubKey srcpub,int64_t amount,std::pair account) -{ - std::vector opret; - opret = E_MARSHAL(ss << (uint8_t)EVAL_IMPORTCOIN; - ss << VARINT(targetCCid); - ss << targetSymbol; - ss << SerializeHash(payouts); - ss << rawproof; - ss << pegstxid; - ss << tokenid; - ss << srcpub; - ss << amount; - ss << account); - return CTxOut(value, CScript() << OP_RETURN << opret); -} - - -bool UnmarshalImportTx(const CTransaction importTx, ImportProof &proof, CTransaction &burnTx, std::vector &payouts) +/**** + * @brief break a serialized import tx into its components + * @param[in] importTx the transaction + * @param[out] proof the proof + * @param[out] burnTx the burn transaction + * @param[out] payouts the collection of tx outs + * @returns true on success + */ +bool UnmarshalImportTx(const CTransaction importTx, ImportProof &proof, CTransaction &burnTx, + std::vector &payouts) { if (importTx.vout.size() < 1) return false; - if ((!importTx.IsPegsImport() && importTx.vin.size() != 1) || importTx.vin[0].scriptSig != (CScript() << E_MARSHAL(ss << EVAL_IMPORTCOIN))) { + if (importTx.vin.size() != 1 || importTx.vin[0].scriptSig != (CScript() << E_MARSHAL(ss << EVAL_IMPORTCOIN))) { LOGSTREAM("importcoin", CCLOG_INFO, stream << "UnmarshalImportTx() incorrect import tx vin" << std::endl); return false; } @@ -203,15 +229,22 @@ bool UnmarshalImportTx(const CTransaction importTx, ImportProof &proof, CTransac return retcode; } - -bool UnmarshalBurnTx(const CTransaction burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash,std::vector&rawproof) +/**** + * @brief break a serialized burn tx into its components + * @param[in] burnTx the transaction + * @param[out] targetSymbol the symbol + * @param[out] targetCCid the target ccid + * @param[out] payoutsHash the hash of the payouts + * @param[out] rawproof the bytes of the proof + * @returns true on success + */ +bool UnmarshalBurnTx(const CTransaction burnTx, std::string &targetSymbol, uint32_t *targetCCid, + uint256 &payoutsHash,std::vector&rawproof) { - std::vector vburnOpret; uint32_t ccid = 0; - uint8_t evalCode; - if (burnTx.vout.size() == 0) return false; + std::vector vburnOpret; GetOpReturnData(burnTx.vout.back().scriptPubKey, vburnOpret); if (vburnOpret.empty()) { LOGSTREAM("importcoin", CCLOG_INFO, stream << "UnmarshalBurnTx() cannot unmarshal burn tx: empty burn opret" << std::endl); @@ -245,20 +278,33 @@ bool UnmarshalBurnTx(const CTransaction burnTx, std::string &targetSymbol, uint3 ss >> rawproof; isEof = ss.eof();) || !isEof; // if isEof == false it means we have successfully read the vars upto 'rawproof' // and it might be additional data further that we do not need here so we allow !isEof } - else { - LOGSTREAM("importcoin", CCLOG_INFO, stream << "UnmarshalBurnTx() invalid eval code in opret" << std::endl); - return false; - } + + LOGSTREAM("importcoin", CCLOG_INFO, stream << "UnmarshalBurnTx() invalid eval code in opret" << std::endl); + return false; } +/**** + * @brief break a serialized burn tx into its components + * @param[in] burnTx the transaction + * @param[out] srcaddr the source address + * @param[out] receipt + * @returns true on success + */ bool UnmarshalBurnTx(const CTransaction burnTx, std::string &srcaddr, std::string &receipt) { - std::vector burnOpret,rawproof; bool isEof=true; - std::string targetSymbol; uint32_t targetCCid; uint256 payoutsHash; + if (burnTx.vout.size() == 0) + return false; + + // parts of tx that are deserialized but not returned + std::vector rawproof; + std::string targetSymbol; + uint32_t targetCCid; + uint256 payoutsHash; uint8_t evalCode; - if (burnTx.vout.size() == 0) return false; + std::vector burnOpret; GetOpReturnData(burnTx.vout.back().scriptPubKey, burnOpret); + return (E_UNMARSHAL(burnOpret, ss >> evalCode; ss >> VARINT(targetCCid); ss >> targetSymbol; @@ -268,13 +314,36 @@ bool UnmarshalBurnTx(const CTransaction burnTx, std::string &srcaddr, std::strin ss >> receipt)); } -bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &bindtxid,std::vector &publishers,std::vector &txids,uint256& burntxid,int32_t &height,int32_t &burnvout,std::string &rawburntx,CPubKey &destpub, int64_t &amount) +/**** + * @brief break a serialized burn tx into its components + * @param[in] burnTx the transaction + * @param[out] bindtxid + * @param[out] publishers + * @param[out] txids + * @param[out] burntxid + * @param[out] height + * @param[out] burnvout + * @param[out] rawburntx + * @param[out] destpub + * @param[out] amount + * @returns true on success + */ +bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &bindtxid, + std::vector &publishers,std::vector &txids, + uint256& burntxid, int32_t &height,int32_t &burnvout, + std::string &rawburntx,CPubKey &destpub, int64_t &amount) { - std::vector burnOpret,rawproof; bool isEof=true; - uint32_t targetCCid; uint256 payoutsHash; std::string targetSymbol; + if (burnTx.vout.size() == 0) + return false; + + // parts of tx that are deserialized but not returned + std::vector rawproof; + uint32_t targetCCid; + uint256 payoutsHash; + std::string targetSymbol; uint8_t evalCode; - if (burnTx.vout.size() == 0) return false; + std::vector burnOpret; GetOpReturnData(burnTx.vout.back().scriptPubKey, burnOpret); return (E_UNMARSHAL(burnOpret, ss >> evalCode; ss >> VARINT(targetCCid); @@ -292,36 +361,18 @@ bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &bindtxid,std::vector> amount)); } -bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &pegstxid,uint256 &tokenid,CPubKey &srcpub, int64_t &amount,std::pair &account) -{ - std::vector burnOpret,rawproof; bool isEof=true; - uint32_t targetCCid; uint256 payoutsHash; std::string targetSymbol; - uint8_t evalCode; - - - if (burnTx.vout.size() == 0) return false; - GetOpReturnData(burnTx.vout.back().scriptPubKey, burnOpret); - return (E_UNMARSHAL(burnOpret, ss >> evalCode; - ss >> VARINT(targetCCid); - ss >> targetSymbol; - ss >> payoutsHash; - ss >> rawproof; - ss >> pegstxid; - ss >> tokenid; - ss >> srcpub; - ss >> amount; - ss >> account)); -} - -/* - * Required by main +/****** + * @brief get the value of the transaction + * @param tx the transaction + * @returns the burned value within tx */ CAmount GetCoinImportValue(const CTransaction &tx) { - ImportProof proof; CTransaction burnTx; std::vector payouts; - bool isNewImportTx = false; + ImportProof proof; + CTransaction burnTx; + std::vector payouts; - if ((isNewImportTx = UnmarshalImportTx(tx, proof, burnTx, payouts))) { + if ( UnmarshalImportTx(tx, proof, burnTx, payouts) ) { if (burnTx.vout.size() > 0) { vscript_t vburnOpret; @@ -331,7 +382,7 @@ CAmount GetCoinImportValue(const CTransaction &tx) return 0; } - if (isNewImportTx && vburnOpret.begin()[0] == EVAL_TOKENS) { //if it is tokens + if ( vburnOpret.begin()[0] == EVAL_TOKENS) { //if it is tokens uint8_t evalCodeInOpret; uint256 tokenid; @@ -365,17 +416,22 @@ CAmount GetCoinImportValue(const CTransaction &tx) -/* - * CoinImport is different enough from normal script execution that it's not worth +/***** + * @brief verify a coin import signature + * @note CoinImport is different enough from normal script execution that it's not worth * making all the mods neccesary in the interpreter to do the dispatch correctly. + * @param[in] scriptSig the signature + * @param[in] checker the checker to use + * @param[out] state the error state + * @returns true on success, `state` will contain the reason if false */ bool VerifyCoinImport(const CScript& scriptSig, TransactionSignatureChecker& checker, CValidationState &state) { auto pc = scriptSig.begin(); - opcodetype opcode; - std::vector evalScript; auto f = [&] () { + opcodetype opcode; + std::vector evalScript; if (!scriptSig.GetOp(pc, opcode, evalScript)) return false; if (pc != scriptSig.end()) @@ -394,29 +450,37 @@ bool VerifyCoinImport(const CScript& scriptSig, TransactionSignatureChecker& che return f() ? true : state.Invalid(false, 0, "invalid-coin-import"); } - +/**** + * @brief add an import tombstone + * @param importTx the transaction + * @param inputs the inputs to be modified + * @param nHeight the height + */ void AddImportTombstone(const CTransaction &importTx, CCoinsViewCache &inputs, int nHeight) { - uint256 burnHash = importTx.vin[0].prevout.hash; - //fprintf(stderr,"add tombstone.(%s)\n",burnHash.GetHex().c_str()); - CCoinsModifier modifier = inputs.ModifyCoins(burnHash); + CCoinsModifier modifier = inputs.ModifyCoins(importTx.vin[0].prevout.hash); modifier->nHeight = nHeight; - modifier->nVersion = 4;//1; + modifier->nVersion = 4; modifier->vout.push_back(CTxOut(0, CScript() << OP_0)); } - +/***** + * @brief remove an import tombstone from inputs + * @param importTx the transaction + * @param inputs what to modify + */ void RemoveImportTombstone(const CTransaction &importTx, CCoinsViewCache &inputs) { - uint256 burnHash = importTx.vin[0].prevout.hash; - //fprintf(stderr,"remove tombstone.(%s)\n",burnHash.GetHex().c_str()); - inputs.ModifyCoins(burnHash)->Clear(); + inputs.ModifyCoins(importTx.vin[0].prevout.hash)->Clear(); } - -int ExistsImportTombstone(const CTransaction &importTx, const CCoinsViewCache &inputs) +/***** + * @brief See if a tombstone exists + * @param importTx the transaction + * @param inputs + * @returns true if the transaction is a tombstone + */ +bool ExistsImportTombstone(const CTransaction &importTx, const CCoinsViewCache &inputs) { - uint256 burnHash = importTx.vin[0].prevout.hash; - //fprintf(stderr,"check tombstone.(%s) in %s\n",burnHash.GetHex().c_str(),importTx.GetHash().GetHex().c_str()); - return inputs.HaveCoins(burnHash); + return inputs.HaveCoins(importTx.vin[0].prevout.hash); } diff --git a/src/importcoin.h b/src/importcoin.h index 955ead8257a..fed69b45443 100644 --- a/src/importcoin.h +++ b/src/importcoin.h @@ -1,3 +1,4 @@ +#pragma once /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * @@ -12,10 +13,6 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - -#ifndef IMPORTCOIN_H -#define IMPORTCOIN_H - #include "cc/eval.h" #include "coins.h" #include "primitives/transaction.h" @@ -29,6 +26,12 @@ enum ProofKind : uint8_t { PROOF_MERKLEBLOCK = 0x13 }; +/***** + * Holds the proof. This can be one of 3 types: + * - Merkle branch + * - Notary TXIDs + * - Merkle block + */ class ImportProof { private: @@ -38,13 +41,28 @@ class ImportProof { std::vector proofBlock; public: + /**** + * @brief Default ctor + */ ImportProof() { proofKind = PROOF_NONE; } + /**** + * @brief Merkle branch proof ctor + * @param _proofBranch the Merkle branch + */ ImportProof(const TxProof &_proofBranch) { proofKind = PROOF_MERKLEBRANCH; proofBranch = _proofBranch; } + /**** + * @brief Notary TXID proof ctor + * @param _notaryTxids the collection of txids + */ ImportProof(const std::vector &_notaryTxids) { proofKind = PROOF_NOTARYTXIDS; notaryTxids = _notaryTxids; } + /***** + * @brief Merkle block proof ctor + * @param _proofBlock the Merkle block + */ ImportProof(const std::vector &_proofBlock) { proofKind = PROOF_MERKLEBLOCK; proofBlock = _proofBlock; } @@ -64,6 +82,10 @@ class ImportProof { proofKind = PROOF_NONE; // if we have read some trash } + /***** + * @param _proofBranch the merkle branch to store + * @returns true if this object is a Merkle branch ImportProof + */ bool IsMerkleBranch(TxProof &_proofBranch) const { if (proofKind == PROOF_MERKLEBRANCH) { _proofBranch = proofBranch; @@ -72,6 +94,11 @@ class ImportProof { else return false; } + + /***** + * @param _notaryTxids the txids to store + * @returns true if this object is a Notary TXID ImportProof + */ bool IsNotaryTxids(std::vector &_notaryTxids) const { if (proofKind == PROOF_NOTARYTXIDS) { _notaryTxids = notaryTxids; @@ -80,6 +107,11 @@ class ImportProof { else return false; } + + /***** + * @param _proofBlock the block to store + * @returns true if this object is a Merkle Block ImportProof + */ bool IsMerkleBlock(std::vector &_proofBlock) const { if (proofKind == PROOF_MERKLEBLOCK) { _proofBlock = proofBlock; @@ -90,36 +122,153 @@ class ImportProof { } }; - - +/****** + * @brief get the value of the transaction + * @param tx the transaction + * @returns the burned value within tx + */ CAmount GetCoinImportValue(const CTransaction &tx); +/****** + * @brief makes import tx for either coins or tokens + * @param proof the proof + * @param burnTx the inputs + * @param payouts the outputs + * @param nExpiryHeightOverride if an actual height (!= 0) makes a tx for validating int import tx + * @returns the generated import transaction + */ CTransaction MakeImportCoinTransaction(const ImportProof proof, const CTransaction burnTx, const std::vector payouts, uint32_t nExpiryHeightOverride = 0); -CTransaction MakePegsImportCoinTransaction(const ImportProof proof, const CTransaction burnTx, const std::vector payouts, uint32_t nExpiryHeightOverride = 0); -CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, const std::string targetSymbol, const std::vector payouts, const std::vector rawproof); -CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector payouts,std::vector rawproof, - uint256 bindtxid,std::vector publishers,std::vectortxids,uint256 burntxid,int32_t height,int32_t burnvout,std::string rawburntx,CPubKey destpub, int64_t amount); -CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, std::string targetSymbol, const std::vector payouts,std::vector rawproof,std::string srcaddr, - std::string receipt); -CTxOut MakeBurnOutput(CAmount value,uint32_t targetCCid,std::string targetSymbol,const std::vector payouts,std::vector rawproof,uint256 pegstxid, - uint256 tokenid,CPubKey srcpub,int64_t amount,std::pair account); +/****** + * @brief make a burn output + * @param value the amount + * @param targetCCid the ccid + * @param targetSymbol + * @param payouts the outputs + * @param rawproof + * @returns the txout + */ +CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, const std::string& targetSymbol, + const std::vector payouts, const std::vector rawproof); + +/****** + * @brief make a burn output + * @param value + * @param targetCCid the target ccid + * @param targetSymbol the target symbol + * @param payouts the outputs + * @param rawproof the proof in binary form + * @param bindtxid + * @param publishers + * @param txids + * @param burntxid + * @param height + * @param burnvout + * @param rawburntx + * @param destpub + * @param amount + * @returns the txout + */ +CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, const std::string& targetSymbol, + const std::vector payouts,std::vector rawproof, uint256 bindtxid, + std::vector publishers,std::vectortxids,uint256 burntxid,int32_t height, + int32_t burnvout,const std::string& rawburntx,CPubKey destpub, int64_t amount); -bool UnmarshalBurnTx(const CTransaction burnTx, std::string &targetSymbol, uint32_t *targetCCid, uint256 &payoutsHash,std::vector &rawproof); +/****** + * @brief make a burn output + * @param value the amount + * @param targetCCid the ccid + * @param targetSymbol + * @param payouts the outputs + * @param rawproof the proof in binary form + * @param srcaddr the source address + * @param receipt + * @returns the txout + */ +CTxOut MakeBurnOutput(CAmount value, uint32_t targetCCid, const std::string& targetSymbol, + const std::vector payouts,std::vector rawproof, const std::string& srcaddr, + const std::string& receipt); + +/**** + * @brief break a serialized burn tx into its components + * @param[in] burnTx the transaction + * @param[out] targetSymbol the symbol + * @param[out] targetCCid the target ccid + * @param[out] payoutsHash the hash of the payouts + * @param[out] rawproof the bytes of the proof + * @returns true on success + */ +bool UnmarshalBurnTx(const CTransaction burnTx, std::string &targetSymbol, uint32_t *targetCCid, + uint256 &payoutsHash,std::vector &rawproof); + +/**** + * @brief break a serialized burn tx into its components + * @param[in] burnTx the transaction + * @param[out] srcaddr the source address + * @param[out] receipt + * @returns true on success + */ bool UnmarshalBurnTx(const CTransaction burnTx, std::string &srcaddr, std::string &receipt); -bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &bindtxid,std::vector &publishers,std::vector &txids,uint256& burntxid,int32_t &height,int32_t &burnvout,std::string &rawburntx,CPubKey &destpub, int64_t &amount); -bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &pegstxid,uint256 &tokenid,CPubKey &srcpub,int64_t &amount,std::pair &account); -bool UnmarshalImportTx(const CTransaction importTx, ImportProof &proof, CTransaction &burnTx,std::vector &payouts); +/**** + * @brief break a serialized burn tx into its components + * @param[in] burnTx the transaction + * @param[out] bindtxid + * @param[out] publishers + * @param[out] txids + * @param[out] burntxid + * @param[out] height + * @param[out] burnvout + * @param[out] rawburntx + * @param[out] destpub + * @param[out] amount + * @returns true on success + */ +bool UnmarshalBurnTx(const CTransaction burnTx,uint256 &bindtxid,std::vector &publishers, + std::vector &txids,uint256& burntxid,int32_t &height,int32_t &burnvout, + std::string &rawburntx,CPubKey &destpub, int64_t &amount); + +/**** + * @brief break a serialized import tx into its components + * @param[in] importTx the transaction + * @param[out] proof the proof + * @param[out] burnTx the burn transaction + * @param[out] payouts the collection of tx outs + * @returns true on success + */ +bool UnmarshalImportTx(const CTransaction importTx, ImportProof &proof, + CTransaction &burnTx,std::vector &payouts); + +/***** + * @brief verify a coin import signature + * @note CoinImport is different enough from normal script execution that it's not worth + * making all the mods neccesary in the interpreter to do the dispatch correctly. + * @param[in] scriptSig the signature + * @param[in] checker the checker to use + * @param[out] state the error state + * @returns true on success, `state` will contain the reason if false + */ bool VerifyCoinImport(const CScript& scriptSig, TransactionSignatureChecker& checker, CValidationState &state); +/**** + * @brief add an import tombstone + * @param importTx the transaction + * @param inputs the inputs to be modified + * @param nHeight the height + */ void AddImportTombstone(const CTransaction &importTx, CCoinsViewCache &inputs, int nHeight); -void RemoveImportTombstone(const CTransaction &importTx, CCoinsViewCache &inputs); -int ExistsImportTombstone(const CTransaction &importTx, const CCoinsViewCache &inputs); - -bool CheckVinPubKey(const CTransaction &sourcetx, int32_t i, uint8_t pubkey33[33]); -CMutableTransaction MakeSelfImportSourceTx(CTxDestination &dest, int64_t amount); -int32_t GetSelfimportProof(const CMutableTransaction sourceMtx, CMutableTransaction &templateMtx, ImportProof &proofNull); +/***** + * @brief remove an import tombstone from inputs + * @param importTx the transaction + * @param inputs what to modify + */ +void RemoveImportTombstone(const CTransaction &importTx, CCoinsViewCache &inputs); -#endif /* IMPORTCOIN_H */ +/***** + * @brief See if a tombstone exists + * @param importTx the transaction + * @param inputs + * @returns true if the transaction is a tombstone + */ +bool ExistsImportTombstone(const CTransaction &importTx, const CCoinsViewCache &inputs); diff --git a/src/init.cpp b/src/init.cpp index 2f658e01f33..9b2ea04b034 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -35,7 +35,11 @@ #include "httprpc.h" #include "key.h" #include "notarisationdb.h" +#include "komodo.h" +#include "komodo_globals.h" #include "komodo_notary.h" +#include "komodo_gateway.h" +#include "main.h" #ifdef ENABLE_MINING #include "key_io.h" @@ -94,14 +98,19 @@ using namespace std; #include "komodo_defs.h" +#include "komodo_extern_globals.h" +#include "assetchain.h" + +#include "komodo_gateway.h" +#include "rpc/net.h" extern void ThreadSendAlert(); -extern bool komodo_dailysnapshot(int32_t height); -extern int32_t KOMODO_LOADINGBLOCKS; -extern char ASSETCHAINS_SYMBOL[]; -extern int32_t KOMODO_SNAPSHOT_INTERVAL; +//extern bool komodo_dailysnapshot(int32_t height); //todo remove +//extern int32_t KOMODO_SNAPSHOT_INTERVAL; ZCJoinSplit* pzcashParams = NULL; +assetchain chainName; + #ifdef ENABLE_WALLET CWallet* pwalletMain = NULL; #endif @@ -222,7 +231,8 @@ void Shutdown() /// Be sure that anything that writes files or flushes caches only does this if the respective /// module was initialized. static char shutoffstr[128]; - sprintf(shutoffstr,"%s-shutoff",ASSETCHAINS_SYMBOL); + sprintf(shutoffstr,"%s-shutoff",chainName.symbol().c_str()); + //RenameThread("verus-shutoff"); RenameThread(shutoffstr); mempool.AddTransactionsUpdated(1); @@ -268,7 +278,9 @@ void Shutdown() delete pcoinsdbview; pcoinsdbview = NULL; delete pblocktree; - pblocktree = NULL; + pblocktree = nullptr; + delete pnotarisations; + pnotarisations = nullptr; } #ifdef ENABLE_WALLET if (pwalletMain) @@ -656,7 +668,7 @@ void CleanupBlockRevFiles() remove(it->path()); } } - path komodostate = GetDataDir() / "komodostate"; + path komodostate = GetDataDir() / KOMODO_STATE_FILENAME; remove(komodostate); path minerids = GetDataDir() / "minerids"; remove(minerids); @@ -697,7 +709,7 @@ void ThreadImport(std::vector vImportFiles) LogPrintf("Reindexing finished\n"); // To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked): InitBlockIndex(); - KOMODO_LOADINGBLOCKS = 0; + KOMODO_LOADINGBLOCKS = false; } // hardcoded $DATADIR/bootstrap.dat @@ -749,26 +761,19 @@ void ThreadNotifyRecentlyAdded() } } -/* declarations needed for ThreadUpdateKomodoInternals */ -void komodo_passport_iteration(); -void komodo_cbopretupdate(int32_t forceflag); - +/** + * @brief periodically (every 10 secs) update internal structures + * @note this does nothing on asset chains, only the kmd chain + */ void ThreadUpdateKomodoInternals() { RenameThread("int-updater"); - // boost::signals2::connection c = uiInterface.NotifyBlockTip.connect( - // [](const uint256& hashNewTip) mutable { - // CBlockIndex* pblockindex = mapBlockIndex[hashNewTip]; - // std::cerr << __FUNCTION__ << ": NotifyBlockTip " << hashNewTip.ToString() << " - " << pblockindex->nHeight << std::endl; - // } - // ); - int fireDelaySeconds = 10; try { while (true) { - if ( ASSETCHAINS_SYMBOL[0] == 0 ) + if ( chainName.isKMD() ) fireDelaySeconds = 10; else fireDelaySeconds = ASSETCHAINS_BLOCKTIME/5 + 1; @@ -782,26 +787,13 @@ void ThreadUpdateKomodoInternals() { boost::this_thread::interruption_point(); - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - { - if ( KOMODO_NSPV_FULLNODE ) { - auto start = std::chrono::high_resolution_clock::now(); - komodo_passport_iteration(); // call komodo_interestsum() inside (possible locks) - auto finish = std::chrono::high_resolution_clock::now(); - std::chrono::duration elapsed = finish - start; - // std::cerr << DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()) << " " << __FUNCTION__ << ": komodo_passport_iteration -> Elapsed Time: " << elapsed.count() << " ms" << std::endl; - } - } - else - { - if ( ASSETCHAINS_CBOPRET != 0 ) - komodo_cbopretupdate(0); - } + if (chainName.isKMD() && KOMODO_NSPV_FULLNODE) { + komodo_update_interest(); + komodo_longestchain(); + } } } catch (const boost::thread_interrupted&) { - // std::cerr << "ThreadUpdateKomodoInternals() interrupted" << std::endl; - // c.disconnect(); throw; } catch (const std::exception& e) { @@ -915,11 +907,128 @@ bool AppInitServers(boost::thread_group& threadGroup) return true; } -/** Initialize bitcoin. - * @pre Parameters should be parsed and config file should be read. +//extern int32_t KOMODO_REWIND; + +class InvalidGenesisException : public std::runtime_error +{ +public: + InvalidGenesisException(const std::string& msg) : std::runtime_error(msg) {} +}; + +/**** + * Attempt to open the databases + * @param[in] nBlockTreeDBCache size of cache for block tree db + * @param[in] dbCompression true to compress block tree db files + * @param[in] dbMaxOpenFiles max number of open files for block tree db + * @param[in] nCoinDBCache size of cache for coin db + * @param[out] strLoadError error message + * @returns true on success + * @throws InvalidGenesisException if data directory is incorrect */ -extern int32_t KOMODO_REWIND; +bool AttemptDatabaseOpen(size_t nBlockTreeDBCache, bool dbCompression, size_t dbMaxOpenFiles, size_t nCoinDBCache, + std::string &strLoadError) +{ + try { + UnloadBlockIndex(); + delete pcoinsTip; + delete pcoinsdbview; + delete pcoinscatcher; + delete pblocktree; + delete pnotarisations; + + pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex, dbCompression, dbMaxOpenFiles); + pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex); + pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview); + pcoinsTip = new CCoinsViewCache(pcoinscatcher); + pnotarisations = new NotarisationDB(100*1024*1024, false, fReindex); + + if (fReindex) { + boost::filesystem::remove(GetDataDir() / KOMODO_STATE_FILENAME); + boost::filesystem::remove(GetDataDir() / "signedmasks"); + pblocktree->WriteReindexing(true); + //If we're reindexing in prune mode, wipe away unusable block files and all undo data files + if (fPruneMode) + CleanupBlockRevFiles(); + } + + if (!LoadBlockIndex(fReindex)) { + strLoadError = _("Error loading block database"); + return false; + } + + const CChainParams& chainparams = Params(); + // If the loaded chain has a wrong genesis, bail out immediately + // (we're likely using a testnet datadir, or the other way around). + if (!mapBlockIndex.empty() && mapBlockIndex.count(chainparams.GetConsensus().hashGenesisBlock) == 0) + throw InvalidGenesisException(_("Incorrect or no genesis block found. Wrong datadir for network?")); + komodo_init(1); + if (ShutdownRequested()) return false; + + // Initialize the block index (no-op if non-empty database was already loaded) + if (!InitBlockIndex()) { + strLoadError = _("Error initializing block database"); + return false; + } + KOMODO_LOADINGBLOCKS = false; + // Check for changed -txindex state + if (fTxIndex != GetBoolArg("-txindex", true)) { + strLoadError = _("You need to rebuild the database using -reindex to change -txindex"); + return false; + } + + // Check for changed -prune state. What we are concerned about is a user who has pruned blocks + // in the past, but is now trying to run unpruned. + if (fHavePruned && !fPruneMode) { + strLoadError = _("You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain"); + return false; + } + + if ( ASSETCHAINS_CC != 0 && KOMODO_SNAPSHOT_INTERVAL != 0 && chainActive.Height() >= KOMODO_SNAPSHOT_INTERVAL ) + { + if ( !komodo_dailysnapshot(chainActive.Height()) ) + { + strLoadError = _("daily snapshot failed, please reindex your chain."); + return false; + } + } + + if (!fReindex) { + uiInterface.InitMessage(_("Rewinding blocks if needed...")); + if (!RewindBlockIndex(chainparams)) { + strLoadError = _("Unable to rewind the database to a pre-upgrade state. You will need to redownload the blockchain"); + return false; + } + } + + uiInterface.InitMessage(_("Verifying blocks...")); + if (fHavePruned && GetArg("-checkblocks", 288) > MIN_BLOCKS_TO_KEEP) { + LogPrintf("Prune: pruned datadir may not have more than %d blocks; -checkblocks=%d may fail\n", + MIN_BLOCKS_TO_KEEP, GetArg("-checkblocks", 288)); + } + if ( KOMODO_REWIND == 0 ) + { + if (!CVerifyDB().VerifyDB(pcoinsdbview, GetArg("-checklevel", 3), + GetArg("-checkblocks", 288))) { + strLoadError = _("Corrupted block database detected"); + return false; + } + } + } catch (const std::exception& e) { + if (fDebug) LogPrintf("%s\n", e.what()); + strLoadError = _("Error opening block database"); + return false; + } + return true; +} + +/*** + * Initialize everything and fire up the services + * @pre Parameters should be parsed and config file should be read + * @param threadGroup + * @param scheduler + * @returns true on success + */ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) { // ********************************************************* Step 1: setup @@ -1421,7 +1530,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) return InitError(_("Unable to start HTTP server. See debug log for details.")); } - int64_t nStart; + int64_t nStart = GetTimeMillis(); // ********************************************************* Step 5: verify wallet database integrity #ifdef ENABLE_WALLET @@ -1595,7 +1704,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) SetRPCWarmupFinished(); uiInterface.InitMessage(_("Done loading")); pwalletMain = new CWallet("tmptmp.wallet"); - return !fRequestShutdown; + return !ShutdownRequested(); } // ********************************************************* Step 7: load block chain @@ -1635,11 +1744,11 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("* Using %.1fMiB for chain state database\n", nCoinDBCache * (1.0 / 1024 / 1024)); LogPrintf("* Using %.1fMiB for in-memory UTXO set\n", nCoinCacheUsage * (1.0 / 1024 / 1024)); - if ( fReindex == 0 ) + if ( !fReindex ) { - bool checkval,fAddressIndex,fSpentIndex; pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex, dbCompression, dbMaxOpenFiles); - fAddressIndex = GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX); + bool fAddressIndex = GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX); + bool checkval; pblocktree->ReadFlag("addressindex", checkval); if ( checkval != fAddressIndex && fAddressIndex != 0 ) { @@ -1647,7 +1756,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) fprintf(stderr,"set addressindex, will reindex. could take a while.\n"); fReindex = true; } - fSpentIndex = GetBoolArg("-spentindex", DEFAULT_SPENTINDEX); + bool fSpentIndex = GetBoolArg("-spentindex", DEFAULT_SPENTINDEX); pblocktree->ReadFlag("spentindex", checkval); if ( checkval != fSpentIndex && fSpentIndex != 0 ) { @@ -1657,116 +1766,33 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } } - bool clearWitnessCaches = false; - - bool fLoaded = false; - while (!fLoaded) { + // ************ + // Now we're finally able to open the database + // Results can be: + // - everything opens fine (AttemptDatabaseOpen == true) + // - It looks like we are trying to open a database that belongs to another chain (AttemptDatabaseOpen throws) + // - Some error that is recoverable, perhaps just reindex? If user agrees, reindex and try again + // + // AttemptDatabaseOpen is tried until + // -- returns true + // -- returns false but user opts out + // -- throws exception + // ************ + + try + { bool fReset = fReindex; std::string strLoadError; - - uiInterface.InitMessage(_("Loading block index...")); - - nStart = GetTimeMillis(); - do { - try { - UnloadBlockIndex(); - delete pcoinsTip; - delete pcoinsdbview; - delete pcoinscatcher; - delete pblocktree; - delete pnotarisations; - - pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex, dbCompression, dbMaxOpenFiles); - pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex); - pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview); - pcoinsTip = new CCoinsViewCache(pcoinscatcher); - pnotarisations = new NotarisationDB(100*1024*1024, false, fReindex); - - - if (fReindex) { - boost::filesystem::remove(GetDataDir() / "komodostate"); - boost::filesystem::remove(GetDataDir() / "signedmasks"); - pblocktree->WriteReindexing(true); - //If we're reindexing in prune mode, wipe away unusable block files and all undo data files - if (fPruneMode) - CleanupBlockRevFiles(); - } - - if (!LoadBlockIndex()) { - strLoadError = _("Error loading block database"); - break; - } - - // If the loaded chain has a wrong genesis, bail out immediately - // (we're likely using a testnet datadir, or the other way around). - if (!mapBlockIndex.empty() && mapBlockIndex.count(chainparams.GetConsensus().hashGenesisBlock) == 0) - return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?")); - komodo_init(1); - // Initialize the block index (no-op if non-empty database was already loaded) - if (!InitBlockIndex()) { - strLoadError = _("Error initializing block database"); - break; - } - KOMODO_LOADINGBLOCKS = 0; - // Check for changed -txindex state - if (fTxIndex != GetBoolArg("-txindex", true)) { - strLoadError = _("You need to rebuild the database using -reindex to change -txindex"); - break; - } - - // Check for changed -prune state. What we are concerned about is a user who has pruned blocks - // in the past, but is now trying to run unpruned. - if (fHavePruned && !fPruneMode) { - strLoadError = _("You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain"); - break; - } - - if ( ASSETCHAINS_CC != 0 && KOMODO_SNAPSHOT_INTERVAL != 0 && chainActive.Height() >= KOMODO_SNAPSHOT_INTERVAL ) - { - if ( !komodo_dailysnapshot(chainActive.Height()) ) - { - strLoadError = _("daily snapshot failed, please reindex your chain."); - break; - } - } - - if (!fReindex) { - uiInterface.InitMessage(_("Rewinding blocks if needed...")); - if (!RewindBlockIndex(chainparams, clearWitnessCaches)) { - strLoadError = _("Unable to rewind the database to a pre-upgrade state. You will need to redownload the blockchain"); - break; - } - } - - uiInterface.InitMessage(_("Verifying blocks...")); - if (fHavePruned && GetArg("-checkblocks", 288) > MIN_BLOCKS_TO_KEEP) { - LogPrintf("Prune: pruned datadir may not have more than %d blocks; -checkblocks=%d may fail\n", - MIN_BLOCKS_TO_KEEP, GetArg("-checkblocks", 288)); - } - if ( KOMODO_REWIND == 0 ) - { - if (!CVerifyDB().VerifyDB(pcoinsdbview, GetArg("-checklevel", 3), - GetArg("-checkblocks", 288))) { - strLoadError = _("Corrupted block database detected"); - break; - } - } - } catch (const std::exception& e) { - if (fDebug) LogPrintf("%s\n", e.what()); - strLoadError = _("Error opening block database"); - break; - } - - fLoaded = true; - } while(false); - - if (!fLoaded) { - // first suggest a reindex - if (!fReset) { + while(!AttemptDatabaseOpen(nBlockTreeDBCache, dbCompression, dbMaxOpenFiles, nCoinDBCache, strLoadError)) + { + if (!fReset) // suggest a reindex if we haven't already + { bool fRet = uiInterface.ThreadSafeMessageBox( strLoadError + ".\n\n" + _("error in HDD data, might just need to update to latest, if that doesnt work, then you need to resync"), "", CClientUIInterface::MSG_ERROR | CClientUIInterface::BTN_ABORT); - if (fRet) { + if (fRet) + { + // we should try again, but this time reindex fReindex = true; fRequestShutdown = false; } else { @@ -1776,9 +1802,15 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } else { return InitError(strLoadError); } + } } - KOMODO_LOADINGBLOCKS = 0; + catch(const InvalidGenesisException& ex) + { + // We're probably pointing to the wrong data directory + return InitError(ex.what()); + } + KOMODO_LOADINGBLOCKS = false; // As LoadBlockIndex can take several minutes, it's possible the user // requested to kill the GUI during the last operation. If so, exit. @@ -1890,8 +1922,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) RegisterValidationInterface(pwalletMain); + LOCK(cs_main); CBlockIndex *pindexRescan = chainActive.Tip(); - if (clearWitnessCaches || GetBoolArg("-rescan", false)) + if (GetBoolArg("-rescan", false)) { pwalletMain->ClearNoteWitnessCache(); pindexRescan = chainActive.Genesis(); @@ -2011,10 +2044,22 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) vImportFiles.push_back(strFile); } threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles)); - if (chainActive.Tip() == NULL) { - LogPrintf("Waiting for genesis block to be imported...\n"); - while (!fRequestShutdown && chainActive.Tip() == NULL) - MilliSleep(10); + { + CBlockIndex *tip = nullptr; + { + LOCK(cs_main); + tip = chainActive.Tip(); + } + if (tip == nullptr) { + LogPrintf("Waiting for genesis block to be imported...\n"); + while (!ShutdownRequested() && tip == nullptr) + { + MilliSleep(10); + LOCK(cs_main); + tip = chainActive.Tip(); + } + if (ShutdownRequested()) return false; + } } // ********************************************************* Step 11: start node @@ -2027,7 +2072,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) //// debug print LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size()); - LogPrintf("nBestHeight = %d\n", chainActive.Height()); + { + LOCK(cs_main); + LogPrintf("nBestHeight = %d\n", chainActive.Height()); + } #ifdef ENABLE_WALLET RescanWallets(); @@ -2076,5 +2124,5 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // SENDALERT threadGroup.create_thread(boost::bind(ThreadSendAlert)); - return !fRequestShutdown; + return !ShutdownRequested(); } diff --git a/src/init.h b/src/init.h index 108339865be..ae23a906819 100644 --- a/src/init.h +++ b/src/init.h @@ -41,6 +41,13 @@ bool ShutdownRequested(); /** Interrupt threads */ void Interrupt(boost::thread_group& threadGroup); void Shutdown(); +/*** + * Initialize everything and fire up the services + * @pre Parameters should be parsed and config file should be read + * @param threadGroup + * @param scheduler + * @returns true on success + */ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler); /** The help message mode determines what help message to show */ diff --git a/src/komodo-tx.cpp b/src/komodo-tx.cpp index 509a53abe30..bf0cfadb532 100644 --- a/src/komodo-tx.cpp +++ b/src/komodo-tx.cpp @@ -56,6 +56,7 @@ uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 static bool fCreateBlank; static std::map registers; static const int CONTINUE_EXECUTION=-1; +assetchain chainName; // // This function returns either one of EXIT_ codes when it's expected to stop the process or diff --git a/src/komodo.cpp b/src/komodo.cpp index 319d78ed162..0164301d2d6 100644 --- a/src/komodo.cpp +++ b/src/komodo.cpp @@ -13,9 +13,19 @@ * * ******************************************************************************/ #include "komodo.h" +#include "komodo_globals.h" #include "komodo_extern_globals.h" +#include "komodo_utils.h" #include "komodo_notary.h" +#include "komodo_bitcoind.h" #include "mem_read.h" +#include "notaries_staked.h" + +static FILE *fp; // for stateupdate +//int32_t KOMODO_EXTERNAL_NOTARIES = 0; //todo remove +#include "komodo_gateway.h" +#include "komodo_events.h" +#include "komodo_ccdata.h" void komodo_currentheight_set(int32_t height) { @@ -38,7 +48,7 @@ int32_t komodo_currentheight() else return(0); } -int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char *dest) +int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol, const char *dest) { int32_t func; @@ -47,17 +57,17 @@ int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char if ( (func= fgetc(fp)) != EOF ) { bool matched = false; - if ( ASSETCHAINS_SYMBOL[0] == 0 && strcmp(symbol,"KMD") == 0 ) + if ( chainName.isKMD() && strcmp(symbol,"KMD") == 0 ) matched = true; else - matched = (strcmp(symbol,ASSETCHAINS_SYMBOL) == 0); + matched = chainName.isSymbol(symbol); int32_t ht; if ( fread(&ht,1,sizeof(ht),fp) != sizeof(ht) ) throw komodo::parse_error("Unable to read height from file"); if ( func == 'P' ) { - std::shared_ptr pk = std::make_shared(fp, ht); + komodo::event_pubkeys pk(fp, ht); if ( (KOMODO_EXTERNAL_NOTARIES && matched ) || (strcmp(symbol,"KMD") == 0 && !KOMODO_EXTERNAL_NOTARIES) ) { komodo_eventadd_pubkeys(sp, symbol, ht, pk); @@ -65,23 +75,23 @@ int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char } else if ( func == 'N' || func == 'M' ) { - std::shared_ptr evt = std::make_shared(fp, ht, dest, func == 'M'); + komodo::event_notarized evt(fp, ht, dest, func == 'M'); komodo_eventadd_notarized(sp, symbol, ht, evt); } else if ( func == 'U' ) // deprecated { - std::shared_ptr evt = std::make_shared(fp, ht); + komodo::event_u evt(fp, ht); } else if ( func == 'K' || func == 'T') { - std::shared_ptr evt = std::make_shared(fp, ht, func == 'T'); + komodo::event_kmdheight evt(fp, ht, func == 'T'); komodo_eventadd_kmdheight(sp, symbol, ht, evt); } else if ( func == 'R' ) { - std::shared_ptr evt = std::make_shared(fp, ht); + komodo::event_opreturn evt(fp, ht); // check for oversized opret - if ( evt->opret.size() < 16384*4 ) + if ( evt.opret.size() < 16384*4 ) komodo_eventadd_opreturn(sp, symbol, ht, evt); } else if ( func == 'D' ) @@ -90,20 +100,29 @@ int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char } else if ( func == 'V' ) { - std::shared_ptr evt = std::make_shared(fp, ht); + komodo::event_pricefeed evt(fp, ht); komodo_eventadd_pricefeed(sp, symbol, ht, evt); } + else if ( func == 'B' ) { + // can be written but not processed on read + } + else { + throw komodo::parse_error("Unable to parse state file: unknown event"); + } } // retrieved the func } catch(const komodo::parse_error& pe) { LogPrintf("Error occurred in parsestatefile: %s\n", pe.what()); + LogPrintf("%s file is invalid. Komodod will be stopped. Please remove %s and %s.ind files and start the daemon\n", KOMODO_STATE_FILENAME, KOMODO_STATE_FILENAME, KOMODO_STATE_FILENAME); + uiInterface.ThreadSafeMessageBox(strprintf("Please remove %s and %s.ind files and restart", KOMODO_STATE_FILENAME, KOMODO_STATE_FILENAME), "", CClientUIInterface::MSG_ERROR); + StartShutdown(); func = -1; } return func; } -int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest) +int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,const char *symbol, const char *dest) { int32_t func = -1; @@ -115,17 +134,17 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long func = filedata[fpos++]; bool matched = false; - if ( ASSETCHAINS_SYMBOL[0] == 0 && strcmp(symbol,"KMD") == 0 ) + if ( chainName.isKMD() && strcmp(symbol,"KMD") == 0 ) matched = true; else - matched = (strcmp(symbol,ASSETCHAINS_SYMBOL) == 0); + matched = chainName.isSymbol(symbol); int32_t ht; if ( mem_read(ht, filedata, fpos, datalen) != sizeof(ht) ) throw komodo::parse_error("Unable to parse height from file data"); if ( func == 'P' ) { - std::shared_ptr pk = std::make_shared(filedata, fpos, datalen, ht); + komodo::event_pubkeys pk(filedata, fpos, datalen, ht); if ( (KOMODO_EXTERNAL_NOTARIES && matched ) || (strcmp(symbol,"KMD") == 0 && !KOMODO_EXTERNAL_NOTARIES) ) { komodo_eventadd_pubkeys(sp, symbol, ht, pk); @@ -133,25 +152,21 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long } else if ( func == 'N' || func == 'M' ) { - std::shared_ptr ntz = - std::make_shared(filedata, fpos, datalen, ht, dest, func == 'M'); + komodo::event_notarized ntz(filedata, fpos, datalen, ht, dest, func == 'M'); komodo_eventadd_notarized(sp, symbol, ht, ntz); } else if ( func == 'U' ) // deprecated { - std::shared_ptr u = - std::make_shared(filedata, fpos, datalen, ht); + komodo::event_u u(filedata, fpos, datalen, ht); } else if ( func == 'K' || func == 'T' ) { - std::shared_ptr kmd_ht = - std::make_shared(filedata, fpos, datalen, ht, func == 'T'); + komodo::event_kmdheight kmd_ht(filedata, fpos, datalen, ht, func == 'T'); komodo_eventadd_kmdheight(sp, symbol, ht, kmd_ht); } else if ( func == 'R' ) { - std::shared_ptr opret = - std::make_shared(filedata, fpos, datalen, ht); + komodo::event_opreturn opret(filedata, fpos, datalen, ht); komodo_eventadd_opreturn(sp, symbol, ht, opret); } else if ( func == 'D' ) @@ -160,74 +175,73 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long } else if ( func == 'V' ) { - std::shared_ptr pf = - std::make_shared(filedata, fpos, datalen, ht); + komodo::event_pricefeed pf(filedata, fpos, datalen, ht); komodo_eventadd_pricefeed(sp, symbol, ht, pf); } + else if ( func == 'B' ) { + // can be written but not processed on read + } + else { + throw komodo::parse_error("Unable to parse file data: unknown event"); + } *fposp = fpos; } } catch( const komodo::parse_error& pe) { LogPrintf("Unable to parse state file data. Error: %s\n", pe.what()); + LogPrintf("%s file is invalid. Komodod will be stopped. Please remove %s and %s.ind files and start the daemon\n", KOMODO_STATE_FILENAME, KOMODO_STATE_FILENAME, KOMODO_STATE_FILENAME); + uiInterface.ThreadSafeMessageBox(strprintf("Please remove %s and %s.ind files and restart", KOMODO_STATE_FILENAME, KOMODO_STATE_FILENAME), "", CClientUIInterface::MSG_ERROR); + StartShutdown(); func = -1; } return func; } -/*** - * @brief persist event to file stream - * @param evt the event - * @param fp the file - * @returns the number of bytes written - */ -size_t write_event(std::shared_ptr evt, FILE *fp) -{ - std::stringstream ss; - ss << evt; - std::string buf = ss.str(); - return fwrite(buf.c_str(), buf.size(), 1, fp); -} - void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries, - uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals, + uint8_t notaryid,uint256 txhash,uint32_t *pvals, uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue, uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth) { - static FILE *fp; static int32_t errs,didinit; static uint256 zero; struct komodo_state *sp; - char fname[512],symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; - int32_t retval,ht,func; + char fname[MAX_STATEFNAME+1],symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; + int32_t ht,func; uint8_t num,pubkeys[64][33]; if ( didinit == 0 ) { - portable_mutex_init(&KOMODO_KV_mutex); portable_mutex_init(&KOMODO_CC_mutex); didinit = 1; } if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) { KOMODO_INITDONE = (uint32_t)time(NULL); - printf("[%s] no komodo_stateptr\n",ASSETCHAINS_SYMBOL); + printf("[%s] no komodo_stateptr\n",chainName.symbol().c_str()); return; } if ( fp == 0 ) { - komodo_statefname(fname,ASSETCHAINS_SYMBOL,(char *)"komodostate"); - if ( (fp= fopen(fname,"rb+")) != 0 ) + komodo_statefname(fname, chainName.symbol().c_str(), KOMODO_STATE_FILENAME); + if ( (fp= fopen(fname,"rb+")) != nullptr ) { - if ( (retval= komodo_faststateinit(sp,fname,symbol,dest)) > 0 ) + if ( komodo_faststateinit(sp, fname, symbol, dest) ) fseek(fp,0,SEEK_END); else { - fprintf(stderr,"komodo_faststateinit retval.%d\n",retval); - while ( komodo_parsestatefile(sp,fp,symbol,dest) >= 0 ) + // unable to use faststateinit, so try again only slower + fprintf(stderr,"komodo_faststateinit retval.-1\n"); + while (!ShutdownRequested() && komodo_parsestatefile(sp,fp,symbol,dest) >= 0) ; } - } else fp = fopen(fname,"wb+"); + LogPrintf("komodo read last notarised height %d from %s\n", sp->LastNotarizedHeight(), KOMODO_STATE_FILENAME); + } + else + fp = fopen(fname,"wb+"); // the state file probably did not exist, create it. + + if (ShutdownRequested()) { fclose(fp); return; } + KOMODO_INITDONE = (uint32_t)time(NULL); } if ( height <= 0 ) @@ -238,40 +252,41 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar { if ( KMDheight != 0 ) { - std::shared_ptr kmd_ht = std::make_shared(height); - kmd_ht->kheight = KMDheight; - kmd_ht->timestamp = KMDtimestamp; + komodo::event_kmdheight kmd_ht(height); + kmd_ht.kheight = KMDheight; + kmd_ht.timestamp = KMDtimestamp; write_event(kmd_ht, fp); komodo_eventadd_kmdheight(sp,symbol,height,kmd_ht); } else if ( opretbuf != 0 && opretlen > 0 ) { - std::shared_ptr evt = std::make_shared(height); - evt->txid = txhash; - evt->vout = vout; - evt->value = opretvalue; + komodo::event_opreturn evt(height); + evt.txid = txhash; + evt.vout = vout; + evt.value = opretvalue; for(uint16_t i = 0; i < opretlen; ++i) - evt->opret.push_back(opretbuf[i]); + evt.opret.push_back(opretbuf[i]); write_event(evt, fp); komodo_eventadd_opreturn(sp,symbol,height,evt); } else if ( notarypubs != 0 && numnotaries > 0 ) { - std::shared_ptr pk = std::make_shared(height); - pk->num = numnotaries; - memcpy(pk->pubkeys, notarypubs, 33 * 64); + komodo::event_pubkeys pk(height); + pk.num = numnotaries; + memcpy(pk.pubkeys, notarypubs, 33 * 64); write_event(pk, fp); komodo_eventadd_pubkeys(sp,symbol,height,pk); } + /* TODO: why is this removed in jmj_event_fix3? else if ( voutmask != 0 && numvouts > 0 ) { - std::shared_ptr evt = std::make_shared(height); - evt->n = numvouts; - evt->nid = notaryid; - memcpy(evt->mask, &voutmask, sizeof(voutmask)); - memcpy(evt->hash, &txhash, sizeof(txhash)); + komodo::event_u evt(height); + evt.n = numvouts; + evt.nid = notaryid; + memcpy(evt.mask, &voutmask, sizeof(voutmask)); + memcpy(evt.hash, &txhash, sizeof(txhash)); write_event(evt, fp); - } + } */ else if ( pvals != 0 && numpvals > 0 ) { int32_t i,nonz = 0; @@ -280,10 +295,10 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar nonz++; if ( nonz >= 32 ) { - std::shared_ptr evt = std::make_shared(height); - evt->num = numpvals; - for( uint8_t i = 0; i < evt->num; ++i) - evt->prices[i] = pvals[i]; + komodo::event_pricefeed evt(height); + evt.num = numpvals; + for( uint8_t i = 0; i < evt.num; ++i) + evt.prices[i] = pvals[i]; write_event(evt, fp); komodo_eventadd_pricefeed(sp,symbol,height,evt); } @@ -292,12 +307,12 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar { if ( sp != nullptr ) { - std::shared_ptr evt = std::make_shared(height, dest); - evt->blockhash = sp->LastNotarizedHash(); - evt->desttxid = sp->LastNotarizedDestTxId(); - evt->notarizedheight = sp->LastNotarizedHeight(); - evt->MoM = sp->LastNotarizedMoM(); - evt->MoMdepth = sp->LastNotarizedMoMDepth(); + komodo::event_notarized evt(height, dest); + evt.blockhash = sp->LastNotarizedHash(); + evt.desttxid = sp->LastNotarizedDestTxId(); + evt.notarizedheight = sp->LastNotarizedHeight(); + evt.MoM = sp->LastNotarizedMoM(); + evt.MoMdepth = sp->LastNotarizedMoMDepth(); write_event(evt, fp); komodo_eventadd_notarized(sp,symbol,height,evt); } @@ -323,7 +338,8 @@ int32_t komodo_validate_chain(uint256 srchash,int32_t notarized_height) if ( last_rewind != 0 ) { fprintf(stderr,"%s FORK detected. notarized.%d %s not in this chain! last notarization %d -> rewindtarget.%d\n", - ASSETCHAINS_SYMBOL,notarized_height,srchash.ToString().c_str(),sp->LastNotarizedHeight(),rewindtarget); + chainName.symbol().c_str(),notarized_height,srchash.ToString().c_str(), + sp->LastNotarizedHeight(),rewindtarget); } last_rewind = rewindtarget; } @@ -344,7 +360,7 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar { if ( i == 0 && j == 0 && memcmp(NOTARY_PUBKEY33,scriptbuf+1,33) == 0 && IS_KOMODO_NOTARY ) { - printf("%s KOMODO_LASTMINED.%d -> %d\n",ASSETCHAINS_SYMBOL,KOMODO_LASTMINED,height); + printf("%s KOMODO_LASTMINED.%d -> %d\n",chainName.symbol().c_str(),KOMODO_LASTMINED,height); prevKOMODO_LASTMINED = KOMODO_LASTMINED; KOMODO_LASTMINED = height; } @@ -372,9 +388,6 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar } else if ( notaryid != nid ) { - //for (i=0; i<33; i++) - // printf("%02x",scriptbuf[i+1]); - //printf(" %s mismatch notaryid.%d k.%d\n",ASSETCHAINS_SYMBOL,notaryid,nid); notaryid = 64; *voutmaskp = 0; } @@ -395,7 +408,7 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar } opoffset = len; matched = 0; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) + if ( chainName.isKMD() ) { if ( strcmp("KMD",(char *)&scriptbuf[len+32 * 2 + 4]) == 0 ) matched = 1; @@ -405,10 +418,10 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar if ( scriptbuf[len] == 'K' ) { //fprintf(stderr,"i.%d j.%d KV OPRET len.%d %.8f\n",i,j,opretlen,dstr(value)); - komodo_stateupdate(height,0,0,0,txhash,0,0,0,0,0,0,value,&scriptbuf[len],opretlen,j,zero,0); + komodo_stateupdate(height,0,0,0,txhash,0,0,0,0,value,&scriptbuf[len],opretlen,j,zero,0); return(-1); } - if ( strcmp(ASSETCHAINS_SYMBOL,(char *)&scriptbuf[len+32*2+4]) == 0 ) + if ( strcmp(chainName.symbol().c_str(),(char *)&scriptbuf[len+32*2+4]) == 0 ) matched = 1; } offset = 32 * (1 + matched) + 4; @@ -423,8 +436,6 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar notarized = 1; if ( strcmp("PIZZA",ccdata.symbol) == 0 || strncmp("TXSCL",ccdata.symbol,5) == 0 || strcmp("BEER",ccdata.symbol) == 0) notarized = 1; - if ( 0 && opretlen != 149 ) - printf("[%s].%d (%s) matched.%d i.%d j.%d notarized.%d %llx opretlen.%d len.%d offset.%d opoffset.%d\n",ASSETCHAINS_SYMBOL,height,ccdata.symbol,matched,i,j,notarized,(long long)signedmask,opretlen,len,offset,opoffset); len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&srchash); len += iguana_rwnum(0,&scriptbuf[len],sizeof(*notarizedheightp),(uint8_t *)notarizedheightp); if ( matched != 0 ) @@ -456,13 +467,11 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar if ( len+sizeof(ccdata.CCid)-opoffset <= opretlen ) { len += iguana_rwnum(0,&scriptbuf[len],sizeof(ccdata.CCid),(uint8_t *)&ccdata.CCid); - //if ( ((MoMdepth>>16) & 0xffff) != (ccdata.CCid & 0xffff) ) - // fprintf(stderr,"%s CCid mismatch %u != %u\n",ASSETCHAINS_SYMBOL,((MoMdepth>>16) & 0xffff),(ccdata.CCid & 0xffff)); ccdata.len = sizeof(ccdata.CCid); - if ( ASSETCHAINS_SYMBOL[0] != 0 ) + if ( !chainName.isKMD() ) { // MoMoM, depth, numpairs, (notarization ht, MoMoM offset) - if ( len+48-opoffset <= opretlen && strcmp(ccdata.symbol,ASSETCHAINS_SYMBOL) == 0 ) + if ( len+48-opoffset <= opretlen && chainName.isSymbol(ccdata.symbol) ) { len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.kmdstarti); len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.kmdendi); @@ -491,7 +500,7 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar else { if ( matched != 0 ) - printf("[%s] matched.%d VALID (%s) MoM.%s [%d] CCid.%u\n",ASSETCHAINS_SYMBOL,matched,ccdata.symbol,MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff); + printf("[%s] matched.%d VALID (%s) MoM.%s [%d] CCid.%u\n",chainName.symbol().c_str(),matched,ccdata.symbol,MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff); } if ( MoMoMdata.pairs != 0 ) free(MoMoMdata.pairs); @@ -509,19 +518,19 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar sp->SetLastNotarizedMoM(MoM); sp->SetLastNotarizedMoMDepth(MoMdepth); } - komodo_stateupdate(height,0,0,0,zero,0,0,0,0,0,0,0,0,0,0,sp->LastNotarizedMoM(),sp->LastNotarizedMoMDepth()); + komodo_stateupdate(height,0,0,0,zero,0,0,0,0,0,0,0,0,sp->LastNotarizedMoM(),sp->LastNotarizedMoMDepth()); printf("[%s] ht.%d NOTARIZED.%d %s.%s %sTXID.%s lens.(%d %d) MoM.%s %d\n", - ASSETCHAINS_SYMBOL,height,sp->LastNotarizedHeight(), - ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(), - ASSETCHAINS_SYMBOL[0]==0?"BTC":"KMD",desttxid.ToString().c_str(),opretlen,len, - sp->LastNotarizedMoM().ToString().c_str(),sp->LastNotarizedMoMDepth()); + chainName.symbol().c_str(),height,sp->LastNotarizedHeight(), + chainName.ToString().c_str(),srchash.ToString().c_str(), + chainName.isKMD()?"BTC":"KMD",desttxid.ToString().c_str(), + opretlen,len,sp->LastNotarizedMoM().ToString().c_str(),sp->LastNotarizedMoMDepth()); - if ( ASSETCHAINS_SYMBOL[0] == 0 ) + if ( chainName.isKMD() ) { if ( signedfp == 0 ) { - char fname[512]; - komodo_statefname(fname,ASSETCHAINS_SYMBOL,(char *)"signedmasks"); + char fname[MAX_STATEFNAME+1]; + komodo_statefname(fname,chainName.symbol().c_str(),(char *)"signedmasks"); if ( (signedfp= fopen(fname,"rb+")) == 0 ) signedfp = fopen(fname,"wb"); else fseek(signedfp,0,SEEK_END); @@ -537,26 +546,23 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar //for (i=0; i 600000 && matched != 0 ) printf("%s validated.%d notarized.%d %llx reject ht.%d NOTARIZED.%d prev.%d %s.%s DESTTXID.%s len.%d opretlen.%d\n", - ccdata.symbol,validated,notarized,(long long)signedmask,height,*notarizedheightp,sp->LastNotarizedHeight(), - ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),desttxid.ToString().c_str(),len,opretlen); + ccdata.symbol,validated,notarized,(long long)signedmask,height, + *notarizedheightp, sp->LastNotarizedHeight(),chainName.ToString().c_str(), + srchash.ToString().c_str(), desttxid.ToString().c_str(),len,opretlen); } else if ( matched != 0 && i == 0 && j == 1 && opretlen == 149 ) { - if ( notaryid >= 0 && notaryid < 64 ) - komodo_paxpricefeed(height,&scriptbuf[len],opretlen); + // old pax pricefeed. Ignore. } else if ( matched != 0 ) { - //int32_t k; for (k=0; k= 32*2+4 && strcmp(ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,(char *)&scriptbuf[len+32*2+4]) == 0 ) + if ( opretlen >= 32*2+4 && strcmp(chainName.ToString().c_str(),(char *)&scriptbuf[len+32*2+4]) == 0 ) { for (k=0; k<32; k++) if ( scriptbuf[len+k] != 0 ) @@ -569,7 +575,7 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar } if ( *isratificationp == 0 && (signedmask != 0 || (scriptbuf[len] != 'X' && scriptbuf[len] != 'A')) ) // && scriptbuf[len] != 'I') - komodo_stateupdate(height,0,0,0,txhash,0,0,0,0,0,0,value,&scriptbuf[len],opretlen,j,zero,0); + komodo_stateupdate(height,0,0,0,txhash,0,0,0,0,value,&scriptbuf[len],opretlen,j,zero,0); } } return(notaryid); @@ -581,7 +587,24 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar // if txi == 0 && 2 outputs and 2nd OP_RETURN, len == 32*2+4 -> notarized, 1st byte 'P' -> pricefeed // OP_RETURN: 'D' -> deposit, 'W' -> withdraw -int32_t gettxout_scriptPubKey(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid,int32_t n); +int32_t gettxout_scriptPubKey(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid,int32_t n) +{ + int32_t i,m; uint8_t *ptr; + LOCK(cs_main); + CTransaction tx; + uint256 hashBlock; + if ( GetTransaction(txid,tx,hashBlock,false) == 0 ) + return(-1); + else if ( n < tx.vout.size() ) + { + ptr = (uint8_t *)&tx.vout[n].scriptPubKey[0]; + m = tx.vout[n].scriptPubKey.size(); + for (i=0; i notarisations; uint64_t signedmask,voutmask; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; @@ -619,12 +649,11 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) KOMODO_INITDONE = (uint32_t)time(NULL); if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) { - fprintf(stderr,"unexpected null komodostateptr.[%s]\n",ASSETCHAINS_SYMBOL); + fprintf(stderr,"unexpected null komodostateptr.[%s]\n",chainName.symbol().c_str()); return(0); } - //fprintf(stderr,"%s connect.%d\n",ASSETCHAINS_SYMBOL,pindex->nHeight); // Wallet Filter. Disabled here. Cant be activated by notaries or pools with some changes. - if ( is_STAKED(ASSETCHAINS_SYMBOL) != 0 || STAKED_NOTARY_ID > -1 ) + if ( is_STAKED(chainName.symbol()) != 0 || STAKED_NOTARY_ID > -1 ) { staked_era = STAKED_era(pindex->GetBlockTime()); if ( !fJustCheck && staked_era != lastStakedEra ) @@ -644,17 +673,17 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) { if ( pindex->nHeight != hwmheight ) { - printf("%s hwmheight.%d vs pindex->nHeight.%d t.%u reorg.%d\n",ASSETCHAINS_SYMBOL,hwmheight,pindex->nHeight,(uint32_t)pindex->nTime,hwmheight-pindex->nHeight); + printf("%s hwmheight.%d vs pindex->nHeight.%d t.%u reorg.%d\n",chainName.symbol().c_str(),hwmheight,pindex->nHeight,(uint32_t)pindex->nTime,hwmheight-pindex->nHeight); komodo_purge_ccdata((int32_t)pindex->nHeight); hwmheight = pindex->nHeight; } if (!fJustCheck) { komodo_event_rewind(sp,symbol,pindex->nHeight); - komodo_stateupdate(pindex->nHeight,0,0,0,zero,0,0,0,0,-pindex->nHeight,pindex->nTime,0,0,0,0,zero,0); + komodo_stateupdate(pindex->nHeight,0,0,0,zero,0,0,-pindex->nHeight,pindex->nTime,0,0,0,0,zero,0); } } - komodo_currentheight_set(chainActive.LastTip()->nHeight); + komodo_currentheight_set(chainActive.Tip()->nHeight); int transaction = 0; if ( pindex != 0 ) { @@ -662,7 +691,7 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) txn_count = block.vtx.size(); for (i=0; i= KOMODO_MINRATIFY) || - (numvalid >= KOMODO_MINRATIFY && ASSETCHAINS_SYMBOL[0] != 0) || - numvalid > (numnotaries/5) ) + if ( ((height < 90000 || (signedmask & 1) != 0) && numvalid >= KOMODO_MINRATIFY) + || (numvalid >= KOMODO_MINRATIFY && !chainName.isKMD()) + || numvalid > (numnotaries/5) ) { - if ( !fJustCheck && ASSETCHAINS_SYMBOL[0] != 0) + if ( !fJustCheck && !chainName.isKMD() ) { static FILE *signedfp; if ( signedfp == 0 ) { - char fname[512]; - komodo_statefname(fname,ASSETCHAINS_SYMBOL,(char *)"signedmasks"); + char fname[MAX_STATEFNAME+1]; + komodo_statefname(fname,chainName.symbol().c_str(),(char *)"signedmasks"); if ( (signedfp= fopen(fname,"rb+")) == 0 ) signedfp = fopen(fname,"wb"); else fseek(signedfp,0,SEEK_END); @@ -715,7 +744,7 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) fflush(signedfp); } transaction = i; - printf("[%s] ht.%d txi.%d signedmask.%llx numvins.%d numvouts.%d <<<<<<<<<<< notarized\n",ASSETCHAINS_SYMBOL,height,i,(long long)signedmask,numvins,numvouts); + printf("[%s] ht.%d txi.%d signedmask.%llx numvins.%d numvouts.%d <<<<<<<<<<< notarized\n",chainName.symbol().c_str(),height,i,(long long)signedmask,numvins,numvouts); } notarized = 1; } @@ -733,7 +762,7 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) if ( len >= sizeof(uint32_t) && len <= sizeof(scriptbuf) ) { memcpy(scriptbuf,(uint8_t *)&block.vtx[i].vout[j].scriptPubKey[0],len); - notaryid = komodo_voutupdate(fJustCheck,&isratification,notaryid,scriptbuf,len,height,txhash,i,j,&voutmask,&specialtx,¬arizedheight,(uint64_t)block.vtx[i].vout[j].nValue,notarized,signedmask,(uint32_t)chainActive.LastTip()->GetBlockTime()); + notaryid = komodo_voutupdate(fJustCheck,&isratification,notaryid,scriptbuf,len,height,txhash,i,j,&voutmask,&specialtx,¬arizedheight,(uint64_t)block.vtx[i].vout[j].nValue,notarized,signedmask,(uint32_t)chainActive.Tip()->GetBlockTime()); if ( fJustCheck && notaryid == -2 ) { // We see a valid notarisation here, save its location. @@ -747,13 +776,11 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) } } } - if ( 0 && ASSETCHAINS_SYMBOL[0] == 0 ) - printf("[%s] ht.%d txi.%d signedmask.%llx numvins.%d numvouts.%d notarized.%d special.%d isratification.%d\n",ASSETCHAINS_SYMBOL,height,i,(long long)signedmask,numvins,numvouts,notarized,specialtx,isratification); if ( !fJustCheck && (notarized != 0 && (notarizedheight != 0 || specialtx != 0)) ) { if ( isratification != 0 ) { - printf("%s NOTARY SIGNED.%llx numvins.%d ht.%d txi.%d notaryht.%d specialtx.%d\n",ASSETCHAINS_SYMBOL,(long long)signedmask,numvins,height,i,notarizedheight,specialtx); + printf("%s NOTARY SIGNED.%llx numvins.%d ht.%d txi.%d notaryht.%d specialtx.%d\n",chainName.symbol().c_str(),(long long)signedmask,numvins,height,i,notarizedheight,specialtx); printf("ht.%d specialtx.%d isratification.%d numvouts.%d signed.%llx numnotaries.%d\n",height,specialtx,isratification,numvouts,(long long)signedmask,numnotaries); } if ( specialtx != 0 && isratification != 0 && numvouts > 2 ) @@ -775,27 +802,25 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) } } } - if ( ASSETCHAINS_SYMBOL[0] != 0 || height < 100000 ) + if ( !chainName.isKMD() || height < 100000 ) { if ( ((signedmask & 1) != 0 && numvalid >= KOMODO_MINRATIFY) || bitweight(signedmask) > (numnotaries/3) ) { memset(&txhash,0,sizeof(txhash)); - komodo_stateupdate(height,pubkeys,numvalid,0,txhash,0,0,0,0,0,0,0,0,0,0,zero,0); + komodo_stateupdate(height,pubkeys,numvalid,0,txhash,0,0,0,0,0,0,0,0,zero,0); printf("RATIFIED! >>>>>>>>>> new notaries.%d newheight.%d from height.%d\n",numvalid,(((height+KOMODO_ELECTION_GAP/2)/KOMODO_ELECTION_GAP)+1)*KOMODO_ELECTION_GAP,height); } else printf("signedmask.%llx numvalid.%d wt.%d numnotaries.%d\n",(long long)signedmask,numvalid,bitweight(signedmask),numnotaries); } } } } - if ( !fJustCheck && IS_KOMODO_NOTARY && ASSETCHAINS_SYMBOL[0] == 0 ) - printf("%s ht.%d\n",ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL,height); + if ( !fJustCheck && IS_KOMODO_NOTARY && chainName.isKMD() ) + printf("%s ht.%d\n",chainName.ToString().c_str(),height); if ( !fJustCheck && pindex->nHeight == hwmheight ) - komodo_stateupdate(height,0,0,0,zero,0,0,0,0,height,(uint32_t)pindex->nTime,0,0,0,0,zero,0); + komodo_stateupdate(height,0,0,0,zero,0,0,height,(uint32_t)pindex->nTime,0,0,0,0,zero,0); } else { fprintf(stderr,"komodo_connectblock: unexpected null pindex\n"); return(0); } - //KOMODO_INITDONE = (uint32_t)time(NULL); - //fprintf(stderr,"%s end connect.%d\n",ASSETCHAINS_SYMBOL,pindex->nHeight); if (fJustCheck) { if ( notarisations.size() == 0 ) @@ -813,3 +838,12 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) } else return(0); } + +void komodo_statefile_uninit() +{ + if (fp != nullptr) + { + fclose(fp); + fp = nullptr; + } +} diff --git a/src/komodo.h b/src/komodo.h index bdf0913933f..5139ab35986 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -13,74 +13,43 @@ * * ******************************************************************************/ #pragma once -#include -#include -#include -#include - #include "uint256.h" +#include "chain.h" +#include "komodo_structs.h" +#include "komodo_utils.h" +#include "komodo_curve25519.h" + +//#include "komodo_cJSON.h" +//#include "komodo_bitcoind.h" +//#include "komodo_interest.h" // Todo: // verify: reorgs -#define KOMODO_ASSETCHAINS_WAITNOTARIZE -#define KOMODO_PAXMAX (10000 * COIN) - -#include "uthash.h" -#include "utlist.h" -#include "chain.h" - -int32_t gettxout_scriptPubKey(uint8_t *scriptPubkey,int32_t maxsize,uint256 txid,int32_t n); -void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height); -int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block); -bool check_pprevnotarizedht(); -#include "komodo_structs.h" -#include "komodo_utils.h" -#include "komodo_curve25519.h" +//#include "komodo_kv.h" +//#include "komodo_gateway.h" +//#include "komodo_events.h" +//#include "komodo_ccdata.h" +#include -#include "komodo_cJSON.h" -#include "komodo_bitcoind.h" -#include "komodo_interest.h" -#include "komodo_pax.h" -#include "komodo_notary.h" +const char KOMODO_STATE_FILENAME[] = "komodoevents"; -int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char *dest); -#include "komodo_kv.h" -#include "komodo_jumblr.h" -#include "komodo_gateway.h" -#include "komodo_events.h" -#include "komodo_ccdata.h" +int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol, const char *dest); void komodo_currentheight_set(int32_t height); int32_t komodo_currentheight(); -int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char *dest); - -int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest); +int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,const char *symbol, const char *dest); -void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth); +void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid, + uint256 txhash,uint32_t *pvals,uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp, + uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth); int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notaryid, uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i, int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp, uint64_t value,int32_t notarized,uint64_t signedmask,uint32_t timestamp); -int32_t komodo_validate_chain(uint256 srchash,int32_t notarized_height); - -// Special tx have vout[0] -> CRYPTO777 -// with more than KOMODO_MINRATIFY pay2pubkey outputs -> ratify -// if all outputs to notary -> notary utxo -// if txi == 0 && 2 outputs and 2nd OP_RETURN, len == 32*2+4 -> notarized, 1st byte 'P' -> pricefeed -// OP_RETURN: 'D' -> deposit, 'W' -> withdraw - -int32_t gettxout_scriptPubKey(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid,int32_t n); - -int32_t komodo_notarycmp(uint8_t *scriptPubKey,int32_t scriptlen,uint8_t pubkeys[64][33],int32_t numnotaries,uint8_t rmd160[20]); - -// int32_t (!!!) -/* - read blackjok3rtt comments in main.cpp -*/ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block); diff --git a/src/komodo_bitcoind.cpp b/src/komodo_bitcoind.cpp index 43f06c2200d..51b60755c05 100644 --- a/src/komodo_bitcoind.cpp +++ b/src/komodo_bitcoind.cpp @@ -13,9 +13,14 @@ * * ******************************************************************************/ #include "komodo_bitcoind.h" -#include "komodo_extern_globals.h" +#include "komodo_globals.h" +#include "komodo.h" // komodo_voutupdate() #include "komodo_utils.h" // OS_milliseconds -#include "komodo_notary.h" // komodo_chosennotary() +#include "komodo_notary.h" +#include "komodo.h" +#include "rpc/net.h" +#include "init.h" + /************************************************************************ * @@ -35,7 +40,8 @@ void init_string(struct return_string *s) s->ptr[0] = '\0'; } -int tx_height( const uint256 &hash ){ +int tx_height( const uint256 &hash ) +{ int nHeight = 0; CTransaction tx; uint256 hashBlock; @@ -348,11 +354,8 @@ char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port) { sprintf(url,(char *)"http://127.0.0.1:%u",port); sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params); - // printf("[%s] (%s) postdata.(%s) params.(%s) USERPASS.(%s)\n",ASSETCHAINS_SYMBOL,url,postdata,params,KMDUSERPASS); retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,userpass,method,params); - //retstr = curl_post(&cHandle,url,USERPASS,postdata,0,0,0,0); } - // fprintf(stderr, "RPC RESP: %s\n", retstr2); return(retstr2); } @@ -440,7 +443,7 @@ int32_t komodo_verifynotarizedscript(int32_t height,uint8_t *script,int32_t len, printf(" notarized, "); for (i=0; i<32; i++) printf("%02x",((uint8_t *)&hash)[i]); - printf(" opreturn from [%s] ht.%d MISMATCHED\n",ASSETCHAINS_SYMBOL,height); + printf(" opreturn from [%s] ht.%d MISMATCHED\n",chainName.symbol().c_str(),height); return(-1); } @@ -456,25 +459,20 @@ void komodo_reconsiderblock(uint256 blockhash) //fprintf(stderr,"komodo_reconsiderblock.(%s) (%s %u) -> NULL\n",params,ASSETCHAINS_USERPASS,ASSETCHAINS_RPCPORT); } -int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t NOTARIZED_HEIGHT,uint256 NOTARIZED_HASH,uint256 NOTARIZED_DESTTXID) +int32_t komodo_verifynotarization(const char *symbol,const char *dest,int32_t height,int32_t NOTARIZED_HEIGHT,uint256 NOTARIZED_HASH,uint256 NOTARIZED_DESTTXID) { - char params[256],*jsonstr,*hexstr; uint8_t *script,_script[8192]; int32_t n,len,retval = -1; cJSON *json,*txjson,*vouts,*vout,*skey; + char params[256]; + char *jsonstr = nullptr; + char *hexstr; uint8_t *script,_script[8192]; int32_t n,len,retval = -1; cJSON *json,*txjson,*vouts,*vout,*skey; script = _script; - /*params[0] = '['; - params[1] = '"'; - for (i=0; i<32; i++) - sprintf(¶ms[i*2 + 2],"%02x",((uint8_t *)&NOTARIZED_DESTTXID)[31-i]); - strcat(params,"\", 1]");*/ sprintf(params,"[\"%s\", 1]",NOTARIZED_DESTTXID.ToString().c_str()); - if ( strcmp(symbol,ASSETCHAINS_SYMBOL[0]==0?(char *)"KMD":ASSETCHAINS_SYMBOL) != 0 ) + if ( strcmp(symbol, chainName.ToString().c_str()) != 0 ) return(0); - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - printf("[%s] src.%s dest.%s params.[%s] ht.%d notarized.%d\n",ASSETCHAINS_SYMBOL,symbol,dest,params,height,NOTARIZED_HEIGHT); if ( strcmp(dest,"KMD") == 0 ) { if ( KMDUSERPASS[0] != 0 ) { - if ( ASSETCHAINS_SYMBOL[0] != 0 ) + if ( !chainName.isKMD() ) { jsonstr = komodo_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,KMD_PORT); //printf("userpass.(%s) got (%s)\n",KMDUSERPASS,jsonstr); @@ -482,7 +480,7 @@ int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t }//else jsonstr = _dex_getrawtransaction(); else return(0); // need universal way to issue DEX* API, since notaries mine most blocks, this ok } - else if ( strcmp(dest,"BTC") == 0 ) + else if ( strcmp(dest,"BTC") == 0 ) // Note: this should work for LTC too (BTC is used as an alias for LTC) { if ( BTCUSERPASS[0] != 0 ) { @@ -493,18 +491,16 @@ int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t } else { - printf("[%s] verifynotarization error unexpected dest.(%s)\n",ASSETCHAINS_SYMBOL,dest); + printf("[%s] verifynotarization error unexpected dest.(%s)\n",chainName.symbol().c_str(),dest); return(-1); } if ( jsonstr != 0 ) { if ( (json= cJSON_Parse(jsonstr)) != 0 ) { - if ( (txjson= jobj(json,(char *)"result")) != 0 && (vouts= jarray(&n,txjson,(char *)"vout")) != 0 ) + if ( (txjson= jobj(json,(char *)"result")) != 0 && (vouts= jarray(&n,txjson,(char *)"vout")) != nullptr ) { vout = jitem(vouts,n-1); - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - printf("vout.(%s)\n",jprint(vout,0)); if ( (skey= jobj(vout,(char *)"scriptPubKey")) != 0 ) { if ( (hexstr= jstr(skey,(char *)"hex")) != 0 ) @@ -643,7 +639,8 @@ bool komodo_checkopret(CBlock *pblock, CScript &merkleroot) bool komodo_hardfork_active(uint32_t time) { - return ( (ASSETCHAINS_SYMBOL[0] == 0 && chainActive.Height() > nDecemberHardforkHeight) || (ASSETCHAINS_SYMBOL[0] != 0 && time > nStakedDecemberHardforkTimestamp) ); //December 2019 hardfork + return ( (chainName.isKMD() && chainActive.Height() > nDecemberHardforkHeight) + || ( !chainName.isKMD() && time > nStakedDecemberHardforkTimestamp) ); //December 2019 hardfork } uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHeight, bool fNew, CScript scriptPubKey) @@ -705,18 +702,6 @@ int32_t komodo_isPoS(CBlock *pblock, int32_t height,CTxDestination *addressout) return(0); } -void komodo_disconnect(CBlockIndex *pindex,CBlock& block) -{ - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - //fprintf(stderr,"disconnect ht.%d\n",pindex->nHeight); - komodo_init(pindex->nHeight); - if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - { - //sp->rewinding = pindex->nHeight; - //fprintf(stderr,"-%d ",pindex->nHeight); - } else printf("komodo_disconnect: ht.%d cant get komodo_state.(%s)\n",pindex->nHeight,ASSETCHAINS_SYMBOL); -} - int32_t komodo_is_notarytx(const CTransaction& tx) { uint8_t *ptr; static uint8_t crypto777[33]; @@ -775,7 +760,7 @@ int32_t komodo_block2height(CBlock *block) return(height); } -int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block) +bool komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block) { int32_t n; if ( KOMODO_LOADINGBLOCKS == 0 ) @@ -797,7 +782,7 @@ int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block) } else memset(pubkey33,0,33); } - return(0); + return false; } int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex) @@ -819,30 +804,31 @@ int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex) uint32_t komodo_chainactive_timestamp() { - if ( chainActive.LastTip() != 0 ) - return((uint32_t)chainActive.LastTip()->GetBlockTime()); - else return(0); + AssertLockHeld(cs_main); + CBlockIndex *index = chainActive.Tip(); + if ( index != nullptr ) + return((uint32_t)index->GetBlockTime()); + return 0; } CBlockIndex *komodo_chainactive(int32_t height) { - if ( chainActive.LastTip() != 0 ) + AssertLockHeld(cs_main); + CBlockIndex *index = chainActive.Tip(); + if ( index != nullptr ) { - if ( height <= chainActive.LastTip()->nHeight ) + if ( height <= index->nHeight ) return(chainActive[height]); - // else fprintf(stderr,"komodo_chainactive height %d > active.%d\n",height,chainActive.LastTip()->nHeight); } - //fprintf(stderr,"komodo_chainactive null chainActive.LastTip() height %d\n",height); - return(0); + return 0; } uint32_t komodo_heightstamp(int32_t height) { CBlockIndex *ptr; - if ( height > 0 && (ptr= komodo_chainactive(height)) != 0 ) + if ( height > 0 && (ptr= komodo_chainactive(height)) != nullptr ) return(ptr->nTime); - //else fprintf(stderr,"komodo_heightstamp null ptr for block.%d\n",height); - return(0); + return 0; } void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height) @@ -1031,7 +1017,7 @@ uint32_t komodo_blocktime(uint256 hash) bool komodo_checkpoint(int32_t *notarized_heightp, int32_t nHeight, uint256 hash) { CBlockIndex *pindex; - if ( (pindex= chainActive.LastTip()) == 0 ) + if ( (pindex= chainActive.Tip()) == 0 ) return false; // get the most recent (highest) notarized_checkpointdata @@ -1053,7 +1039,8 @@ bool komodo_checkpoint(int32_t *notarized_heightp, int32_t nHeight, uint256 hash else if ( nHeight == notarized_height && memcmp(&hash,¬arized_hash,sizeof(hash)) != 0 ) { // the height matches, but the hash they passed us does not match the notarized_hash we found - fprintf(stderr,"[%s] nHeight.%d == NOTARIZED_HEIGHT.%d, diff hash\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height); + fprintf(stderr,"[%s] nHeight.%d == NOTARIZED_HEIGHT.%d, diff hash\n", + chainName.symbol().c_str(),nHeight,notarized_height); return false; } } @@ -1061,90 +1048,64 @@ bool komodo_checkpoint(int32_t *notarized_heightp, int32_t nHeight, uint256 hash return true; } -uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n) -{ - LOCK(cs_main); - CTransaction tx; uint256 hashBlock; CBlockIndex *pindex,*tipindex; - *txheighttimep = *txheightp = *tiptimep = 0; - *valuep = 0; - if ( !GetTransaction(hash,tx,hashBlock,true) ) - return(0); - uint32_t locktime = 0; - if ( n < tx.vout.size() ) - { - if ( (pindex= komodo_getblockindex(hashBlock)) != 0 ) - { - *valuep = tx.vout[n].nValue; - *txheightp = pindex->nHeight; - *txheighttimep = pindex->nTime; - if ( *tiptimep == 0 && (tipindex= chainActive.LastTip()) != 0 ) - *tiptimep = (uint32_t)tipindex->nTime; - locktime = tx.nLockTime; - //fprintf(stderr,"tx locktime.%u %.8f height.%d | tiptime.%u\n",locktime,(double)*valuep/COIN,*txheightp,*tiptimep); - } - } - return(locktime); -} - -uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); - -uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight) -{ - uint64_t value; uint32_t tiptime=0,txheighttimep; CBlockIndex *pindex; - if ( (pindex= chainActive[tipheight]) != 0 ) - tiptime = (uint32_t)pindex->nTime; - else fprintf(stderr,"cant find height[%d]\n",tipheight); - if ( (*locktimep= komodo_interest_args(&txheighttimep,txheightp,&tiptime,&value,hash,n)) != 0 ) - { - if ( (checkvalue == 0 || value == checkvalue) && (checkheight == 0 || *txheightp == checkheight) ) - return(komodo_interest(*txheightp,value,*locktimep,tiptime)); - //fprintf(stderr,"nValue %llu lock.%u:%u nTime.%u -> %llu\n",(long long)coins.vout[n].nValue,coins.nLockTime,timestamp,pindex->nTime,(long long)interest); - else fprintf(stderr,"komodo_accrued_interest value mismatch %llu vs %llu or height mismatch %d vs %d\n",(long long)value,(long long)checkvalue,*txheightp,checkheight); - } - return(0); -} - int32_t komodo_nextheight() { + //AssertLockHeld(cs_main); + LOCK(cs_main); // assume usually called without lock CBlockIndex *pindex; int32_t ht; - if ( (pindex= chainActive.LastTip()) != 0 && (ht= pindex->nHeight) > 0 ) + if ( (pindex= chainActive.Tip()) != 0 && (ht= pindex->nHeight) > 0 ) return(ht+1); else return(komodo_longestchain() + 1); } +/** + * @brief get the KMD chain height + * + * @param kmdheightp the chain height of KMD + * @return 1 if this chain's height >= komodo_longestchain(), otherwise 0 + */ int32_t komodo_isrealtime(int32_t *kmdheightp) { - struct komodo_state *sp; CBlockIndex *pindex; - if ( (sp= komodo_stateptrget((char *)"KMD")) != 0 ) - *kmdheightp = sp->CURRENT_HEIGHT; - else *kmdheightp = 0; - if ( (pindex= chainActive.LastTip()) != 0 && pindex->nHeight >= (int32_t)komodo_longestchain() ) - return(1); - else return(0); -} + AssertLockHeld(cs_main); -int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t cmptime,int32_t dispflag) + komodo_state *sp = komodo_stateptrget( (char*)"KMD"); + if ( sp != nullptr ) + *kmdheightp = sp->CURRENT_HEIGHT; + else + *kmdheightp = 0; + CBlockIndex *pindex = chainActive.Tip(); + if ( pindex != nullptr && pindex->nHeight >= (int32_t)komodo_longestchain() ) + return 1; + return 0; +} + +/******* + * @brief validate interest in processing a transaction + * @param tx the transaction + * @param txheight the desired chain height to evaluate + * @param cmptime the block time (often the median block time of a chunk of recent blocks) + * @returns true if tx seems okay, false if tx has been in mempool too long (currently an hour + some) + */ +bool komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t cmptime) { - dispflag = 1; - if ( KOMODO_REWIND == 0 && ASSETCHAINS_SYMBOL[0] == 0 && (int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD ) //1473793441 ) + if ( KOMODO_REWIND == 0 && chainName.isKMD() && (int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD ) //1473793441 ) { - if ( txheight > 246748 ) + if ( txheight > 246748 ) // a long time ago { - if ( txheight < 247205 ) - cmptime -= 16000; + if ( txheight < 247205 ) // a long time ago + cmptime -= 16000; // subtract about 4 1/2 hours if ( (int64_t)tx.nLockTime < cmptime-KOMODO_MAXMEMPOOLTIME ) - { - if ( tx.nLockTime != 1477258935 && dispflag != 0 ) + { + // transaction has been in mempool for more than an hour + if ( tx.nLockTime != 1477258935 ) { - fprintf(stderr,"komodo_validate_interest.%d reject.%d [%d] locktime %u cmp2.%u\n",dispflag,txheight,(int32_t)(tx.nLockTime - (cmptime-KOMODO_MAXMEMPOOLTIME)),(uint32_t)tx.nLockTime,cmptime); + fprintf(stderr,"komodo_validate_interest.%d reject.%d [%d] locktime %u cmp2.%u\n",1,txheight,(int32_t)(tx.nLockTime - (cmptime-KOMODO_MAXMEMPOOLTIME)),(uint32_t)tx.nLockTime,cmptime); } - return(-1); + return false; } - if ( 0 && dispflag != 0 ) - fprintf(stderr,"validateinterest.%d accept.%d [%d] locktime %u cmp2.%u\n",dispflag,(int32_t)txheight,(int32_t)(tx.nLockTime - (cmptime-KOMODO_MAXMEMPOOLTIME)),(int32_t)tx.nLockTime,cmptime); } } - return(0); + return true; } /* @@ -1160,53 +1121,20 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams); uint64_t komodo_commission(const CBlock *pblock,int32_t height) { - static bool didinit = false,ishush3 = false; // LABS fungible chains, cannot have any block reward! - if ( is_STAKED(ASSETCHAINS_SYMBOL) == 2 ) + if ( is_STAKED(chainName.symbol()) == 2 ) return(0); - if (!didinit) { - ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false; - didinit = true; - } + int32_t i,j,n=0,txn_count; int64_t nSubsidy; + uint64_t commission = 0; + uint64_t total = 0; - int32_t i,j,n=0,txn_count; int64_t nSubsidy; uint64_t commission,total = 0; if ( ASSETCHAINS_FOUNDERS != 0 ) { nSubsidy = GetBlockSubsidy(height,Params().GetConsensus()); //fprintf(stderr,"ht.%d nSubsidy %.8f prod %llu\n",height,(double)nSubsidy/COIN,(long long)(nSubsidy * ASSETCHAINS_COMMISSION)); commission = ((nSubsidy * ASSETCHAINS_COMMISSION) / COIN); - if (ishush3) { - int32_t starting_commission = 125000000, HALVING1 = 340000, INTERVAL = 840000, TRANSITION = 129, BR_END = 5422111; - // HUSH supply curve cannot be exactly represented via KMD AC CLI args, so we do it ourselves. - // You specify the BR, and the FR % gets added so 10% of 12.5 is 1.25 - // but to tell the AC params, I need to say "11% of 11.25" is 1.25 - // 11% ie. 1/9th cannot be exactly represented and so the FR has tiny amounts of error unless done manually - // Transition period of 128 blocks has BR=FR=0 - if (height < TRANSITION) { - commission = 0; - } else if (height < HALVING1) { - commission = starting_commission; - } else if (height < HALVING1+1*INTERVAL) { - commission = starting_commission / 2; - } else if (height < HALVING1+2*INTERVAL) { - commission = starting_commission / 4; - } else if (height < HALVING1+3*INTERVAL) { - commission = starting_commission / 8; - } else if (height < HALVING1+4*INTERVAL) { - commission = starting_commission / 16; - } else if (height < HALVING1+5*INTERVAL) { - commission = starting_commission / 32; - } else if (height < HALVING1+6*INTERVAL) { // Block 5380000 - // Block reward will go to zero between 7th+8th halvings, ac_end may need adjusting - commission = starting_commission / 64; - } else if (height < HALVING1+7*INTERVAL) { - // Block reward will be zero before this is ever reached - commission = starting_commission / 128; // Block 6220000 - } - } - if ( ASSETCHAINS_FOUNDERS > 1 ) { if ( (height % ASSETCHAINS_FOUNDERS) == 0 ) @@ -1326,32 +1254,6 @@ uint32_t komodo_stakehash(uint256 *hashp,char *address,uint8_t *hashbuf,uint256 return(addrhash.uints[0]); } -arith_uint256 komodo_adaptivepow_target(int32_t height,arith_uint256 bnTarget,uint32_t nTime) -{ - arith_uint256 origtarget,easy; int32_t diff,tipdiff; int64_t mult; bool fNegative,fOverflow; CBlockIndex *tipindex; - if ( height > 10 && (tipindex= komodo_chainactive(height - 1)) != 0 ) // disable offchain diffchange - { - diff = (nTime - tipindex->GetMedianTimePast()); - tipdiff = (nTime - tipindex->nTime); - if ( tipdiff > 13*ASSETCHAINS_BLOCKTIME ) - diff = tipdiff; - if ( diff >= 13 * ASSETCHAINS_BLOCKTIME && (height < 30 || tipdiff > 2*ASSETCHAINS_BLOCKTIME) ) - { - mult = diff - 12 * ASSETCHAINS_BLOCKTIME; - mult = (mult / ASSETCHAINS_BLOCKTIME) * ASSETCHAINS_BLOCKTIME + ASSETCHAINS_BLOCKTIME / 2; - origtarget = bnTarget; - bnTarget = bnTarget * arith_uint256(mult * mult); - easy.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); - if ( bnTarget < origtarget || bnTarget > easy ) // deal with overflow - { - bnTarget = easy; - fprintf(stderr,"tipdiff.%d diff.%d height.%d miner overflowed mult.%lld, set to mindiff\n",tipdiff,diff,height,(long long)mult); - } else fprintf(stderr,"tipdiff.%d diff.%d height.%d miner elapsed %d, adjust by factor of %lld\n",tipdiff,diff,height,diff,(long long)mult); - } //else fprintf(stderr,"height.%d tipdiff.%d diff %d, vs %d\n",height,tipdiff,diff,13*ASSETCHAINS_BLOCKTIME); - } else fprintf(stderr,"adaptive cant find height.%d\n",height); - return(bnTarget); -} - arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive) { int32_t oldflag = 0,dispflag = 0; @@ -1603,7 +1505,7 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_ */ if ( ASSETCHAINS_STAKED < 100 && bhash < POWTarget ) { - fprintf(stderr,"[%s:%i] isPoS but meets PoW diff nBits.%u < target.%u\n", ASSETCHAINS_SYMBOL, height, bhash.GetCompact(), POWTarget.GetCompact()); + fprintf(stderr,"[%s:%i] isPoS but meets PoW diff nBits.%u < target.%u\n", chainName.symbol().c_str(), height, bhash.GetCompact(), POWTarget.GetCompact()); isPoS = 0; } } @@ -1843,18 +1745,13 @@ bool komodo_appendACscriptpub() void GetKomodoEarlytxidScriptPub() { + AssertLockHeld(cs_main); if ( KOMODO_EARLYTXID == zeroid ) { fprintf(stderr, "Restart deamon with -earlytxid.\n"); StartShutdown(); return; } - if ( ASSETCHAINS_EARLYTXIDCONTRACT == EVAL_PRICES && KOMODO_SNAPSHOT_INTERVAL == 0 ) - { - fprintf(stderr, "Prices->paymentsCC contract must have -ac_snapshot enabled to pay out.\n"); - StartShutdown(); - return; - } if ( chainActive.Height() < KOMODO_EARLYTXID_HEIGHT ) { fprintf(stderr, "Cannot fetch -earlytxid before block %d.\n",KOMODO_EARLYTXID_HEIGHT); @@ -1971,13 +1868,10 @@ int32_t komodo_checkPOW(int64_t stakeTxValue, int32_t slowflag,CBlock *pblock,in if ( height == 0 ) return(0); } - //if ( ASSETCHAINS_ADAPTIVEPOW > 0 ) - // bnTarget = komodo_adaptivepow_target(height,bnTarget,pblock->nTime); - - if ( (ASSETCHAINS_SYMBOL[0] != 0 || height > 792000) && bhash > bnTarget ) + if ( ( !chainName.isKMD() || height > 792000) && bhash > bnTarget ) { failed = 1; - if ( height > 0 && ASSETCHAINS_SYMBOL[0] == 0 ) // for the fast case + if ( height > 0 && chainName.isKMD() ) // for the fast case { if ( (n= komodo_notaries(pubkeys,height,pblock->nTime)) > 0 ) { @@ -1989,7 +1883,7 @@ int32_t komodo_checkPOW(int64_t stakeTxValue, int32_t slowflag,CBlock *pblock,in } } } - else if ( possible == 0 || ASSETCHAINS_SYMBOL[0] != 0 ) + else if ( possible == 0 || !chainName.isKMD() ) { if ( KOMODO_TEST_ASSETCHAIN_SKIP_POW ) return(0); @@ -2030,7 +1924,7 @@ int32_t komodo_checkPOW(int64_t stakeTxValue, int32_t slowflag,CBlock *pblock,in // PoW fake blocks will be rejected here. If a staking tx is included in a block that meets PoW min diff after block 100, then this will reject it. if ( pblock->vtx.size() > 1 && pblock->vtx[pblock->vtx.size()-1].vout.size() == 2 && DecodeStakingOpRet(pblock->vtx[pblock->vtx.size()-1].vout[1].scriptPubKey, merkleroot) != 0 ) { - fprintf(stderr, "[%s:%d] staking tx in PoW block, nBits.%u < target.%u\n", ASSETCHAINS_SYMBOL,height,bhash.GetCompact(),bnTarget.GetCompact()); + fprintf(stderr, "[%s:%d] staking tx in PoW block, nBits.%u < target.%u\n", chainName.symbol().c_str(),height,bhash.GetCompact(),bnTarget.GetCompact()); return(-1); } // set the pindex->segid as this is now fully validated to be a PoW block. @@ -2046,7 +1940,7 @@ int32_t komodo_checkPOW(int64_t stakeTxValue, int32_t slowflag,CBlock *pblock,in } else if ( is_PoSblock < 0 ) { - fprintf(stderr,"[%s:%d] unexpected negative is_PoSblock.%d\n",ASSETCHAINS_SYMBOL,height,is_PoSblock); + fprintf(stderr,"[%s:%d] unexpected negative is_PoSblock.%d\n",chainName.symbol().c_str(),height,is_PoSblock); return(-1); } else @@ -2058,12 +1952,12 @@ int32_t komodo_checkPOW(int64_t stakeTxValue, int32_t slowflag,CBlock *pblock,in // the coinbase must pay the fees from the last transaction and the block reward at a minimum. if ( pblock->vtx.size() < 1 || pblock->vtx[0].vout.size() < 1 ) { - fprintf(stderr, "[%s:%d] missing coinbase.\n", ASSETCHAINS_SYMBOL, height); + fprintf(stderr, "[%s:%d] missing coinbase.\n", chainName.symbol().c_str(), height); return(-1); } else if ( pblock->vtx[0].vout[0].nValue < stakeTxValue ) { - fprintf(stderr, "[%s:%d] coinbase vout0.%lld < blockreward+stakingtxfee.%lld\n", ASSETCHAINS_SYMBOL, height, (long long)pblock->vtx[0].vout[0].nValue, (long long)stakeTxValue); + fprintf(stderr, "[%s:%d] coinbase vout0.%lld < blockreward+stakingtxfee.%lld\n", chainName.symbol().c_str(), height, (long long)pblock->vtx[0].vout[0].nValue, (long long)stakeTxValue); return(-1); } // set the pindex->segid as this is now fully validated to be a PoS block. @@ -2122,7 +2016,7 @@ int32_t komodo_checkPOW(int64_t stakeTxValue, int32_t slowflag,CBlock *pblock,in if ( slowflag == 0 && pblock->vtx[0].vout.size() > 1 ) { // Check the notarisation tx is to the crypto address. - if ( !komodo_is_notarytx(pblock->vtx[1]) == 1 ) + if ( !komodo_is_notarytx(pblock->vtx[1]) ) { fprintf(stderr, "notarisation is not to crypto address ht.%i\n",height); return(-1); @@ -2151,10 +2045,11 @@ int32_t komodo_acpublic(uint32_t tiptime) { if ( tiptime == 0 ) { - if ( (pindex= chainActive.LastTip()) != 0 ) + AssertLockHeld(cs_main); + if ( (pindex= chainActive.Tip()) != 0 ) tiptime = pindex->nTime; } - if ( (ASSETCHAINS_SYMBOL[0] == 0 || strcmp(ASSETCHAINS_SYMBOL,"ZEX") == 0) && tiptime >= KOMODO_SAPLING_DEADLINE ) + if ( (chainName.isKMD() || chainName.isSymbol("ZEX")) && tiptime >= KOMODO_SAPLING_DEADLINE ) acpublic = 1; } return(acpublic); @@ -2209,7 +2104,7 @@ int64_t komodo_newcoins(int64_t *zfundsp,int64_t *sproutfundsp,int32_t nHeight,C } *zfundsp = zfunds; *sproutfundsp = sproutfunds; - if ( ASSETCHAINS_SYMBOL[0] == 0 && (voutsum-vinsum) == 100003*SATOSHIDEN ) // 15 times + if ( chainName.isKMD() && (voutsum-vinsum) == 100003*SATOSHIDEN ) // 15 times return(3 * SATOSHIDEN); //if ( voutsum-vinsum+zfunds > 100000*SATOSHIDEN || voutsum-vinsum+zfunds < 0 ) //. fprintf(stderr,"ht.%d vins %.8f, vouts %.8f -> %.8f zfunds %.8f\n",nHeight,dstr(vinsum),dstr(voutsum),dstr(voutsum)-dstr(vinsum),dstr(zfunds)); @@ -2247,35 +2142,36 @@ int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height) return(supply); } -struct komodo_staking *komodo_addutxo(struct komodo_staking *array,int32_t *numkp,int32_t *maxkp,uint32_t txtime,uint64_t nValue,uint256 txid,int32_t vout,char *address,uint8_t *hashbuf,CScript pk) +void komodo_addutxo(std::vector &array,uint32_t txtime,uint64_t nValue,uint256 txid,int32_t vout,char *address,uint8_t *hashbuf,CScript pk) { - uint256 hash; uint32_t segid32; struct komodo_staking *kp; + uint256 hash; uint32_t segid32; komodo_staking kp; segid32 = komodo_stakehash(&hash,address,hashbuf,txid,vout); - if ( *numkp >= *maxkp ) - { - *maxkp += 1000; - array = (struct komodo_staking *)realloc(array,sizeof(*array) * (*maxkp)); - //fprintf(stderr,"realloc max.%d array.%p\n",*maxkp,array); - } - kp = &array[(*numkp)++]; - //fprintf(stderr,"kp.%p num.%d\n",kp,*numkp); - memset(kp,0,sizeof(*kp)); - strcpy(kp->address,address); - kp->txid = txid; - kp->vout = vout; - kp->hashval = UintToArith256(hash); - kp->txtime = txtime; - kp->segid32 = segid32; - kp->nValue = nValue; - kp->scriptPubKey = pk; - return(array); + if ( array.size() >= array.capacity() ) + { + array.reserve(array.capacity() + 1000); + //fprintf(stderr,"%s realloc array.size().%d array.capacity().%d\n", __func__, array.size(), array.capacity()); + } + //memset(&kp,0,sizeof(kp)); + strcpy(kp.address, address); + kp.txid = txid; + kp.vout = vout; + kp.hashval = UintToArith256(hash); + kp.txtime = txtime; + kp.segid32 = segid32; + kp.nValue = nValue; + kp.scriptPubKey = pk; + array.push_back(kp); + //fprintf(stderr,"kp.%p array.size().%d\n",kp,array.size()); } int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig, uint256 merkleroot) { - static struct komodo_staking *array; static int32_t numkp,maxkp; static uint32_t lasttime; + // use thread_local to prevent crash in case of accidental thread overlapping + thread_local std::vector array; + thread_local uint32_t lasttime; + int32_t PoSperc = 0, newStakerActive; - std::set setAddress; struct komodo_staking *kp; int32_t winners,segid,minage,nHeight,counter=0,i,m,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; std::vector vecOutputs; uint32_t block_from_future_rejecttime,besttime,eligible,earliest = 0; CScript best_scriptPubKey; arith_uint256 mindiff,ratio,bnTarget,tmpTarget; CBlockIndex *tipindex,*pindex; CTxDestination address; bool fNegative,fOverflow; uint8_t hashbuf[256]; CTransaction tx; uint256 hashBlock; + std::set setAddress; int32_t winners,segid,minage,nHeight,counter=0,i,m,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; std::vector vecOutputs; uint32_t block_from_future_rejecttime,besttime,eligible,earliest = 0; CScript best_scriptPubKey; arith_uint256 mindiff,ratio,bnTarget,tmpTarget; CBlockIndex *pindex; CTxDestination address; bool fNegative,fOverflow; uint8_t hashbuf[256]; CTransaction tx; uint256 hashBlock; uint64_t cbPerc = *utxovaluep, tocoinbase = 0; if (!EnsureWalletIsAvailable(0)) return 0; @@ -2286,7 +2182,12 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt memset(utxotxidp,0,sizeof(*utxotxidp)); memset(utxovoutp,0,sizeof(*utxovoutp)); memset(utxosig,0,72); - if ( (tipindex= chainActive.Tip()) == 0 ) + CBlockIndex *tipindex = nullptr; + { + LOCK(cs_main); + tipindex = chainActive.Tip(); + } + if ( tipindex == nullptr ) return(0); nHeight = tipindex->nHeight + 1; if ( (minage= nHeight*3) > 6000 ) // about 100 blocks @@ -2297,7 +2198,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt // this was for VerusHash PoS64 //tmpTarget = komodo_PoWtarget(&PoSperc,bnTarget,nHeight,ASSETCHAINS_STAKED); bool resetstaker = false; - if ( array != 0 ) + if ( array.size() != 0 ) { LOCK(cs_main); CBlockIndex* pblockindex = chainActive[tipindex->nHeight]; @@ -2305,26 +2206,24 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt if ( ReadBlockFromDisk(block, pblockindex, 1) && komodo_isPoS(&block, nHeight, &addressout) != 0 && IsMine(*pwalletMain,addressout) != 0 ) { resetstaker = true; - fprintf(stderr, "[%s:%d] Reset ram staker after mining a block!\n",ASSETCHAINS_SYMBOL,nHeight); + fprintf(stderr, "[%s:%d] Reset ram staker after mining a block!\n",chainName.symbol().c_str(),nHeight); } } - if ( resetstaker || array == 0 || time(NULL) > lasttime+600 ) + if ( resetstaker || array.size() == 0 || time(NULL) > lasttime+600 ) { LOCK2(cs_main, pwalletMain->cs_wallet); pwalletMain->AvailableCoins(vecOutputs, false, NULL, true); - if ( array != 0 ) + if ( array.size() != 0 ) { - free(array); - array = 0; - maxkp = numkp = 0; + array.clear(); lasttime = 0; } BOOST_FOREACH(const COutput& out, vecOutputs) { if ( (tipindex= chainActive.Tip()) == 0 || tipindex->nHeight+1 > nHeight ) { - fprintf(stderr,"[%s:%d] chain tip changed during staking loop t.%u counter.%d\n",ASSETCHAINS_SYMBOL,nHeight,(uint32_t)time(NULL),counter); + fprintf(stderr,"[%s:%d] chain tip changed during staking loop t.%u counter.%d\n",chainName.symbol().c_str(),nHeight,(uint32_t)time(NULL),counter); return(0); } counter++; @@ -2343,41 +2242,45 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt continue; if ( myGetTransaction(out.tx->GetHash(),tx,hashBlock) != 0 && (pindex= komodo_getblockindex(hashBlock)) != 0 ) { - array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,out.tx->GetHash(),out.i,(char *)CBitcoinAddress(address).ToString().c_str(),hashbuf,(CScript)pk); - //fprintf(stderr,"addutxo numkp.%d vs max.%d\n",numkp,maxkp); + komodo_addutxo(array,(uint32_t)pindex->nTime,(uint64_t)nValue,out.tx->GetHash(),out.i,(char *)CBitcoinAddress(address).ToString().c_str(),hashbuf,(CScript)pk); + //fprintf(stderr,"%s array.size().%d vs array.capacity().%d\n", __func__,array.size(),array.capacity()); } } } lasttime = (uint32_t)time(NULL); - //fprintf(stderr,"finished kp data of utxo for staking %u ht.%d numkp.%d maxkp.%d\n",(uint32_t)time(NULL),nHeight,numkp,maxkp); + //fprintf(stderr,"%s finished kp data of utxo for staking %u ht.%d array.size().%d array.capacity().%d\n", __func__,(uint32_t)time(NULL),nHeight,array.size(),array.capacity()); } block_from_future_rejecttime = (uint32_t)GetTime() + ASSETCHAINS_STAKED_BLOCK_FUTURE_MAX; - for (i=winners=0; inHeight+1 > nHeight ) { - fprintf(stderr,"[%s:%d] chain tip changed during staking loop t.%u counter.%d\n",ASSETCHAINS_SYMBOL,nHeight,(uint32_t)time(NULL),i); - return(0); + LOCK(cs_main); + tipindex = chainActive.Tip(); } - kp = &array[i]; - eligible = komodo_stake(0,bnTarget,nHeight,kp->txid,kp->vout,0,(uint32_t)tipindex->nTime+ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF,kp->address,PoSperc); + if ( tipindex == nullptr || tipindex->nHeight+1 > nHeight ) + { + fprintf(stderr,"[%s:%d] chain tip changed during staking loop t.%u counter.%d\n",chainName.symbol().c_str(),nHeight,(uint32_t)time(NULL),i); + return 0; + } + komodo_staking &kp = array[i]; + eligible = komodo_stake(0,bnTarget,nHeight,kp.txid,kp.vout,0,(uint32_t)tipindex->nTime+ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF,kp.address,PoSperc); if ( eligible > 0 ) { besttime = 0; - if ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF,kp->address,PoSperc) ) + if ( eligible == komodo_stake(1,bnTarget,nHeight,kp.txid,kp.vout,eligible,(uint32_t)tipindex->nTime+ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF,kp.address,PoSperc) ) { // have elegible utxo to stake with. - if ( earliest == 0 || eligible < earliest || (eligible == earliest && (*utxovaluep == 0 || kp->nValue < *utxovaluep)) ) + if ( earliest == 0 || eligible < earliest || (eligible == earliest && (*utxovaluep == 0 || kp.nValue < *utxovaluep)) ) { // is better than the previous best, so use it instead. earliest = eligible; - best_scriptPubKey = kp->scriptPubKey; - *utxovaluep = (uint64_t)kp->nValue; - decode_hex((uint8_t *)utxotxidp,32,(char *)kp->txid.GetHex().c_str()); - *utxovoutp = kp->vout; - *txtimep = kp->txtime; + best_scriptPubKey = kp.scriptPubKey; + *utxovaluep = (uint64_t)kp.nValue; + decode_hex((uint8_t *)utxotxidp,32,(char *)kp.txid.GetHex().c_str()); + *utxovoutp = kp.vout; + *txtimep = kp.txtime; } /*if ( eligible < block_from_future_rejecttime ) { @@ -2388,17 +2291,20 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt } } } - if ( numkp < 500 && array != 0 ) + if ( array.size() < 500 && array.size() != 0 ) { - free(array); - array = 0; - maxkp = numkp = 0; + array.clear(); lasttime = 0; } if ( earliest != 0 ) { bool signSuccess; SignatureData sigdata; uint64_t txfee; uint8_t *ptr; uint256 revtxid,utxotxid; - auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); + int newHeight = 0; + { + LOCK(cs_main); + newHeight = chainActive.Height() + 1; + } + auto consensusBranchId = CurrentEpochBranchId(newHeight, Params().GetConsensus()); const CKeyStore& keystore = *pwalletMain; txNew.vin.resize(1); txNew.vout.resize(1); diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index 29174c2b92c..4e5a20b3af0 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -21,20 +21,12 @@ #include "komodo_defs.h" #include "script/standard.h" #include "cc/CCinclude.h" +#include "komodo_globals.h" -int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); -int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp); -int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i,int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp,uint64_t value,int32_t notarized,uint64_t signedmask,uint32_t timestamp); -unsigned int lwmaGetNextPOSRequired(const CBlockIndex* pindexLast, const Consensus::Params& params); bool EnsureWalletIsAvailable(bool avoidException); -extern bool fRequestShutdown; -extern CScript KOMODO_EARLYTXID_SCRIPTPUB; -uint8_t DecodeMaramaraCoinbaseOpRet(const CScript scriptPubKey,CPubKey &pk,int32_t &height,int32_t &unlockht); uint32_t komodo_heightstamp(int32_t height); -//#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"curl",(char *)"http://127.0.0.1:7776",0,0,(char *)(cmdstr)) - struct MemoryStruct { char *memory; size_t size; }; struct return_string { char *ptr; size_t len; }; @@ -101,7 +93,7 @@ int32_t komodo_verifynotarizedscript(int32_t height,uint8_t *script,int32_t len, void komodo_reconsiderblock(uint256 blockhash); -int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t NOTARIZED_HEIGHT,uint256 NOTARIZED_HASH,uint256 NOTARIZED_DESTTXID); +int32_t komodo_verifynotarization(const char *symbol, const char *dest,int32_t height,int32_t NOTARIZED_HEIGHT,uint256 NOTARIZED_HASH,uint256 NOTARIZED_DESTTXID); CScript komodo_makeopret(CBlock *pblock, bool fNew); @@ -129,13 +121,11 @@ uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHe int32_t komodo_isPoS(CBlock *pblock, int32_t height,CTxDestination *addressout); -void komodo_disconnect(CBlockIndex *pindex,CBlock& block); - int32_t komodo_is_notarytx(const CTransaction& tx); int32_t komodo_block2height(CBlock *block); -int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); +bool komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex); @@ -143,8 +133,6 @@ uint32_t komodo_chainactive_timestamp(); CBlockIndex *komodo_chainactive(int32_t height); -uint32_t komodo_heightstamp(int32_t height); - void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height); int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t blocktimes[66],int32_t *nonzpkeysp,int32_t height); @@ -170,15 +158,18 @@ uint32_t komodo_blocktime(uint256 hash); */ bool komodo_checkpoint(int32_t *notarized_heightp,int32_t nHeight,uint256 hash); -uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n); - -uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); - int32_t komodo_nextheight(); int32_t komodo_isrealtime(int32_t *kmdheightp); -int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t cmptime,int32_t dispflag); +/******* + * @brief validate interest in processing a transaction + * @param tx the transaction + * @param txheight the desired chain height to evaluate + * @param cmptime the block time (often the median block time of a chunk of recent blocks) + * @returns true if tx seems okay, false if tx has been in mempool too long (currently an hour + some) + */ +bool komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t cmptime); /* komodo_checkPOW (fast) is called early in the process and should only refer to data immediately available. it is a filter to prevent bad blocks from going into the local DB. The more blocks we can filter out at this stage, the less junk in the local DB that will just get purged later on. @@ -199,8 +190,6 @@ void komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n); uint32_t komodo_stakehash(uint256 *hashp,char *address,uint8_t *hashbuf,uint256 txid,int32_t vout); -arith_uint256 komodo_adaptivepow_target(int32_t height,arith_uint256 bnTarget,uint32_t nTime); - arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive); uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeight,uint256 txid,int32_t vout,uint32_t blocktime,uint32_t prevtime,char *destaddr,int32_t PoSperc); @@ -244,6 +233,6 @@ struct komodo_staking CScript scriptPubKey; }; -struct komodo_staking *komodo_addutxo(struct komodo_staking *array,int32_t *numkp,int32_t *maxkp,uint32_t txtime,uint64_t nValue,uint256 txid,int32_t vout,char *address,uint8_t *hashbuf,CScript pk); +void komodo_addutxo(std::vector &array,uint32_t txtime,uint64_t nValue,uint256 txid,int32_t vout,char *address,uint8_t *hashbuf,CScript pk); int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig, uint256 merkleroot); diff --git a/src/komodo_cJSON.c b/src/komodo_cJSON.c index 14c190de36d..0cdd79316d7 100644 --- a/src/komodo_cJSON.c +++ b/src/komodo_cJSON.c @@ -27,10 +27,6 @@ #include "cJSON.h" #include "hex.h" -#ifndef DBL_EPSILON -#define DBL_EPSILON 2.2204460492503131E-16 -#endif - static const char *ep; long stripquotes(char *str) diff --git a/src/komodo_cJSON.h b/src/komodo_cJSON.h index 8fdb338c738..94f07fb6ab2 100644 --- a/src/komodo_cJSON.h +++ b/src/komodo_cJSON.h @@ -54,6 +54,10 @@ #define MAX_JSON_FIELD 4096 // on the big side +#ifndef DBL_EPSILON +#define DBL_EPSILON 2.2204460492503131E-16 +#endif + #ifdef __cplusplus extern "C" { diff --git a/src/komodo_ccdata.cpp b/src/komodo_ccdata.cpp index 083ba18156c..d2e6897ff01 100644 --- a/src/komodo_ccdata.cpp +++ b/src/komodo_ccdata.cpp @@ -13,12 +13,16 @@ * * ******************************************************************************/ #include "komodo_ccdata.h" +#include "komodo_globals.h" +#include "komodo_bitcoind.h" #include "komodo_extern_globals.h" +#include "komodo_utils.h" struct komodo_ccdata *CC_data; -int32_t CC_firstheight; +//int32_t CC_firstheight; +pthread_mutex_t KOMODO_CC_mutex; -uint256 BuildMerkleTree(bool* fMutated, const std::vector leaves, std::vector &vMerkleTree); +//uint256 BuildMerkleTree(bool* fMutated, const std::vector leaves, std::vector &vMerkleTree); uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth) { @@ -178,7 +182,7 @@ int32_t komodo_MoMoMdata(char *hexstr,int32_t hexsize,struct komodo_ccdataMoMoM void komodo_purge_ccdata(int32_t height) { struct komodo_ccdata *ccdata,*tmpptr; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) + if ( chainName.isKMD() ) { portable_mutex_lock(&KOMODO_CC_mutex); DL_FOREACH_SAFE(CC_data,ccdata,tmpptr) diff --git a/src/komodo_curve25519.cpp b/src/komodo_curve25519.cpp index 1b0dc7bb2bf..db76fb801c3 100644 --- a/src/komodo_curve25519.cpp +++ b/src/komodo_curve25519.cpp @@ -202,7 +202,6 @@ bits256 curve25519_keypair(bits256 *pubkeyp) bits256 privkey; privkey = rand256(1); *pubkeyp = curve25519(privkey,curve25519_basepoint9()); - //printf("[%llx %llx] ",privkey.txid,(*pubkeyp).txid); return(privkey); } @@ -211,8 +210,6 @@ bits256 curve25519_shared(bits256 privkey,bits256 otherpub) bits256 shared,hash; shared = curve25519(privkey,otherpub); vcalc_sha256(0,hash.bytes,shared.bytes,sizeof(shared)); - //printf("priv.%llx pub.%llx shared.%llx -> hash.%llx\n",privkey.txid,pubkey.txid,shared.txid,hash.txid); - //hash.bytes[0] &= 0xf8, hash.bytes[31] &= 0x7f, hash.bytes[31] |= 64; return(hash); } @@ -226,74 +223,26 @@ int32_t curve25519_donna(uint8_t *mypublic,const uint8_t *secret,const uint8_t * return(0); } -uint64_t conv_NXTpassword(unsigned char *mysecret,unsigned char *mypublic,uint8_t *pass,int32_t passlen) +/*** + * @param[out] mysecret a hash of pass + * @param[in] mypublic the public key + * @param[in] pass the password + * @param[in] passlen the length of pass + * @return a hash of mypublic (unused) + */ +uint64_t conv_NXTpassword(unsigned char *mysecret, unsigned char *mypublic, uint8_t *pass, int32_t passlen) { static uint8_t basepoint[32] = {9}; - uint64_t addr; uint8_t hash[32]; + uint64_t addr; + uint8_t hash[32]; if ( pass != 0 && passlen != 0 ) vcalc_sha256(0,mysecret,pass,passlen); - mysecret[0] &= 248, mysecret[31] &= 127, mysecret[31] |= 64; + mysecret[0] &= 248; + mysecret[31] &= 127; + mysecret[31] |= 64; curve25519_donna(mypublic,mysecret,basepoint); + // hash mypublic vcalc_sha256(0,hash,mypublic,32); memcpy(&addr,hash,sizeof(addr)); - return(addr); -} - -uint256 komodo_kvprivkey(uint256 *pubkeyp,char *passphrase) -{ - uint256 privkey; - conv_NXTpassword((uint8_t *)&privkey,(uint8_t *)pubkeyp,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); - return(privkey); -} - -uint256 komodo_kvsig(uint8_t *buf,int32_t len,uint256 _privkey) -{ - bits256 sig,hash,otherpub,checksig,pubkey,privkey; uint256 usig; - memcpy(&privkey,&_privkey,sizeof(privkey)); - vcalc_sha256(0,hash.bytes,buf,len); - otherpub = curve25519(hash,curve25519_basepoint9()); - pubkey = curve25519(privkey,curve25519_basepoint9()); - sig = curve25519_shared(privkey,otherpub); - checksig = curve25519_shared(hash,pubkey); - /*int32_t i; for (i=0; i "); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&privkey)[i]); - printf(" -> "); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&pubkey)[i]); - printf(" pubkey\n");*/ - memcpy(&usig,&sig,sizeof(usig)); - return(usig); -} - -int32_t komodo_kvsigverify(uint8_t *buf,int32_t len,uint256 _pubkey,uint256 sig) -{ - bits256 hash,checksig,pubkey; static uint256 zeroes; - memcpy(&pubkey,&_pubkey,sizeof(pubkey)); - if ( memcmp(&pubkey,&zeroes,sizeof(pubkey)) != 0 ) - { - vcalc_sha256(0,hash.bytes,buf,len); - checksig = curve25519_shared(hash,pubkey); - /*int32_t i; for (i=0; i "); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&hash)[i]); - printf(" -> "); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&pubkey)[i]); - printf(" verify pubkey\n"); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&sig)[i]); - printf(" sig vs"); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&checksig)[i]); - printf(" checksig\n");*/ - if ( memcmp(&checksig,&sig,sizeof(sig)) != 0 ) - return(-1); - //else printf("VALIDATED\n"); - } - return(0); + return addr; } diff --git a/src/komodo_curve25519.h b/src/komodo_curve25519.h index 9b755c11838..fc7acc3892f 100644 --- a/src/komodo_curve25519.h +++ b/src/komodo_curve25519.h @@ -765,9 +765,3 @@ bits256 curve25519_shared(bits256 privkey,bits256 otherpub); int32_t curve25519_donna(uint8_t *mypublic,const uint8_t *secret,const uint8_t *basepoint); uint64_t conv_NXTpassword(unsigned char *mysecret,unsigned char *mypublic,uint8_t *pass,int32_t passlen); - -uint256 komodo_kvprivkey(uint256 *pubkeyp,char *passphrase); - -uint256 komodo_kvsig(uint8_t *buf,int32_t len,uint256 _privkey); - -int32_t komodo_kvsigverify(uint8_t *buf,int32_t len,uint256 _pubkey,uint256 sig); diff --git a/src/komodo_cutils.cpp b/src/komodo_cutils.cpp index 4fa84fe6932..78f8f9c0597 100644 --- a/src/komodo_cutils.cpp +++ b/src/komodo_cutils.cpp @@ -49,9 +49,6 @@ char *clonestr(char *str) if ( str == 0 || str[0] == 0 ) { printf("warning cloning nullstr.%p\n",str); -#ifdef __APPLE__ - while ( 1 ) sleep(1); -#endif str = (char *)""; } clone = (char *)malloc(strlen(str)+16); diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 451c1a38af4..cf82ef4a50d 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -12,22 +12,23 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ +#pragma once -#ifndef KOMODO_DEFS_H -#define KOMODO_DEFS_H #include "arith_uint256.h" +#define ASSETCHAINS_MAX_ERAS 7 // needed by chain.h #include "chain.h" +#include "assetchain.h" #include "komodo_nk.h" +#define NUM_KMD_NOTARIES 64 + #define KOMODO_EARLYTXID_HEIGHT 100 -//#define ADAPTIVEPOW_CHANGETO_DEFAULTON 1572480000 #define ASSETCHAINS_MINHEIGHT 128 -#define ASSETCHAINS_MAX_ERAS 7 #define KOMODO_ELECTION_GAP 2000 #define KOMODO_ASSETCHAIN_MAXLEN 65 #define KOMODO_LIMITED_NETWORKSIZE 4 #define IGUANA_MAXSCRIPTSIZE 10001 -#define KOMODO_MAXMEMPOOLTIME 3600 // affects consensus +#define KOMODO_MAXMEMPOOLTIME 3600 // affects consensus, 3600 secs = 1hr #define CRYPTO777_PUBSECPSTR "020e46e79a2a8d12b9b5d12c7a91adb4e454edfae43c0a0cb805427d2ac7613fd9" #define KOMODO_FIRSTFUNGIBLEID 100 #define KOMODO_SAPLING_ACTIVATION 1544832000 // Dec 15th, 2018 @@ -35,18 +36,8 @@ #define ASSETCHAINS_STAKED_BLOCK_FUTURE_MAX 57 #define ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF 27 #define ASSETCHAINS_STAKED_MIN_POW_DIFF 536900000 // 537000000 537300000 -#define _COINBASE_MATURITY 100 #define _ASSETCHAINS_TIMELOCKOFF 0xffffffffffffffff -// KMD Notary Seasons -// 1: May 1st 2018 1530921600 -// 2: July 15th 2019 1563148800 -> estimated height 1444000 -// 3: 3rd season ending isnt known, so use very far times in future. - // 1751328000 = dummy timestamp, 1 July 2025! - // 7113400 = 5x current KMD blockheight. -// to add 4th season, change NUM_KMD_SEASONS to 4, and add timestamp and height of activation to these arrays. - - #define SETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] |= (1 << ((bitoffset) & 7))) #define GETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] & (1 << ((bitoffset) & 7))) #define CLEARBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] &= ~(1 << ((bitoffset) & 7))) @@ -55,87 +46,53 @@ #define KOMODO_BIT63SET(x) ((x) & ((uint64_t)1 << 63)) #define KOMODO_VALUETOOBIG(x) ((x) > (uint64_t)10000000001*COIN) -//#ifndef TESTMODE -#define PRICES_DAYWINDOW ((3600*24/ASSETCHAINS_BLOCKTIME) + 1) -//#else -//#define PRICES_DAYWINDOW (7) -//#endif -extern uint8_t ASSETCHAINS_TXPOW,ASSETCHAINS_PUBLIC; -extern int8_t ASSETCHAINS_ADAPTIVEPOW; +#define SATOSHIDEN ((uint64_t)100000000L) +#define dstr(x) ((double)(x) / SATOSHIDEN) +#define SMALLVAL 0.000000000000001 + +//#define PRICES_DAYWINDOW ((3600*24/ASSETCHAINS_BLOCKTIME) + 1) + int32_t MAX_BLOCK_SIZE(int32_t height); -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; -extern uint32_t ASSETCHAIN_INIT, ASSETCHAINS_MAGIC; -extern int32_t ASSETCHAINS_SAPLING, ASSETCHAINS_OVERWINTER,ASSETCHAINS_BLOCKTIME; -extern uint64_t ASSETCHAINS_SUPPLY, ASSETCHAINS_FOUNDERS_REWARD; - -extern uint64_t ASSETCHAINS_TIMELOCKGTE; -extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH,KOMODO_INITDONE; - -extern bool IS_KOMODO_NOTARY; -extern int32_t KOMODO_MININGTHREADS,KOMODO_LONGESTCHAIN,ASSETCHAINS_SEED,USE_EXTERNAL_PUBKEY,KOMODO_ON_DEMAND,KOMODO_PASSPORT_INITDONE,ASSETCHAINS_STAKED,KOMODO_NSPV; -extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_LASTERA,ASSETCHAINS_CBOPRET; -extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[],ASSETCHAINS_NK[2]; + +extern int32_t ASSETCHAINS_BLOCKTIME; +extern uint32_t ASSETCHAINS_ALGO; +extern int32_t KOMODO_LONGESTCHAIN,USE_EXTERNAL_PUBKEY; +extern uint64_t ASSETCHAINS_COMMISSION; +extern uint64_t ASSETCHAINS_NONCEMASK[],ASSETCHAINS_NK[2]; extern const char *ASSETCHAINS_ALGORITHMS[]; -extern uint32_t ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[]; -extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY,ASSETCHAINS_SCRIPTPUB; -extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33]; -extern std::vector ASSETCHAINS_PRICES,ASSETCHAINS_STOCKS; - -extern uint256 KOMODO_EARLYTXID; - -extern bool IS_KOMODO_DEALERNODE; -extern int32_t KOMODO_CONNECTING,KOMODO_CCACTIVATE; -extern uint32_t ASSETCHAINS_CC; -extern std::string CCerror,ASSETCHAINS_CCLIB; -extern uint8_t ASSETCHAINS_CCDISABLES[256]; - -extern int32_t USE_EXTERNAL_PUBKEY; -extern std::string NOTARY_PUBKEY,NOTARY_ADDRESS; -extern bool IS_MODE_EXCHANGEWALLET; -extern std::string DONATION_PUBKEY; -extern uint8_t ASSETCHAINS_PRIVATE; -extern int32_t USE_EXTERNAL_PUBKEY; +extern uint32_t ASSETCHAINS_NONCESHIFT[]; + +extern std::string CCerror; + extern bool IS_KOMODO_TESTNODE; -extern int32_t KOMODO_SNAPSHOT_INTERVAL,STAKED_NOTARY_ID,STAKED_ERA; +extern int32_t KOMODO_SNAPSHOT_INTERVAL; extern int32_t ASSETCHAINS_EARLYTXIDCONTRACT; extern int32_t ASSETCHAINS_STAKED_SPLIT_PERCENTAGE; -int tx_height( const uint256 &hash ); -extern std::vector vWhiteListAddress; extern std::map mapHeightEvalActivate; + +uint256 Parseuint256(const char *hexstr); // defined in cc/CCutilbits.cpp void komodo_netevent(std::vector payload); +/* TODO: remove +extern std::vector vWhiteListAddress; +extern std::map mapHeightEvalActivate; int32_t getacseason(uint32_t timestamp); int32_t getkmdseason(int32_t height); #define IGUANA_MAXSCRIPTSIZE 10001 +*/ #define KOMODO_KVDURATION 1440 -#define KOMODO_KVBINARY 2 -#define PRICES_SMOOTHWIDTH 1 -#define PRICES_MAXDATAPOINTS 8 -uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume); -int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel); +#define KOMODO_KVPROTECTED 1 +/*#define PRICES_MAXDATAPOINTS 8 int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len); int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width); int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); uint32_t komodo_blocktime(uint256 hash); -int32_t komodo_longestchain(); int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); int8_t komodo_segid(int32_t nocache,int32_t height); -int32_t komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHeight); -char *komodo_pricename(char *name,int32_t ind); -int32_t komodo_priceind(const char *symbol); -int32_t komodo_pricesinit(); -int64_t komodo_priceave(int64_t *tmpbuf,int64_t *correlated,int32_t cskip); -int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int32_t rawskip,uint32_t *nonzprices,int32_t smoothwidth); int32_t komodo_nextheight(); -uint32_t komodo_heightstamp(int32_t height); -int64_t komodo_pricemult(int32_t ind); -int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblocks); -uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); -int32_t komodo_currentheight(); int32_t komodo_notarized_bracket(struct notarized_checkpoint *nps[2],int32_t height); arith_uint256 komodo_adaptivepow_target(int32_t height,arith_uint256 bnTarget,uint32_t nTime); bool komodo_hardfork_active(uint32_t time); @@ -152,7 +109,7 @@ bool komodo_txnotarizedconfirmed(uint256 txid); int32_t komodo_blockload(CBlock& block, CBlockIndex *pindex); uint32_t komodo_chainactive_timestamp(); uint32_t GetLatestTimestamp(int32_t height); - +*/ #ifndef KOMODO_NSPV_FULLNODE #define KOMODO_NSPV_FULLNODE (KOMODO_NSPV <= 0) #endif // !KOMODO_NSPV_FULLNODE @@ -160,4 +117,3 @@ uint32_t GetLatestTimestamp(int32_t height); #define KOMODO_NSPV_SUPERLITE (KOMODO_NSPV > 0) #endif // !KOMODO_NSPV_SUPERLITE -#endif diff --git a/src/komodo_events.cpp b/src/komodo_events.cpp index e9c4b68aff1..ef6da5e02f0 100644 --- a/src/komodo_events.cpp +++ b/src/komodo_events.cpp @@ -13,11 +13,17 @@ * * ******************************************************************************/ #include "komodo_events.h" -#include "komodo_extern_globals.h" +#include "komodo_globals.h" #include "komodo_bitcoind.h" // komodo_verifynotarization #include "komodo_notary.h" // komodo_notarized_update -#include "komodo_pax.h" // komodo_pvals -#include "komodo_gateway.h" // komodo_opreturn +#include "komodo_kv.h" + +#define KOMODO_EVENT_RATIFY 'P' +#define KOMODO_EVENT_NOTARIZED 'N' +#define KOMODO_EVENT_KMDHEIGHT 'K' +#define KOMODO_EVENT_REWIND 'B' +#define KOMODO_EVENT_PRICEFEED 'V' +#define KOMODO_EVENT_OPRETURN 'R' /***** * Add a notarized event to the collection @@ -26,25 +32,32 @@ * @param height * @param ntz the event */ -void komodo_eventadd_notarized( komodo_state *sp, char *symbol, int32_t height, std::shared_ptr ntz) +void komodo_eventadd_notarized( komodo_state *sp, const char *symbol, int32_t height, komodo::event_notarized& ntz) { - char *coin = (ASSETCHAINS_SYMBOL[0] == 0) ? (char *)"KMD" : ASSETCHAINS_SYMBOL; + if (IS_KOMODO_NOTARY) { + int32_t ntz_verify = komodo_verifynotarization(symbol, ntz.dest, height, ntz.notarizedheight, ntz.blockhash, ntz.desttxid); + LogPrint("notarisation", "komodo_verifynotarization result %d\n", ntz_verify); - if ( IS_KOMODO_NOTARY - && komodo_verifynotarization(symbol,ntz->dest,height,ntz->notarizedheight,ntz->blockhash, ntz->desttxid) < 0 ) - { - static uint32_t counter; - if ( counter++ < 100 ) - printf("[%s] error validating notarization ht.%d notarized_height.%d, if on a pruned %s node this can be ignored\n", - ASSETCHAINS_SYMBOL,height,ntz->notarizedheight, ntz->dest); + if (ntz_verify < 0) { + static uint32_t counter; + if ( counter++ < 100 ) + printf("[%s] error validating notarization ht.%d notarized_height.%d, if on a pruned %s node this can be ignored\n", + chainName.symbol().c_str(), height, ntz.notarizedheight, ntz.dest); + return; + } } - else if ( strcmp(symbol,coin) == 0 ) + + if (chainName.isSymbol(symbol) || chainName.isKMD() && std::string(symbol) == "KMD" /*special case for KMD*/) { - if ( sp != nullptr ) + if (sp != nullptr) { sp->add_event(symbol, height, ntz); - komodo_notarized_update(sp,height, ntz->notarizedheight, ntz->blockhash, ntz->desttxid, ntz->MoM, ntz->MoMdepth); + komodo_notarized_update(sp, height, ntz.notarizedheight, ntz.blockhash, ntz.desttxid, ntz.MoM, ntz.MoMdepth); + } else { + LogPrintf("could not update notarisation event: komodo_state is null"); } + } else { + LogPrintf("could not update notarisation event: invalid symbol %s", symbol); } } @@ -55,28 +68,28 @@ void komodo_eventadd_notarized( komodo_state *sp, char *symbol, int32_t height, * @param height * @param pk the event */ -void komodo_eventadd_pubkeys(komodo_state *sp, char *symbol, int32_t height, std::shared_ptr pk) +void komodo_eventadd_pubkeys(komodo_state *sp, const char *symbol, int32_t height, komodo::event_pubkeys& pk) { if (sp != nullptr) { sp->add_event(symbol, height, pk); - komodo_notarysinit(height, pk->pubkeys, pk->num); + komodo_notarysinit(height, pk.pubkeys, pk.num); } } /******** * Add a pricefeed event to the collection + * @note was for PAX, deprecated * @param sp where to add * @param symbol * @param height * @param pf the event */ -void komodo_eventadd_pricefeed( komodo_state *sp, char *symbol, int32_t height, std::shared_ptr pf) +void komodo_eventadd_pricefeed( komodo_state *sp, const char *symbol, int32_t height, komodo::event_pricefeed& pf) { if (sp != nullptr) { sp->add_event(symbol, height, pf); - komodo_pvals(height,pf->prices, pf->num); } } @@ -87,12 +100,15 @@ void komodo_eventadd_pricefeed( komodo_state *sp, char *symbol, int32_t height, * @param height * @param opret the event */ -void komodo_eventadd_opreturn( komodo_state *sp, char *symbol, int32_t height, std::shared_ptr opret) +void komodo_eventadd_opreturn( komodo_state *sp, const char *symbol, int32_t height, komodo::event_opreturn& opret) { - if ( sp != nullptr && ASSETCHAINS_SYMBOL[0] != 0) + if ( sp != nullptr && !chainName.isKMD() ) { sp->add_event(symbol, height, opret); - komodo_opreturn(height, opret->value, opret->opret.data(), opret->opret.size(), opret->txid, opret->vout, symbol); + if ( opret.opret.data()[0] == 'K' && opret.opret.size() != 40 ) + { + komodo_kvupdate(opret.opret.data(), opret.opret.size(), opret.value); + } } } @@ -102,34 +118,25 @@ void komodo_eventadd_opreturn( komodo_state *sp, char *symbol, int32_t height, s * @param sp the state object * @param ev the event to undo */ -void komodo_event_undo(komodo_state *sp, std::shared_ptr ev) +template +void komodo_event_undo(komodo_state *sp, T& ev) { - switch ( ev->type ) - { - case KOMODO_EVENT_RATIFY: - printf("rewind of ratify, needs to be coded.%d\n",ev->height); - break; - case KOMODO_EVENT_NOTARIZED: - break; - case KOMODO_EVENT_KMDHEIGHT: - if ( ev->height <= sp->SAVEDHEIGHT ) - sp->SAVEDHEIGHT = ev->height; - break; - case KOMODO_EVENT_PRICEFEED: - // backtrack prices; - break; - case KOMODO_EVENT_OPRETURN: - // backtrack opreturns - break; - } } +template<> +void komodo_event_undo(komodo_state* sp, komodo::event_kmdheight& ev) +{ + if ( ev.height <= sp->SAVEDHEIGHT ) + sp->SAVEDHEIGHT = ev.height; +} + + -void komodo_event_rewind(komodo_state *sp, char *symbol, int32_t height) +void komodo_event_rewind(komodo_state *sp, const char *symbol, int32_t height) { if ( sp != nullptr ) { - if ( ASSETCHAINS_SYMBOL[0] == 0 && height <= KOMODO_LASTMINED && prevKOMODO_LASTMINED != 0 ) + if ( chainName.isKMD() && height <= KOMODO_LASTMINED && prevKOMODO_LASTMINED != 0 ) { printf("undo KOMODO_LASTMINED %d <- %d\n",KOMODO_LASTMINED,prevKOMODO_LASTMINED); KOMODO_LASTMINED = prevKOMODO_LASTMINED; @@ -138,9 +145,9 @@ void komodo_event_rewind(komodo_state *sp, char *symbol, int32_t height) while ( sp->events.size() > 0) { auto ev = sp->events.back(); - if (ev-> height < height) + if (ev->height < height) break; - komodo_event_undo(sp, ev); + komodo_event_undo(sp, *ev); sp->events.pop_back(); } } @@ -167,19 +174,20 @@ void komodo_setkmdheight(struct komodo_state *sp,int32_t kmdheight,uint32_t time * @param height * @param kmdht the event */ -void komodo_eventadd_kmdheight(struct komodo_state *sp,char *symbol,int32_t height, std::shared_ptr kmdht) +void komodo_eventadd_kmdheight(struct komodo_state *sp, const char *symbol,int32_t height, + komodo::event_kmdheight& kmdht) { if (sp != nullptr) { - if ( kmdht->kheight > 0 ) // height is advancing + if ( kmdht.kheight > 0 ) // height is advancing { sp->add_event(symbol, height, kmdht); - komodo_setkmdheight(sp, kmdht->kheight, kmdht->timestamp); + komodo_setkmdheight(sp, kmdht.kheight, kmdht.timestamp); } else // rewinding { - std::shared_ptr e = std::make_shared(height); + komodo::event_rewind e(height); sp->add_event(symbol, height, e); komodo_event_rewind(sp,symbol,height); } diff --git a/src/komodo_events.h b/src/komodo_events.h index 31cd2407dfc..c17dc31b21a 100644 --- a/src/komodo_events.h +++ b/src/komodo_events.h @@ -16,18 +16,16 @@ #include "komodo_defs.h" #include "komodo_structs.h" -void komodo_eventadd_notarized(komodo_state *sp,char *symbol,int32_t height, std::shared_ptr ntz); +void komodo_eventadd_notarized(komodo_state *sp, const char *symbol,int32_t height, komodo::event_notarized& ntz); -void komodo_eventadd_pubkeys(komodo_state *sp,char *symbol,int32_t height, std::shared_ptr pk); +void komodo_eventadd_pubkeys(komodo_state *sp, const char *symbol,int32_t height, komodo::event_pubkeys& pk); -void komodo_eventadd_pricefeed(komodo_state *sp,char *symbol,int32_t height, std::shared_ptr pf); +void komodo_eventadd_pricefeed(komodo_state *sp, const char *symbol,int32_t height, komodo::event_pricefeed& pf); -void komodo_eventadd_opreturn(komodo_state *sp,char *symbol,int32_t height, std::shared_ptr opret); +void komodo_eventadd_opreturn(komodo_state *sp, const char *symbol,int32_t height, komodo::event_opreturn& opret); -void komodo_eventadd_kmdheight(komodo_state *sp,char *symbol,int32_t height,std::shared_ptr kmd_ht); +void komodo_eventadd_kmdheight(komodo_state *sp, const char *symbol,int32_t height, komodo::event_kmdheight& kmd_ht); -void komodo_event_undo(komodo_state *sp, std::shared_ptr ep); - -void komodo_event_rewind(komodo_state *sp,char *symbol,int32_t height); +void komodo_event_rewind(komodo_state *sp, const char *symbol,int32_t height); void komodo_setkmdheight(komodo_state *sp,int32_t kmdheight,uint32_t timestamp); diff --git a/src/komodo_extern_globals.h b/src/komodo_extern_globals.h index 37d9777d5af..401d633ed9e 100644 --- a/src/komodo_extern_globals.h +++ b/src/komodo_extern_globals.h @@ -17,7 +17,7 @@ * This file provides extern access to variables in komodo_globals.h * Please think twice before adding to this list. Can it be done with a better scope? */ -#include "komodo_structs.h" +#include "komodo_defs.h" #include #include @@ -25,7 +25,6 @@ extern bool IS_KOMODO_NOTARY; extern bool IS_KOMODO_DEALERNODE; extern char KMDUSERPASS[8192+512+1]; extern char BTCUSERPASS[8192]; -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; extern char ASSETCHAINS_USERPASS[4096]; extern uint8_t NOTARY_PUBKEY33[33]; extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33]; @@ -45,16 +44,12 @@ extern int32_t KOMODO_LASTMINED; extern int32_t prevKOMODO_LASTMINED; extern int32_t KOMODO_CCACTIVATE; extern int32_t JUMBLR_PAUSE; -extern int32_t NUM_PRICES; extern int32_t KOMODO_MININGTHREADS; extern int32_t STAKED_NOTARY_ID; extern int32_t USE_EXTERNAL_PUBKEY; -extern int32_t ASSETCHAINS_SEED; +//extern int32_t ASSETCHAINS_SEED; extern int32_t KOMODO_ON_DEMAND; extern int32_t KOMODO_EXTERNAL_NOTARIES; -extern int32_t KOMODO_PASSPORT_INITDONE; -extern int32_t KOMODO_EXTERNAL_NOTARIES; -extern int32_t KOMODO_PAX; extern int32_t KOMODO_REWIND; extern int32_t STAKED_ERA; extern int32_t KOMODO_CONNECTING; @@ -62,15 +57,14 @@ extern int32_t KOMODO_EXTRASATOSHI; extern int32_t ASSETCHAINS_FOUNDERS; extern int32_t ASSETCHAINS_CBMATURITY; extern int32_t KOMODO_NSPV; -extern int32_t KOMODO_LOADINGBLOCKS; // not actually in komodo_globals.h, but used in several places -extern uint32_t *PVALS; +extern bool KOMODO_LOADINGBLOCKS; extern uint32_t ASSETCHAINS_CC; extern uint32_t KOMODO_STOPAT; extern uint32_t KOMODO_DPOWCONFS; extern uint32_t STAKING_MIN_DIFF; extern uint32_t ASSETCHAIN_INIT; extern uint32_t ASSETCHAINS_NUMALGOS; -extern uint32_t ASSETCHAINS_MINDIFF[3]; +extern uint32_t ASSETCHAINS_MINDIFF[]; extern uint64_t PENDING_KOMODO_TX; extern uint64_t ASSETCHAINS_TIMELOCKGTE; extern uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS+1]; @@ -78,19 +72,18 @@ extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS+1]; extern uint64_t ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS+1]; extern uint64_t ASSETCHAINS_DECAY[ASSETCHAINS_MAX_ERAS+1]; extern uint64_t ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS+1]; -extern uint64_t ASSETCHAINS_PEGSCCPARAMS[3]; extern uint64_t ASSETCHAINS_TIMEUNLOCKFROM; extern uint64_t ASSETCHAINS_TIMEUNLOCKTO; -extern uint64_t ASSETCHAINS_CBOPRET; extern std::mutex komodo_mutex; -extern std::vector Mineropret; -extern pthread_mutex_t KOMODO_KV_mutex; extern pthread_mutex_t KOMODO_CC_mutex; -extern komodo_kv *KOMODO_KV; -extern pax_transaction *PAX; -extern knotaries_entry *Pubkeys; -extern komodo_state KOMODO_STATES[34]; -int32_t komodo_baseid(char *origbase); +/** + * @brief Given a currency name, return the index in the KOMODO_STATES array + * + * @param origbase the currency name to look for + * @return the index in the array, or -1 + */ +int32_t komodo_baseid(const char *origbase); + uint64_t komodo_current_supply(uint32_t nHeight); diff --git a/src/komodo_gateway.cpp b/src/komodo_gateway.cpp index ac10a2716fe..6f374393085 100644 --- a/src/komodo_gateway.cpp +++ b/src/komodo_gateway.cpp @@ -13,610 +13,10 @@ * * ******************************************************************************/ #include "komodo.h" -#include "komodo_extern_globals.h" +#include "komodo_globals.h" #include "komodo_utils.h" // komodo_stateptrget #include "komodo_bitcoind.h" // komodo_checkcommission - -struct komodo_extremeprice -{ - uint256 blockhash; - uint32_t pricebits,timestamp; - int32_t height; - int16_t dir,ind; -} ExtremePrice; - -uint32_t PriceCache[KOMODO_LOCALPRICE_CACHESIZE][KOMODO_MAXPRICES];//4+sizeof(Cryptos)/sizeof(*Cryptos)+sizeof(Forex)/sizeof(*Forex)]; -int64_t PriceMult[KOMODO_MAXPRICES]; - -struct komodo_priceinfo -{ - FILE *fp; - char symbol[64]; -} PRICES[KOMODO_MAXPRICES]; - -const char *Cryptos[] = { "KMD", "ETH" }; // must be on binance (for now) -// "LTC", "BCHABC", "XMR", "IOTA", "ZEC", "WAVES", "LSK", "DCR", "RVN", "DASH", "XEM", "BTS", "ICX", "HOT", "STEEM", "ENJ", "STRAT" -const char *Forex[] = -{ "BGN","NZD","ILS","RUB","CAD","PHP","CHF","AUD","JPY","TRY","HKD","MYR","HRK","CZK","IDR","DKK","NOK","HUF","GBP","MXN","THB","ISK","ZAR","BRL","SGD","PLN","INR","KRW","RON","CNY","SEK","EUR" -}; // must be in ECB list - -int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base) -{ - int32_t baseid; struct komodo_state *sp; int64_t netliability,maxallowed,maxval; - *available = *deposited = *issued = *withdrawn = *approved = *redeemed = 0; - if ( (baseid= komodo_baseid(base)) >= 0 ) - { - if ( (sp= komodo_stateptrget(base)) != 0 ) - { - *deposited = sp->deposited; - *issued = sp->issued; - *withdrawn = sp->withdrawn; - *approved = sp->approved; - *redeemed = sp->redeemed; - maxval = sp->approved; - if ( sp->withdrawn > maxval ) - maxval = sp->withdrawn; - netliability = (sp->issued - maxval) - sp->shorted; - maxallowed = komodo_maxallowed(baseid); - if ( netliability < maxallowed ) - *available = (maxallowed - netliability); - //printf("%llu - %llu %s %.8f %.8f %.8f %.8f %.8f\n",(long long)maxallowed,(long long)netliability,base,dstr(*deposited),dstr(*issued),dstr(*withdrawn),dstr(*approved),dstr(*redeemed)); - return(0); - } else printf("pax_fiatstatus cant get basesp.%s\n",base); - } // else printf("pax_fiatstatus illegal base.%s\n",base); - return(-1); -} - -void pax_keyset(uint8_t *buf,uint256 txid,uint16_t vout,uint8_t type) -{ - memcpy(buf,&txid,32); - memcpy(&buf[32],&vout,2); - buf[34] = type; -} - -struct pax_transaction *komodo_paxfind(uint256 txid,uint16_t vout,uint8_t type) -{ - struct pax_transaction *pax; uint8_t buf[35]; - std::lock_guard lock(komodo_mutex); - pax_keyset(buf,txid,vout,type); - HASH_FIND(hh,PAX,buf,sizeof(buf),pax); - return(pax); -} - -struct pax_transaction *komodo_paxfinds(uint256 txid,uint16_t vout) -{ - struct pax_transaction *pax; int32_t i; uint8_t types[] = { 'I', 'D', 'X', 'A', 'W' }; - for (i=0; i lock(komodo_mutex); - pax_keyset(buf,txid,vout,type); - HASH_FIND(hh,PAX,buf,sizeof(buf),pax); - if ( pax == 0 ) - { - pax = (struct pax_transaction *)calloc(1,sizeof(*pax)); - pax->txid = txid; - pax->vout = vout; - pax->type = type; - memcpy(pax->buf,buf,sizeof(pax->buf)); - HASH_ADD_KEYPTR(hh,PAX,pax->buf,sizeof(pax->buf),pax); - //printf("ht.%d create pax.%p mark.%d\n",height,pax,mark); - } - if ( pax != 0 ) - { - pax->marked = mark; - //if ( height > 214700 || pax->height > 214700 ) - // printf("mark ht.%d %.8f %.8f\n",pax->height,dstr(pax->komodoshis),dstr(pax->fiatoshis)); - - } - return(pax); -} - -void komodo_paxdelete(struct pax_transaction *pax) -{ - return; // breaks when out of order - std::lock_guard lock(komodo_mutex); - HASH_DELETE(hh,PAX,pax); -} - -void komodo_gateway_deposit(char *coinaddr,uint64_t value,char *symbol,uint64_t fiatoshis,uint8_t *rmd160,uint256 txid,uint16_t vout,uint8_t type,int32_t height,int32_t otherheight,char *source,int32_t approved) // assetchain context -{ - struct pax_transaction *pax; uint8_t buf[35]; int32_t addflag = 0; struct komodo_state *sp; char str[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN],*s; - //if ( KOMODO_PAX == 0 ) - // return; - //if ( strcmp(symbol,ASSETCHAINS_SYMBOL) != 0 ) - // return; - sp = komodo_stateptr(str,dest); - { - std::lock_guard lock(komodo_mutex); - pax_keyset(buf,txid,vout,type); - HASH_FIND(hh,PAX,buf,sizeof(buf),pax); - if ( pax == 0 ) - { - pax = (struct pax_transaction *)calloc(1,sizeof(*pax)); - pax->txid = txid; - pax->vout = vout; - pax->type = type; - memcpy(pax->buf,buf,sizeof(pax->buf)); - HASH_ADD_KEYPTR(hh,PAX,pax->buf,sizeof(pax->buf),pax); - addflag = 1; - if ( 0 && ASSETCHAINS_SYMBOL[0] == 0 ) - { - int32_t i; for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&txid)[i]); - printf(" v.%d [%s] kht.%d ht.%d create pax.%p symbol.%s source.%s\n",vout,ASSETCHAINS_SYMBOL,height,otherheight,pax,symbol,source); - } - } - } - if ( coinaddr != 0 ) - { - strcpy(pax->coinaddr,coinaddr); - if ( value != 0 ) - pax->komodoshis = value; - if ( symbol != 0 ) - strcpy(pax->symbol,symbol); - if ( source != 0 ) - strcpy(pax->source,source); - if ( fiatoshis != 0 ) - pax->fiatoshis = fiatoshis; - if ( rmd160 != 0 ) - memcpy(pax->rmd160,rmd160,20); - if ( height != 0 ) - pax->height = height; - if ( otherheight != 0 ) - pax->otherheight = otherheight; - } - else - { - pax->marked = height; - //printf("pax.%p MARK DEPOSIT ht.%d other.%d\n",pax,height,otherheight); - } -} - -int32_t komodo_rwapproval(int32_t rwflag,uint8_t *opretbuf,struct pax_transaction *pax) -{ - int32_t i,len = 0; - if ( rwflag == 1 ) - { - for (i=0; i<32; i++) - opretbuf[len++] = ((uint8_t *)&pax->txid)[i]; - opretbuf[len++] = pax->vout & 0xff; - opretbuf[len++] = (pax->vout >> 8) & 0xff; - } - else - { - for (i=0; i<32; i++) - ((uint8_t *)&pax->txid)[i] = opretbuf[len++]; - //for (i=0; i<32; i++) - // printf("%02x",((uint8_t *)&pax->txid)[31-i]); - pax->vout = opretbuf[len++]; - pax->vout += ((uint32_t)opretbuf[len++] << 8); - //printf(" txid v.%d\n",pax->vout); - } - len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->komodoshis),&pax->komodoshis); - len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->fiatoshis),&pax->fiatoshis); - len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->height),&pax->height); - len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->otherheight),&pax->otherheight); - if ( rwflag != 0 ) - { - memcpy(&opretbuf[len],pax->rmd160,20), len += 20; - for (i=0; i<4; i++) - opretbuf[len++] = pax->source[i]; - } - else - { - memcpy(pax->rmd160,&opretbuf[len],20), len += 20; - for (i=0; i<4; i++) - pax->source[i] = opretbuf[len++]; - } - return(len); -} - -int32_t komodo_issued_opreturn(char *base,uint256 *txids,uint16_t *vouts,int64_t *values,int64_t *srcvalues,int32_t *kmdheights,int32_t *otherheights,int8_t *baseids,uint8_t *rmd160s,uint8_t *opretbuf,int32_t opretlen,int32_t iskomodo) -{ - struct pax_transaction p,*pax; int32_t i,n=0,j,len=0,incr,height,otherheight; uint8_t type,rmd160[20]; uint64_t fiatoshis; char symbol[KOMODO_ASSETCHAIN_MAXLEN]; - //if ( KOMODO_PAX == 0 ) - // return(0); - incr = 34 + (iskomodo * (2*sizeof(fiatoshis) + 2*sizeof(height) + 20 + 4)); - //41e77b91cb68dc2aa02fa88550eae6b6d44db676a7e935337b6d1392d9718f03cb0200305c90660400000000fbcbeb1f000000bde801006201000058e7945ad08ddba1eac9c9b6c8e1e97e8016a2d152 - - // 41e94d736ec69d88c08b5d238abeeca609c02357a8317e0d56c328bcb1c259be5d0200485bc80200000000404b4c000000000059470200b80b000061f22ba7d19fe29ac3baebd839af8b7127d1f9075553440046bb4cc7a3b5cd39dffe7206507a3482a00780e617f68b273cce9817ed69298d02001069ca1b0000000080f0fa02000000005b470200b90b000061f22ba7d19fe29ac3baebd839af8b7127d1f90755 - - //for (i=0; i>>>>>> %s: (%s) fiat %.8f kmdheight.%d other.%d -> %s %.8f\n",type=='A'?"approvedA":"issuedX",baseids[n]>=0?CURRENCIES[baseids[n]]:"???",dstr(p.fiatoshis),kmdheights[n],otherheights[n],coinaddr,dstr(values[n])); - } - } - } - else - { - for (i=0; i<4; i++) - base[i] = opretbuf[opretlen-4+i]; - for (j=0; j<32; j++) - { - ((uint8_t *)&txids[n])[j] = opretbuf[len++]; - //printf("%02x",((uint8_t *)&txids[n])[j]); - } - vouts[n] = opretbuf[len++]; - vouts[n] = (opretbuf[len++] << 8) | vouts[n]; - baseids[n] = komodo_baseid(base); - if ( (pax= komodo_paxfinds(txids[n],vouts[n])) != 0 ) - { - values[n] = (strcmp("KMD",base) == 0) ? pax->komodoshis : pax->fiatoshis; - srcvalues[n] = (strcmp("KMD",base) == 0) ? pax->fiatoshis : pax->komodoshis; - kmdheights[n] = pax->height; - otherheights[n] = pax->otherheight; - memcpy(&rmd160s[n * 20],pax->rmd160,20); - } - } - //printf(" komodo_issued_opreturn issuedtxid v%d i.%d opretlen.%d\n",vouts[n],n,opretlen); - } - } - return(n); -} - -int32_t komodo_paxcmp(char *symbol,int32_t kmdheight,uint64_t value,uint64_t checkvalue,uint64_t seed) -{ - int32_t ratio; - if ( seed == 0 && checkvalue != 0 ) - { - ratio = ((value << 6) / checkvalue); - if ( ratio >= 60 && ratio <= 67 ) - return(0); - else - { - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - printf("ht.%d ignore mismatched %s value %lld vs checkvalue %lld -> ratio.%d\n",kmdheight,symbol,(long long)value,(long long)checkvalue,ratio); - return(-1); - } - } - else if ( checkvalue != 0 ) - { - ratio = ((value << 10) / checkvalue); - if ( ratio >= 1023 && ratio <= 1025 ) - return(0); - } - return(value != checkvalue); -} - -uint64_t komodo_paxtotal() -{ - struct pax_transaction *pax,*pax2,*tmp,*tmp2; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN],*str; int32_t i,ht; int64_t checktoshis; uint64_t seed,total = 0; struct komodo_state *basesp; - if ( KOMODO_PASSPORT_INITDONE == 0 ) //KOMODO_PAX == 0 || - return(0); - if ( komodo_isrealtime(&ht) == 0 ) - return(0); - else - { - HASH_ITER(hh,PAX,pax,tmp) - { - if ( pax->marked != 0 ) - continue; - if ( pax->type == 'A' || pax->type == 'D' || pax->type == 'X' ) - str = pax->symbol; - else str = pax->source; - basesp = komodo_stateptrget(str); - if ( basesp != 0 && pax->didstats == 0 ) - { - if ( pax->type == 'I' && (pax2= komodo_paxfind(pax->txid,pax->vout,'D')) != 0 ) - { - if ( pax2->fiatoshis != 0 ) - { - pax->komodoshis = pax2->komodoshis; - pax->fiatoshis = pax2->fiatoshis; - basesp->issued += pax->fiatoshis; - pax->didstats = 1; - if ( strcmp(str,ASSETCHAINS_SYMBOL) == 0 ) - printf("########### %p issued %s += %.8f kmdheight.%d %.8f other.%d\n",basesp,str,dstr(pax->fiatoshis),pax->height,dstr(pax->komodoshis),pax->otherheight); - pax2->marked = pax->height; - pax->marked = pax->height; - } - } - else if ( pax->type == 'W' ) - { - //bitcoin_address(coinaddr,addrtype,rmd160,20); - if ( (checktoshis= komodo_paxprice(&seed,pax->height,pax->source,(char *)"KMD",(uint64_t)pax->fiatoshis)) != 0 ) - { - if ( komodo_paxcmp(pax->source,pax->height,pax->komodoshis,checktoshis,seed) != 0 ) - { - pax->marked = pax->height; - //printf("WITHDRAW.%s mark <- %d %.8f != %.8f\n",pax->source,pax->height,dstr(checktoshis),dstr(pax->komodoshis)); - } - else if ( pax->validated == 0 ) - { - pax->validated = pax->komodoshis = checktoshis; - //int32_t j; for (j=0; j<32; j++) - // printf("%02x",((uint8_t *)&pax->txid)[j]); - //if ( strcmp(str,ASSETCHAINS_SYMBOL) == 0 ) - // printf(" v%d %p got WITHDRAW.%s kmd.%d ht.%d %.8f -> %.8f/%.8f\n",pax->vout,pax,pax->source,pax->height,pax->otherheight,dstr(pax->fiatoshis),dstr(pax->komodoshis),dstr(checktoshis)); - } - } - } - } - } - } - komodo_stateptr(symbol,dest); - HASH_ITER(hh,PAX,pax,tmp) - { - pax->ready = 0; - if ( 0 && pax->type == 'A' ) - printf("%p pax.%s <- %s marked.%d %.8f -> %.8f validated.%d approved.%d\n",pax,pax->symbol,pax->source,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->validated != 0,pax->approved != 0); - if ( pax->marked != 0 ) - continue; - if ( strcmp(symbol,pax->symbol) == 0 || pax->type == 'A' ) - { - if ( pax->marked == 0 ) - { - if ( komodo_is_issuer() != 0 ) - { - if ( pax->validated != 0 && pax->type == 'D' ) - { - total += pax->fiatoshis; - pax->ready = 1; - } - } - else if ( pax->approved != 0 && pax->type == 'A' ) - { - if ( pax->validated != 0 ) - { - total += pax->komodoshis; - pax->ready = 1; - } - else - { - seed = 0; - checktoshis = komodo_paxprice(&seed,pax->height,pax->source,(char *)"KMD",(uint64_t)pax->fiatoshis); - //printf("paxtotal PAX_fiatdest ht.%d price %s %.8f -> KMD %.8f vs %.8f\n",pax->height,pax->symbol,(double)pax->fiatoshis/COIN,(double)pax->komodoshis/COIN,(double)checktoshis/COIN); - //printf(" v%d %.8f k.%d ht.%d\n",pax->vout,dstr(pax->komodoshis),pax->height,pax->otherheight); - if ( seed != 0 && checktoshis != 0 ) - { - if ( checktoshis == pax->komodoshis ) - { - total += pax->komodoshis; - pax->validated = pax->komodoshis; - pax->ready = 1; - } else pax->marked = pax->height; - } - } - } - if ( 0 && pax->ready != 0 ) - printf("%p (%c) pax.%s marked.%d %.8f -> %.8f validated.%d approved.%d ready.%d ht.%d\n",pax,pax->type,pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->validated != 0,pax->approved != 0,pax->ready,pax->height); - } - } - } - //printf("paxtotal %.8f\n",dstr(total)); - return(total); -} - -int32_t komodo_pending_withdraws(char *opretstr) // todo: enforce deterministic order -{ - struct pax_transaction *pax,*pax2,*tmp,*paxes[64]; uint8_t opretbuf[16384*4]; int32_t i,n,ht,len=0; uint64_t total = 0; - if ( KOMODO_PAX == 0 || KOMODO_PASSPORT_INITDONE == 0 ) - return(0); - if ( komodo_isrealtime(&ht) == 0 || ASSETCHAINS_SYMBOL[0] != 0 ) - return(0); - n = 0; - HASH_ITER(hh,PAX,pax,tmp) - { - if ( pax->type == 'W' ) - { - if ( (pax2= komodo_paxfind(pax->txid,pax->vout,'A')) != 0 ) - { - if ( pax2->approved != 0 ) - pax->approved = pax2->approved; - } - else if ( (pax2= komodo_paxfind(pax->txid,pax->vout,'X')) != 0 ) - pax->approved = pax->height; - //printf("pending_withdraw: pax %s marked.%u approved.%u validated.%llu\n",pax->symbol,pax->marked,pax->approved,(long long)pax->validated); - if ( pax->marked == 0 && pax->approved == 0 && pax->validated != 0 ) //strcmp((char *)"KMD",pax->symbol) == 0 && - { - if ( n < sizeof(paxes)/sizeof(*paxes) ) - { - paxes[n++] = pax; - //int32_t j; for (j=0; j<32; j++) - // printf("%02x",((uint8_t *)&pax->txid)[j]); - //printf(" %s.(kmdht.%d ht.%d marked.%u approved.%d validated %.8f) %.8f\n",pax->source,pax->height,pax->otherheight,pax->marked,pax->approved,dstr(pax->validated),dstr(pax->komodoshis)); - } - } - } - } - opretstr[0] = 0; - if ( n > 0 ) - { - opretbuf[len++] = 'A'; - qsort(paxes,n,sizeof(*paxes),_paxorder); - for (i=0; i>3)*7 ) - len += komodo_rwapproval(1,&opretbuf[len],paxes[i]); - } - if ( len > 0 ) - init_hexbytes_noT(opretstr,opretbuf,len); - } - //fprintf(stderr,"komodo_pending_withdraws len.%d PAXTOTAL %.8f\n",len,dstr(komodo_paxtotal())); - return(len); -} - -int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *base,int32_t tokomodo) -{ - struct pax_transaction *pax,*tmp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; uint8_t *script,opcode,opret[16384*4],data[16384*4]; int32_t i,baseid,ht,len=0,opretlen=0,numvouts=1; struct komodo_state *sp; uint64_t available,deposited,issued,withdrawn,approved,redeemed,mask,sum = 0; - if ( KOMODO_PASSPORT_INITDONE == 0 )//KOMODO_PAX == 0 || - return(0); - struct komodo_state *kmdsp = komodo_stateptrget((char *)"KMD"); - sp = komodo_stateptr(symbol,dest); - strcpy(symbol,base); - if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) < 0 ) - return(0); - PENDING_KOMODO_TX = 0; - for (i=0; i<3; i++) - { - if ( komodo_isrealtime(&ht) != 0 ) - break; - sleep(1); - } - if ( i == 3 ) - { - if ( tokomodo == 0 ) - printf("%s not realtime ht.%d\n",ASSETCHAINS_SYMBOL,ht); - return(0); - } - if ( tokomodo == 0 ) - { - opcode = 'I'; - } - else - { - opcode = 'X'; - if ( 1 || komodo_paxtotal() == 0 ) - return(0); - } - HASH_ITER(hh,PAX,pax,tmp) - { - if ( pax->type != 'D' && pax->type != 'A' ) - continue; - { -#ifdef KOMODO_ASSETCHAINS_WAITNOTARIZE - if ( pax->height > 236000 ) - { - if ( kmdsp != 0 && kmdsp->LastNotarizedHeight() >= pax->height ) - pax->validated = pax->komodoshis; - else if ( kmdsp->CURRENT_HEIGHT > pax->height+30 ) - pax->validated = pax->ready = 0; - } - else - { - if ( kmdsp != 0 && (kmdsp->LastNotarizedHeight() >= pax->height || kmdsp->CURRENT_HEIGHT > pax->height+30) ) // assumes same chain as notarize - pax->validated = pax->komodoshis; - else pax->validated = pax->ready = 0; - } -#else - pax->validated = pax->komodoshis; -#endif - } - if ( ASSETCHAINS_SYMBOL[0] != 0 && (pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,symbol) != 0 || available < pax->fiatoshis) ) - { - //if ( pax->height > 214700 || strcmp(ASSETCHAINS_SYMBOL,symbol) == 0 ) - // printf("miner.[%s]: skip %s %.8f when avail %.8f deposited %.8f, issued %.8f withdrawn %.8f approved %.8f redeemed %.8f\n",ASSETCHAINS_SYMBOL,symbol,dstr(pax->fiatoshis),dstr(available),dstr(deposited),dstr(issued),dstr(withdrawn),dstr(approved),dstr(redeemed)); - continue; - } - /*printf("pax.%s marked.%d %.8f -> %.8f ready.%d validated.%d\n",pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->ready!=0,pax->validated!=0); - if ( pax->marked != 0 || (pax->type != 'D' && pax->type != 'A') || pax->ready == 0 ) - { - printf("reject 2\n"); - continue; - }*/ - if ( ASSETCHAINS_SYMBOL[0] != 0 && (strcmp(pax->symbol,symbol) != 0 || pax->validated == 0 || pax->ready == 0) ) - { - if ( strcmp(pax->symbol,ASSETCHAINS_SYMBOL) == 0 ) - printf("pax->symbol.%s != %s or null pax->validated %.8f ready.%d ht.(%d %d)\n",pax->symbol,symbol,dstr(pax->validated),pax->ready,kmdsp->CURRENT_HEIGHT,pax->height); - pax->marked = pax->height; - continue; - } - if ( pax->ready == 0 ) - continue; - if ( pax->type == 'A' && ASSETCHAINS_SYMBOL[0] == 0 ) - { - if ( kmdsp != 0 ) - { - if ( (baseid= komodo_baseid(pax->symbol)) < 0 || ((1LL << baseid) & sp->RTmask) == 0 ) - { - printf("not RT for (%s) %llx baseid.%d %llx\n",pax->symbol,(long long)sp->RTmask,baseid,(long long)(1LL< %.8f ready.%d validated.%d approved.%d\n",tokomodo,pax->type,pax,pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->ready!=0,pax->validated!=0,pax->approved!=0); - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - printf("pax.%s marked.%d %.8f -> %.8f\n",ASSETCHAINS_SYMBOL,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis)); - if ( opcode == 'I' ) - { - sum += pax->fiatoshis; - if ( sum > available ) - break; - } - txNew->vout.resize(numvouts+1); - txNew->vout[numvouts].nValue = (opcode == 'I') ? pax->fiatoshis : pax->komodoshis; - txNew->vout[numvouts].scriptPubKey.resize(25); - script = (uint8_t *)&txNew->vout[numvouts].scriptPubKey[0]; - *script++ = 0x76; - *script++ = 0xa9; - *script++ = 20; - memcpy(script,pax->rmd160,20), script += 20; - *script++ = 0x88; - *script++ = 0xac; - if ( tokomodo == 0 ) - { - for (i=0; i<32; i++) - data[len++] = ((uint8_t *)&pax->txid)[i]; - data[len++] = pax->vout & 0xff; - data[len++] = (pax->vout >> 8) & 0xff; - PENDING_KOMODO_TX += pax->fiatoshis; - } - else - { - len += komodo_rwapproval(1,&data[len],pax); - PENDING_KOMODO_TX += pax->komodoshis; - printf(" len.%d vout.%u DEPOSIT %.8f <- pax.%s pending ht %d %d %.8f | ",len,pax->vout,(double)txNew->vout[numvouts].nValue/COIN,symbol,pax->height,pax->otherheight,dstr(PENDING_KOMODO_TX)); - } - if ( numvouts++ >= 64 || sum > COIN ) - break; - } - if ( numvouts > 1 ) - { - if ( tokomodo != 0 ) - strcpy(symbol,(char *)"KMD"); - for (i=0; symbol[i]!=0; i++) - data[len++] = symbol[i]; - data[len++] = 0; - for (i=0; ivout.resize(numvouts+1); - txNew->vout[numvouts].nValue = 0; - txNew->vout[numvouts].scriptPubKey.resize(opretlen); - script = (uint8_t *)&txNew->vout[numvouts].scriptPubKey[0]; - memcpy(script,opret,opretlen); - for (i=0; i<8; i++) - printf("%02x",opret[i]); - printf(" <- opret, MINER deposits.%d (%s) vouts.%d %.8f opretlen.%d\n",tokomodo,ASSETCHAINS_SYMBOL,numvouts,dstr(PENDING_KOMODO_TX),opretlen); - return(1); - } - return(0); -} +#include "komodo_notary.h" const char *banned_txids[] = { @@ -650,57 +50,71 @@ const char *banned_txids[] = //"ce567928b5490a17244167af161b1d8dd6ff753fef222fe6855d95b2278a35b3", // missed }; -int32_t komodo_checkvout(int32_t vout,int32_t k,int32_t indallvouts) +/**** + * @brief Check if the n of the vout matches one that is banned + * @param vout the "n" of the vout + * @param k the index in the array of banned txids + * @param indallvouts the index at which all "n"s are banned + * @returns true if vout is banned + */ +bool komodo_checkvout(int32_t vout,int32_t k,int32_t indallvouts) { - if ( k < indallvouts ) - return(vout == 1); - else if ( k == indallvouts || k == indallvouts+1 ) - return(1); - else return(vout == 0); + if ( k < indallvouts ) // most banned txids are vout 1 + return vout == 1; + else if ( k == indallvouts || k == indallvouts+1 ) // all vouts are banned for the last 2 txids + return true; + return vout == 0; // unsure when this might get executed - JMJ } +/**** + * @brief retrieve list of banned txids + * @param[out] indallvoutsp lowest index where all txid "n"s are banned, not just vout 1 + * @param[out] array of txids + * @param[in] max the max size of the array + * @returns the number of txids placed into the array + */ int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max) { - int32_t i; if ( sizeof(banned_txids)/sizeof(*banned_txids) > max ) { fprintf(stderr,"komodo_bannedset: buffer too small %d vs %d\n",(int32_t)(sizeof(banned_txids)/sizeof(*banned_txids)),max); StartShutdown(); } + int32_t i; for (i=0; i 1 && block.vtx[txn_count-1].vout.size() > 0 && block.vtx[txn_count-1].vout[0].nValue == 5000 ) + if ( i == 0 && txn_count > 1 && block.vtx[txn_count-1].vout.size() > 0 + && block.vtx[txn_count-1].vout[0].nValue == 5000 ) { - /* - if ( block.vtx[txn_count-1].vin.size() == 1 && GetTransaction(block.vtx[txn_count-1].vin[0].prevout.hash,tx,hash,false) && block.vtx[0].vout[0].scriptPubKey == tx.vout[block.vtx[txn_count-1].vin[0].prevout.n].scriptPubKey ) - notmatched = 1; - */ if ( block.vtx[txn_count-1].vin.size() == 1 ) { uint256 hashNotaryProofVin = block.vtx[txn_count-1].vin[0].prevout.hash; + CTransaction tx; + uint256 hash; int fNotaryProofVinTxFound = GetTransaction(hashNotaryProofVin,tx,hash,false); if (!fNotaryProofVinTxFound) { // try to search in the same block @@ -713,18 +127,20 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim } } } - if ( fNotaryProofVinTxFound && block.vtx[0].vout[0].scriptPubKey == tx.vout[block.vtx[txn_count-1].vin[0].prevout.n].scriptPubKey ) - { - notmatched = 1; - } + if ( fNotaryProofVinTxFound + && block.vtx[0].vout[0].scriptPubKey == tx.vout[block.vtx[txn_count-1].vin[0].prevout.n].scriptPubKey ) + { + notmatched = 1; + } } } - n = block.vtx[i].vin.size(); - for (j=0; j= indallvouts) ) + if ( block.vtx[i].vin[j].prevout.hash == array[k] + && komodo_checkvout(block.vtx[i].vin[j].prevout.n,k,indallvouts) ) { printf("banned tx.%d being used at ht.%d txi.%d vini.%d\n",k,height,i,j); return(-1); @@ -734,16 +150,16 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim } } // we don't want these checks in VRSC, leave it at the Sapling upgrade - if ( ASSETCHAINS_SYMBOL[0] == 0 || + if ( chainName.isKMD() || ((ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD) && height > 1) || NetworkUpgradeActive(height, Params().GetConsensus(), Consensus::UPGRADE_SAPLING) ) { - n = block.vtx[0].vout.size(); + int32_t n = block.vtx[0].vout.size(); int64_t val,prevtotal = 0; int32_t strangeout=0,overflow = 0; - total = 0; - for (i=1; i= MAX_MONEY ) { overflow = 1; @@ -759,7 +175,7 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim } prevtotal = total; } - if ( ASSETCHAINS_SYMBOL[0] == 0 ) + if ( chainName.isKMD() ) { if ( overflow != 0 || total > COIN/10 ) { @@ -785,18 +201,14 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim } else if ( height > 814000 ) { - script = (uint8_t *)&block.vtx[0].vout[0].scriptPubKey[0]; - //int32_t notary = komodo_electednotary(&num,script+1,height,0); - //if ( (-1 * (komodo_electednotary(&num,script+1,height,0) >= 0) * (height > 1000000)) < 0 ) - // fprintf(stderr, ">>>>>>> FAILED BLOCK.%d notary.%d insync.%d\n",height,notary,KOMODO_INSYNC); - //else - // fprintf(stderr, "<<<<<<< VALID BLOCK.%d notary.%d insync.%d\n",height,notary,KOMODO_INSYNC); + uint8_t *script = (uint8_t *)&block.vtx[0].vout[0].scriptPubKey[0]; + int32_t num; return(-1 * (komodo_electednotary(&num,script+1,height,0) >= 0) * (height > 1000000)); } } else { - checktoshis = 0; + int64_t checktoshis = 0; if ( (ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD) && height > 1 ) { if ( (checktoshis= komodo_checkcommission((CBlock *)&block,height)) < 0 ) @@ -815,7 +227,7 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim { fprintf(stderr,"checkdeposit: ht.%d checktoshis %.8f overflow.%d total %.8f strangeout.%d\n",height,dstr(checktoshis),overflow,dstr(total),strangeout); if ( strangeout != 0 ) - fprintf(stderr,">>>>>>>>>>>>> %s DUST ht.%d strangeout.%d notmatched.%d <<<<<<<<<\n",ASSETCHAINS_SYMBOL,height,strangeout,notmatched); + fprintf(stderr,">>>>>>>>>>>>> %s DUST ht.%d strangeout.%d notmatched.%d <<<<<<<<<\n",chainName.symbol().c_str(),height,strangeout,notmatched); return(-1); } } @@ -823,384 +235,57 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim return(0); } -const char *komodo_opreturn(int32_t height,uint64_t value,uint8_t *opretbuf,int32_t opretlen,uint256 txid,uint16_t vout,char *source) +void komodo_stateind_set(struct komodo_state *sp,uint32_t *inds,int32_t n,uint8_t *filedata,long datalen,const char *symbol,const char *dest) { - uint8_t rmd160[20],rmd160s[64*20],addrtype,shortflag,pubkey33[33]; int32_t didstats,i,j,n,kvheight,len,tokomodo,kmdheight,otherheights[64],kmdheights[64]; int8_t baseids[64]; char base[4],coinaddr[64],destaddr[64]; uint256 txids[64]; uint16_t vouts[64]; uint64_t convtoshis,seed; int64_t fee,fiatoshis,komodoshis,checktoshis,values[64],srcvalues[64]; struct pax_transaction *pax,*pax2; struct komodo_state *basesp; double diff; - const char *typestr = "unknown"; - if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) < 0 && opretbuf[0] != 'K' ) - { - //printf("komodo_opreturn skip %s\n",ASSETCHAINS_SYMBOL); - return("assetchain"); - } - memset(baseids,0xff,sizeof(baseids)); - memset(values,0,sizeof(values)); - memset(srcvalues,0,sizeof(srcvalues)); - memset(rmd160s,0,sizeof(rmd160s)); - memset(kmdheights,0,sizeof(kmdheights)); - memset(otherheights,0,sizeof(otherheights)); - tokomodo = (komodo_is_issuer() == 0); - if ( opretbuf[0] == 'K' && opretlen != 40 ) - { - komodo_kvupdate(opretbuf,opretlen,value); - return("kv"); - } - else if ( ASSETCHAINS_SYMBOL[0] == 0 && KOMODO_PAX == 0 ) - return("nopax"); - if ( opretbuf[0] == 'D' ) + uint8_t func; long lastK,lastT,lastN,lastV,fpos,lastfpos; int32_t i,count,doissue,iter,numn,numv,numN,numV,numR; uint32_t tmp,prevpos100,offset; + count = numR = numN = numV = numn = numv = 0; + lastK = lastT = lastN = lastV = -1; + for (iter=0; iter<2; iter++) { - tokomodo = 0; - if ( opretlen == 38 ) // any KMD tx + for (lastfpos=fpos=prevpos100=i=0; i 195000 || kmdheight <= height) ) + tmp = inds[i]; + if ( (i % 100) == 0 ) + prevpos100 = tmp; + else { - didstats = 0; - if ( komodo_paxcmp(base,kmdheight,value,checktoshis,kmdheight < 225000 ? seed : 0) == 0 ) + func = (tmp & 0xff); + offset = (tmp >> 8); + fpos = prevpos100 + offset; + if ( lastfpos >= datalen || (filedata[lastfpos] != func && func != 0) ) + printf("i.%d/n.%d lastfpos.%ld >= datalen.%ld or [%d] != func.%d\n",i,n,lastfpos,datalen,filedata[lastfpos],func); + else if ( iter == 0 ) { - if ( (pax= komodo_paxfind(txid,vout,'D')) == 0 ) - { - if ( (basesp= komodo_stateptrget(base)) != 0 ) - { - basesp->deposited += fiatoshis; - didstats = 1; - if ( 0 && strcmp(base,ASSETCHAINS_SYMBOL) == 0 ) - printf("########### %p deposited %s += %.8f kmdheight.%d %.8f\n",basesp,base,dstr(fiatoshis),kmdheight,dstr(value)); - } else printf("cant get stateptr.(%s)\n",base); - komodo_gateway_deposit(coinaddr,value,base,fiatoshis,rmd160,txid,vout,'D',kmdheight,height,(char *)"KMD",0); - } - if ( (pax= komodo_paxfind(txid,vout,'D')) != 0 ) + switch ( func ) { - pax->height = kmdheight; - pax->validated = value; - pax->komodoshis = value; - pax->fiatoshis = fiatoshis; - if ( didstats == 0 && pax->didstats == 0 ) - { - if ( (basesp= komodo_stateptrget(base)) != 0 ) - { - basesp->deposited += fiatoshis; - didstats = 1; - if ( 0 && strcmp(base,ASSETCHAINS_SYMBOL) == 0 ) - printf("########### %p depositedB %s += %.8f/%.8f kmdheight.%d/%d %.8f/%.8f\n",basesp,base,dstr(fiatoshis),dstr(pax->fiatoshis),kmdheight,pax->height,dstr(value),dstr(pax->komodoshis)); - } - } // - if ( didstats != 0 ) - pax->didstats = 1; - if ( (pax2= komodo_paxfind(txid,vout,'I')) != 0 ) - { - pax2->fiatoshis = pax->fiatoshis; - pax2->komodoshis = pax->komodoshis; - pax->marked = pax2->marked = pax->height; - pax2->height = pax->height = height; - if ( pax2->didstats == 0 ) - { - if ( (basesp= komodo_stateptrget(base)) != 0 ) - { - basesp->issued += pax2->fiatoshis; - pax2->didstats = 1; - if ( 0 && strcmp(base,"USD") == 0 ) - printf("########### %p issueda %s += %.8f kmdheight.%d %.8f other.%d [%d]\n",basesp,base,dstr(pax2->fiatoshis),pax2->height,dstr(pax2->komodoshis),pax2->otherheight,height); - } - } - } + default: case 'P': case 'U': case 'D': + inds[i] &= 0xffffff00; + break; + case 'K': + lastK = lastfpos; + inds[i] &= 0xffffff00; + break; + case 'T': + lastT = lastfpos; + inds[i] &= 0xffffff00; + break; + case 'N': + lastN = lastfpos; + numN++; + break; + case 'V': + lastV = lastfpos; + numV++; + break; + case 'R': + numR++; + break; } } else { - if ( (pax= komodo_paxfind(txid,vout,'D')) != 0 ) - pax->marked = checktoshis; - if ( kmdheight > 238000 && (kmdheight > 214700 || strcmp(base,ASSETCHAINS_SYMBOL) == 0) ) //seed != 0 && - printf("pax %s deposit %.8f rejected kmdheight.%d %.8f KMD check %.8f seed.%llu\n",base,dstr(fiatoshis),kmdheight,dstr(value),dstr(checktoshis),(long long)seed); - } - } //else printf("[%s] %s paxdeposit height.%d vs kmdheight.%d\n",ASSETCHAINS_SYMBOL,base,height,kmdheight); - } //else printf("unsupported size.%d for opreturn D\n",opretlen); - } - else if ( opretbuf[0] == 'I' ) - { - tokomodo = 0; - if ( strncmp((char *)"KMD",(char *)&opretbuf[opretlen-4],3) != 0 && strncmp(ASSETCHAINS_SYMBOL,(char *)&opretbuf[opretlen-4],3) == 0 ) - { - if ( (n= komodo_issued_opreturn(base,txids,vouts,values,srcvalues,kmdheights,otherheights,baseids,rmd160s,opretbuf,opretlen,0)) > 0 ) - { - for (i=0; itype = opretbuf[0]; - strcpy(pax->source,(char *)&opretbuf[opretlen-4]); - if ( (pax2= komodo_paxfind(txids[i],vouts[i],'D')) != 0 && pax2->fiatoshis != 0 && pax2->komodoshis != 0 ) - { - // realtime path? - pax->fiatoshis = pax2->fiatoshis; - pax->komodoshis = pax2->komodoshis; - pax->marked = pax2->marked = pax2->height; - if ( pax->didstats == 0 ) - { - if ( (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) - { - basesp->issued += pax->fiatoshis; - pax->didstats = 1; - pax->height = pax2->height; - pax->otherheight = height; - if ( 1 && strcmp(CURRENCIES[baseids[i]],"USD") == 0 ) - printf("########### %p issuedb %s += %.8f kmdheight.%d %.8f other.%d [%d]\n",basesp,CURRENCIES[baseids[i]],dstr(pax->fiatoshis),pax->height,dstr(pax->komodoshis),pax->otherheight,height); - } - } - } - } - if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'I',height)) != 0 ) - komodo_paxdelete(pax); - if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'D',height)) != 0 ) - komodo_paxdelete(pax); - } - } //else printf("opreturn none issued?\n"); - } - } - else if ( height < 236000 && opretbuf[0] == 'W' && strncmp(ASSETCHAINS_SYMBOL,(char *)&opretbuf[opretlen-4],3) == 0 )//&& opretlen >= 38 ) - { - if ( komodo_baseid((char *)&opretbuf[opretlen-4]) >= 0 && strcmp(ASSETCHAINS_SYMBOL,(char *)&opretbuf[opretlen-4]) == 0 ) - { - for (i=0; i (%s) len.%d\n",ASSETCHAINS_SYMBOL,base,kmdheight,height,dstr(checktoshis),dstr(komodoshis),dstr(value),komodo_is_issuer(),strncmp(ASSETCHAINS_SYMBOL,base,strlen(base)) == 0,(long long)seed,coinaddr,opretlen); - didstats = 0; - //if ( komodo_paxcmp(base,kmdheight,komodoshis,checktoshis,seed) == 0 ) - { - if ( value != 0 && ((pax= komodo_paxfind(txid,vout,'W')) == 0 || pax->didstats == 0) ) - { - if ( (basesp= komodo_stateptrget(base)) != 0 ) - { - basesp->withdrawn += value; - didstats = 1; - if ( 0 && strcmp(base,ASSETCHAINS_SYMBOL) == 0 ) - printf("########### %p withdrawn %s += %.8f check %.8f\n",basesp,base,dstr(value),dstr(checktoshis)); - } - if ( 0 && strcmp(base,"RUB") == 0 && (pax == 0 || pax->approved == 0) ) - printf("notarize %s %.8f -> %.8f kmd.%d other.%d\n",ASSETCHAINS_SYMBOL,dstr(value),dstr(komodoshis),kmdheight,height); - } - komodo_gateway_deposit(coinaddr,0,(char *)"KMD",value,rmd160,txid,vout,'W',kmdheight,height,source,0); - if ( (pax= komodo_paxfind(txid,vout,'W')) != 0 ) - { - pax->type = opretbuf[0]; - strcpy(pax->source,base); - strcpy(pax->symbol,"KMD"); - pax->height = kmdheight; - pax->otherheight = height; - pax->komodoshis = komodoshis; - } - } // else printf("withdraw %s paxcmp ht.%d %d error value %.8f -> %.8f vs %.8f\n",base,kmdheight,height,dstr(value),dstr(komodoshis),dstr(checktoshis)); - // need to allocate pax - } - else if ( height < 236000 && tokomodo != 0 && opretbuf[0] == 'A' && ASSETCHAINS_SYMBOL[0] == 0 ) - { - tokomodo = 1; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - { - for (i=0; i 0 ) - { - for (i=0; isymbol); - printf("override neg1 with (%s)\n",pax->symbol); - } - if ( baseids[i] < 0 ) - continue; - } - didstats = 0; - seed = 0; - checktoshis = komodo_paxprice(&seed,kmdheights[i],CURRENCIES[baseids[i]],(char *)"KMD",(uint64_t)values[i]); - //printf("PAX_fiatdest ht.%d price %s %.8f -> KMD %.8f vs %.8f\n",kmdheights[i],CURRENCIES[baseids[i]],(double)values[i]/COIN,(double)srcvalues[i]/COIN,(double)checktoshis/COIN); - if ( srcvalues[i] == checktoshis ) - { - if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) == 0 ) - { - bitcoin_address(coinaddr,60,&rmd160s[i*20],20); - komodo_gateway_deposit(coinaddr,srcvalues[i],CURRENCIES[baseids[i]],values[i],&rmd160s[i*20],txids[i],vouts[i],'A',kmdheights[i],otherheights[i],CURRENCIES[baseids[i]],kmdheights[i]); - if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) == 0 ) - printf("unexpected null pax for approve\n"); - else pax->validated = checktoshis; - if ( (pax2= komodo_paxfind(txids[i],vouts[i],'W')) != 0 ) - pax2->approved = kmdheights[i]; - komodo_paxmark(height,txids[i],vouts[i],'W',height); - //komodo_paxmark(height,txids[i],vouts[i],'A',height); - if ( values[i] != 0 && (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) - { - basesp->approved += values[i]; - didstats = 1; - //printf("pax.%p ########### %p approved %s += %.8f -> %.8f/%.8f kht.%d %d\n",pax,basesp,CURRENCIES[baseids[i]],dstr(values[i]),dstr(srcvalues[i]),dstr(checktoshis),kmdheights[i],otherheights[i]); - } - //printf(" i.%d (%s) <- %.8f ADDFLAG APPROVED\n",i,coinaddr,dstr(values[i])); - } - else if ( pax->didstats == 0 && srcvalues[i] != 0 ) - { - if ( (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) - { - basesp->approved += values[i]; - didstats = 1; - //printf("pax.%p ########### %p approved %s += %.8f -> %.8f/%.8f kht.%d %d\n",pax,basesp,CURRENCIES[baseids[i]],dstr(values[i]),dstr(srcvalues[i]),dstr(checktoshis),kmdheights[i],otherheights[i]); - } - } //else printf(" i.%d of n.%d pax.%p baseids[] %d\n",i,n,pax,baseids[i]); - if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) != 0 ) - { - pax->type = opretbuf[0]; - pax->approved = kmdheights[i]; - pax->validated = checktoshis; - if ( didstats != 0 ) - pax->didstats = 1; - //if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 ) - //printf(" i.%d approved.%d <<<<<<<<<<<<< APPROVED %p\n",i,kmdheights[i],pax); - } - } - } - } //else printf("n.%d from opreturns\n",n); - //printf("extra.[%d] after %.8f\n",n,dstr(komodo_paxtotal())); - } - else if ( height < 236000 && opretbuf[0] == 'X' && ASSETCHAINS_SYMBOL[0] == 0 ) - { - tokomodo = 1; - if ( (n= komodo_issued_opreturn(base,txids,vouts,values,srcvalues,kmdheights,otherheights,baseids,rmd160s,opretbuf,opretlen,1)) > 0 ) - { - for (i=0; itype = opretbuf[0]; - if ( height < 121842 ) // fields got switched around due to legacy issues and approves - value = srcvalues[i]; - else value = values[i]; - if ( baseids[i] >= 0 && value != 0 && (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) - { - basesp->redeemed += value; - pax->didstats = 1; - if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 ) - printf("ht.%d %.8f ########### %p redeemed %s += %.8f %.8f kht.%d ht.%d\n",height,dstr(value),basesp,CURRENCIES[baseids[i]],dstr(value),dstr(srcvalues[i]),kmdheights[i],otherheights[i]); - } - } - if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'W',height)) != 0 ) - komodo_paxdelete(pax); - if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'A',height)) != 0 ) - komodo_paxdelete(pax); - if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'X',height)) != 0 ) - komodo_paxdelete(pax); - } - } //else printf("komodo_issued_opreturn returned %d\n",n); - } - return(typestr); -} - -int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest); - -void komodo_stateind_set(struct komodo_state *sp,uint32_t *inds,int32_t n,uint8_t *filedata,long datalen,char *symbol,char *dest) -{ - uint8_t func; long lastK,lastT,lastN,lastV,fpos,lastfpos; int32_t i,count,doissue,iter,numn,numv,numN,numV,numR; uint32_t tmp,prevpos100,offset; - count = numR = numN = numV = numn = numv = 0; - lastK = lastT = lastN = lastV = -1; - for (iter=0; iter<2; iter++) - { - for (lastfpos=fpos=prevpos100=i=0; i> 8); - fpos = prevpos100 + offset; - if ( lastfpos >= datalen || (filedata[lastfpos] != func && func != 0) ) - printf("i.%d/n.%d lastfpos.%ld >= datalen.%ld or [%d] != func.%d\n",i,n,lastfpos,datalen,filedata[lastfpos],func); - else if ( iter == 0 ) - { - switch ( func ) - { - default: case 'P': case 'U': case 'D': - inds[i] &= 0xffffff00; - break; - case 'K': - lastK = lastfpos; - inds[i] &= 0xffffff00; - break; - case 'T': - lastT = lastfpos; - inds[i] &= 0xffffff00; - break; - case 'N': - lastN = lastfpos; - numN++; - break; - case 'V': - lastV = lastfpos; - numV++; - break; - case 'R': - numR++; - break; - } - } - else - { - doissue = 0; - if ( func == 'K' ) + doissue = 0; + if ( func == 'K' ) { if ( lastK == lastfpos ) doissue = 1; @@ -1218,15 +303,12 @@ void komodo_stateind_set(struct komodo_state *sp,uint32_t *inds,int32_t n,uint8_ } else if ( func == 'V' ) { - if ( KOMODO_PAX != 0 && numv > numV-1440 ) - doissue = 1; numv++; } else if ( func == 'R' ) doissue = 1; if ( doissue != 0 ) { - //printf("issue %c total.%d lastfpos.%ld\n",func,count,lastfpos); komodo_parsestatefiledata(sp,filedata,&lastfpos,datalen,symbol,dest); count++; } @@ -1236,12 +318,6 @@ void komodo_stateind_set(struct komodo_state *sp,uint32_t *inds,int32_t n,uint8_ } } printf("numR.%d numV.%d numN.%d count.%d\n",numR,numV,numN,count); - /*else if ( func == 'K' ) // KMD height: stop after 1st - else if ( func == 'T' ) // KMD height+timestamp: stop after 1st - - else if ( func == 'N' ) // notarization, scan backwards 1440+ blocks; - else if ( func == 'V' ) // price feed: can stop after 1440+ - else if ( func == 'R' ) // opreturn:*/ } void *OS_loadfile(const char *fname,uint8_t **bufp,long *lenp,long *allocsizep) @@ -1290,33 +366,49 @@ uint8_t *OS_fileptr(long *allocsizep,const char *fname) return((uint8_t *)retptr); } -long komodo_stateind_validate(struct komodo_state *sp,char *indfname,uint8_t *filedata,long datalen,uint32_t *prevpos100p,uint32_t *indcounterp,char *symbol,char *dest) +/** + * @brief Validate the index of the komodostate file + * + * @param[in] sp the komodo_state struct + * @param[in] indfname the index filename + * @param filedata bytes of data + * @param datalen length of filedata + * @param[out] prevpos100p + * @param[out] indcounterp + * @param symbol + * @param dest + * @return -1 on error + */ +long komodo_stateind_validate(struct komodo_state *sp,const std::string& indfname,uint8_t *filedata,long datalen, + uint32_t *prevpos100p,uint32_t *indcounterp,const char *symbol,const char *dest) { - FILE *fp; long fsize,lastfpos=0,fpos=0; uint8_t *inds,func; int32_t i,n; uint32_t offset,tmp,prevpos100 = 0; *indcounterp = *prevpos100p = 0; - if ( (inds= OS_fileptr(&fsize,indfname)) != 0 ) + long fsize; + uint8_t *inds; + if ( (inds= OS_fileptr(&fsize,indfname.c_str())) != 0 ) { - lastfpos = 0; - fprintf(stderr,"inds.%p validate %s fsize.%ld datalen.%ld n.%d lastfpos.%ld\n",inds,indfname,fsize,datalen,(int32_t)(fsize / sizeof(uint32_t)),lastfpos); + long lastfpos = 0; + fprintf(stderr,"inds.%p validate %s fsize.%ld datalen.%ld n.%d lastfpos.%ld\n",inds,indfname.c_str(),fsize,datalen,(int32_t)(fsize / sizeof(uint32_t)),lastfpos); if ( (fsize % sizeof(uint32_t)) == 0 ) { - n = (int32_t)(fsize / sizeof(uint32_t)); - for (i=0; i n-10 ) - printf("%d: tmp.%08x [%c] prevpos100.%u\n",i,tmp,tmp&0xff,prevpos100); if ( (i % 100) == 0 ) prevpos100 = tmp; else { - func = (tmp & 0xff); - offset = (tmp >> 8); + uint8_t func = (tmp & 0xff); + uint32_t offset = (tmp >> 8); fpos = prevpos100 + offset; if ( lastfpos >= datalen || filedata[lastfpos] != func ) { printf("validate.%d error (%u %d) prev100 %u -> fpos.%ld datalen.%ld [%d] (%c) vs (%c) lastfpos.%ld\n",i,offset,func,prevpos100,fpos,datalen,lastfpos < datalen ? filedata[lastfpos] : -1,func,filedata[lastfpos],lastfpos); - return(-1); + return -1; } } lastfpos = fpos; @@ -1325,25 +417,24 @@ long komodo_stateind_validate(struct komodo_state *sp,char *indfname,uint8_t *fi *prevpos100p = prevpos100; if ( sp != 0 ) komodo_stateind_set(sp,(uint32_t *)inds,n,filedata,fpos,symbol,dest); - //printf("free inds.%p %s validated[%d] fpos.%ld datalen.%ld, offset %ld vs fsize.%ld\n",inds,indfname,i,fpos,datalen,i * sizeof(uint32_t),fsize); free(inds); - return(fpos); - } else printf("wrong filesize %s %ld\n",indfname,fsize); + return fpos; + } + else + printf("wrong filesize %s %ld\n",indfname.c_str(),fsize); } free(inds); fprintf(stderr,"indvalidate return -1\n"); - return(-1); + return -1; } long komodo_indfile_update(FILE *indfp,uint32_t *prevpos100p,long lastfpos,long newfpos,uint8_t func,uint32_t *indcounterp) { - uint32_t tmp; if ( indfp != 0 ) { - tmp = ((uint32_t)(newfpos - *prevpos100p) << 8) | (func & 0xff); + uint32_t tmp = ((uint32_t)(newfpos - *prevpos100p) << 8) | (func & 0xff); if ( ftell(indfp)/sizeof(uint32_t) != *indcounterp ) printf("indfp fpos %ld -> ind.%ld vs counter.%u\n",ftell(indfp),ftell(indfp)/sizeof(uint32_t),*indcounterp); - //fprintf(stderr,"ftell.%ld indcounter.%u lastfpos.%ld newfpos.%ld func.%02x\n",ftell(indfp),*indcounterp,lastfpos,newfpos,func); fwrite(&tmp,1,sizeof(tmp),indfp), (*indcounterp)++; if ( (*indcounterp % 100) == 0 ) { @@ -1351,1373 +442,78 @@ long komodo_indfile_update(FILE *indfp,uint32_t *prevpos100p,long lastfpos,long fwrite(prevpos100p,1,sizeof(*prevpos100p),indfp), (*indcounterp)++; } } - return(newfpos); -} - -int32_t komodo_faststateinit(struct komodo_state *sp,const char *fname,char *symbol,char *dest) -{ - FILE *indfp; char indfname[1024]; uint8_t *filedata; long validated=-1,datalen,fpos,lastfpos; uint32_t tmp,prevpos100,indcounter,starttime; int32_t func,finished = 0; - starttime = (uint32_t)time(NULL); - safecopy(indfname,fname,sizeof(indfname)-4); - strcat(indfname,".ind"); - if ( (filedata= OS_fileptr(&datalen,fname)) != 0 ) - { - if ( 1 )//datalen >= (1LL << 32) || GetArg("-genind",0) != 0 || (validated= komodo_stateind_validate(0,indfname,filedata,datalen,&prevpos100,&indcounter,symbol,dest)) < 0 ) - { - lastfpos = fpos = 0; - indcounter = prevpos100 = 0; - if ( (indfp= fopen(indfname,"wb")) != 0 ) - fwrite(&prevpos100,1,sizeof(prevpos100),indfp), indcounter++; - fprintf(stderr,"processing %s %ldKB, validated.%ld\n",fname,datalen/1024,validated); - while ( (func= komodo_parsestatefiledata(sp,filedata,&fpos,datalen,symbol,dest)) >= 0 ) - { - lastfpos = komodo_indfile_update(indfp,&prevpos100,lastfpos,fpos,func,&indcounter); - } - if ( indfp != 0 ) - { - fclose(indfp); - if ( (fpos= komodo_stateind_validate(0,indfname,filedata,datalen,&prevpos100,&indcounter,symbol,dest)) < 0 ) - printf("unexpected komodostate.ind validate failure %s datalen.%ld\n",indfname,datalen); - else printf("%s validated fpos.%ld\n",indfname,fpos); - } - finished = 1; - fprintf(stderr,"took %d seconds to process %s %ldKB\n",(int32_t)(time(NULL)-starttime),fname,datalen/1024); - } - else if ( validated > 0 ) - { - if ( (indfp= fopen(indfname,"rb+")) != 0 ) - { - lastfpos = fpos = validated; - fprintf(stderr,"datalen.%ld validated %ld -> indcounter %u, prevpos100 %u offset.%d\n",datalen,validated,indcounter,prevpos100,(int32_t)(indcounter * sizeof(uint32_t))); - if ( fpos < datalen ) - { - fseek(indfp,indcounter * sizeof(uint32_t),SEEK_SET); - if ( ftell(indfp) == indcounter * sizeof(uint32_t) ) - { - while ( (func= komodo_parsestatefiledata(sp,filedata,&fpos,datalen,symbol,dest)) >= 0 ) - { - lastfpos = komodo_indfile_update(indfp,&prevpos100,lastfpos,fpos,func,&indcounter); - if ( lastfpos != fpos ) - fprintf(stderr,"unexpected lastfpos.%ld != %ld\n",lastfpos,fpos); - } - } - fclose(indfp); - } - if ( komodo_stateind_validate(sp,indfname,filedata,datalen,&prevpos100,&indcounter,symbol,dest) < 0 ) - printf("unexpected komodostate.ind validate failure %s datalen.%ld\n",indfname,datalen); - else - { - printf("%s validated updated from validated.%ld to %ld new.[%ld] -> indcounter %u, prevpos100 %u offset.%ld | elapsed %d seconds\n",indfname,validated,fpos,fpos-validated,indcounter,prevpos100,indcounter * sizeof(uint32_t),(int32_t)(time(NULL) - starttime)); - finished = 1; - } - } - } else printf("komodo_faststateinit unexpected case\n"); - free(filedata); - return(finished == 1); - } - return(-1); -} - -uint64_t komodo_interestsum(); - -void komodo_passport_iteration() -{ - static long lastpos[34]; static char userpass[33][1024]; static uint32_t lasttime,callcounter,lastinterest; - int32_t maxseconds = 10; - FILE *fp; uint8_t *filedata; long fpos,datalen,lastfpos; int32_t baseid,limit,n,ht,isrealtime,expired,refid,blocks,longest; struct komodo_state *sp,*refsp; char *retstr,fname[512],*base,symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; uint32_t buf[3],starttime; uint64_t RTmask = 0; //CBlockIndex *pindex; - expired = 0; - while ( 0 && KOMODO_INITDONE == 0 ) - { - fprintf(stderr,"[%s] PASSPORT iteration waiting for KOMODO_INITDONE\n",ASSETCHAINS_SYMBOL); - sleep(3); - } - if ( komodo_chainactive_timestamp() > lastinterest ) - { - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - komodo_interestsum(); - //komodo_longestchain(); - lastinterest = komodo_chainactive_timestamp(); - } - refsp = komodo_stateptr(symbol,dest); - if ( ASSETCHAINS_SYMBOL[0] == 0 || strcmp(ASSETCHAINS_SYMBOL,"KMDCC") == 0 ) - { - refid = 33; - limit = 10000000; - jumblr_iteration(); - } - else - { - limit = 10000000; - refid = komodo_baseid(ASSETCHAINS_SYMBOL)+1; // illegal base -> baseid.-1 -> 0 - if ( refid == 0 ) - { - KOMODO_PASSPORT_INITDONE = 1; - return; - } - } - /*if ( KOMODO_PAX == 0 ) - { - KOMODO_PASSPORT_INITDONE = 1; - return; - }*/ - starttime = (uint32_t)time(NULL); - if ( callcounter++ < 1 ) - limit = 10000; - lasttime = starttime; - for (baseid=32; baseid>=0; baseid--) - { - if ( time(NULL) >= starttime+maxseconds ) - break; - sp = 0; - isrealtime = 0; - base = (char *)CURRENCIES[baseid]; - //printf("PASSPORT %s baseid+1 %d refid.%d\n",ASSETCHAINS_SYMBOL,baseid+1,refid); - if ( baseid+1 != refid ) // only need to import state from a different coin - { - if ( baseid == 32 ) // only care about KMD's state - { - refsp->RTmask &= ~(1LL << baseid); - komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"komodostate"); - komodo_nameset(symbol,dest,base); - sp = komodo_stateptrget(symbol); - n = 0; - if ( lastpos[baseid] == 0 && (filedata= OS_fileptr(&datalen,fname)) != 0 ) - { - fpos = 0; - fprintf(stderr,"%s processing %s %ldKB\n",ASSETCHAINS_SYMBOL,fname,datalen/1024); - while ( komodo_parsestatefiledata(sp,filedata,&fpos,datalen,symbol,dest) >= 0 ) - lastfpos = fpos; - fprintf(stderr,"%s took %d seconds to process %s %ldKB\n",ASSETCHAINS_SYMBOL,(int32_t)(time(NULL)-starttime),fname,datalen/1024); - lastpos[baseid] = lastfpos; - free(filedata), filedata = 0; - datalen = 0; - } - else if ( (fp= fopen(fname,"rb")) != 0 && sp != 0 ) - { - fseek(fp,0,SEEK_END); - //fprintf(stderr,"couldnt OS_fileptr(%s), freading %ldKB\n",fname,ftell(fp)/1024); - if ( ftell(fp) > lastpos[baseid] ) - { - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - printf("%s passport refid.%d %s fname.(%s) base.%s %ld %ld\n",ASSETCHAINS_SYMBOL,refid,symbol,fname,base,ftell(fp),lastpos[baseid]); - fseek(fp,lastpos[baseid],SEEK_SET); - while ( komodo_parsestatefile(sp,fp,symbol,dest) >= 0 && n < limit ) - { - if ( n == limit-1 ) - { - if ( time(NULL) < starttime+maxseconds ) - n = 0; - else - { - //printf("expire passport loop %s -> %s at %ld\n",ASSETCHAINS_SYMBOL,base,lastpos[baseid]); - expired++; - } - } - n++; - } - lastpos[baseid] = ftell(fp); - if ( 0 && lastpos[baseid] == 0 && strcmp(symbol,"KMD") == 0 ) - printf("from.(%s) lastpos[%s] %ld isrt.%d\n",ASSETCHAINS_SYMBOL,CURRENCIES[baseid],lastpos[baseid],komodo_isrealtime(&ht)); - } //else fprintf(stderr,"%s.%ld ",CURRENCIES[baseid],ftell(fp)); - fclose(fp); - } else fprintf(stderr,"load error.(%s) %p\n",fname,sp); - komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"realtime"); - if ( (fp= fopen(fname,"rb")) != 0 ) - { - if ( fread(buf,1,sizeof(buf),fp) == sizeof(buf) ) - { - sp->CURRENT_HEIGHT = buf[0]; - if ( buf[0] != 0 && buf[0] >= buf[1] && buf[2] > time(NULL)-60 ) - { - isrealtime = 1; - RTmask |= (1LL << baseid); - memcpy(refsp->RTbufs[baseid+1],buf,sizeof(refsp->RTbufs[baseid+1])); - } - else if ( KOMODO_PAX != 0 && (time(NULL)-buf[2]) > 60 && ASSETCHAINS_SYMBOL[0] != 0 ) - fprintf(stderr,"[%s]: %s not RT %u %u %d\n",ASSETCHAINS_SYMBOL,base,buf[0],buf[1],(int32_t)(time(NULL)-buf[2])); - } //else fprintf(stderr,"%s size error RT\n",base); - fclose(fp); - } //else fprintf(stderr,"%s open error RT\n",base); - } - } - else - { - refsp->RTmask &= ~(1LL << baseid); - komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"realtime"); - if ( (fp= fopen(fname,"wb")) != 0 ) - { - buf[0] = (uint32_t)chainActive.LastTip()->nHeight; - buf[1] = (uint32_t)komodo_longestchain(); - if ( buf[0] != 0 && buf[0] == buf[1] ) - { - buf[2] = (uint32_t)time(NULL); - RTmask |= (1LL << baseid); - memcpy(refsp->RTbufs[baseid+1],buf,sizeof(refsp->RTbufs[baseid+1])); - if ( refid != 0 ) - memcpy(refsp->RTbufs[0],buf,sizeof(refsp->RTbufs[0])); - } - if ( fwrite(buf,1,sizeof(buf),fp) != sizeof(buf) ) - fprintf(stderr,"[%s] %s error writing realtime\n",ASSETCHAINS_SYMBOL,base); - fclose(fp); - } else fprintf(stderr,"%s create error RT\n",base); - } - if ( sp != 0 && isrealtime == 0 ) - refsp->RTbufs[0][2] = 0; - } - //komodo_paxtotal(); // calls komodo_isrealtime(), which calls komodo_longestchain() - refsp->RTmask |= RTmask; - if ( expired == 0 && KOMODO_PASSPORT_INITDONE == 0 ) - { - KOMODO_PASSPORT_INITDONE = 1; - printf("READY for %s RPC calls at %u! done PASSPORT %s refid.%d\n",ASSETCHAINS_SYMBOL,(uint32_t)time(NULL),ASSETCHAINS_SYMBOL,refid); - } -} - -void komodo_PriceCache_shift() -{ - int32_t i; - for (i=KOMODO_LOCALPRICE_CACHESIZE-1; i>0; i--) - memcpy(PriceCache[i],PriceCache[i-1],sizeof(PriceCache[i])); - memcpy(PriceCache[0],Mineropret.data(),Mineropret.size()); -} - -int32_t _komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,CBlock *block) -{ - CTransaction tx; int32_t numvouts; std::vector vopret; - tx = block->vtx[0]; - numvouts = (int32_t)tx.vout.size(); - GetOpReturnData(tx.vout[numvouts-1].scriptPubKey,vopret); - if ( vopret.size() >= PRICES_SIZEBIT0 ) - { - if ( seedp != 0 ) - memcpy(seedp,&block->hashMerkleRoot,sizeof(*seedp)); - memcpy(heightbits,vopret.data(),vopret.size()); - return((int32_t)(vopret.size()/sizeof(uint32_t))); - } - return(-1); -} - -// komodo_heightpricebits() extracts the price data in the coinbase for nHeight -int32_t komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHeight) -{ - CBlockIndex *pindex; CBlock block; - if ( seedp != 0 ) - *seedp = 0; - if ( (pindex= komodo_chainactive(nHeight)) != 0 ) - { - if ( komodo_blockload(block,pindex) == 0 ) - { - return(_komodo_heightpricebits(seedp,heightbits,&block)); - } - } - fprintf(stderr,"couldnt get pricebits for %d\n",nHeight); - return(-1); + return newfpos; } -/* - komodo_pricenew() is passed in a reference price, the change tolerance and the proposed price. it needs to return a clipped price if it is too big and also set a flag if it is at or above the limit +/*** + * @brief read the komodostate file + * @param sp the komodo_state struct + * @param fname the filename + * @param symbol the chain symbol + * @param dest the "parent" chain + * @return true on success */ -uint32_t komodo_pricenew(char *maxflagp,uint32_t price,uint32_t refprice,int64_t tolerance) +bool komodo_faststateinit(komodo_state *sp,const char *fname,char *symbol, const char *dest) { - uint64_t highprice,lowprice; - if ( refprice < 2 ) - return(0); - highprice = ((uint64_t)refprice * (COIN + tolerance)) / COIN; // calc highest acceptable price - lowprice = ((uint64_t)refprice * (COIN - tolerance)) / COIN; // and lowest - if ( highprice == refprice ) - highprice++; - if ( lowprice == refprice ) - lowprice--; - if ( price >= highprice ) - { - //fprintf(stderr,"high %u vs h%llu l%llu tolerance.%llu\n",price,(long long)highprice,(long long)lowprice,(long long)tolerance); - if ( price > highprice ) // return non-zero only if we violate the tolerance - { - *maxflagp = 2; - return(highprice); - } - *maxflagp = 1; - } - else if ( price <= lowprice ) - { - //fprintf(stderr,"low %u vs h%llu l%llu tolerance.%llu\n",price,(long long)highprice,(long long)lowprice,(long long)tolerance); - if ( price < lowprice ) - { - *maxflagp = -2; - return(lowprice); - } - *maxflagp = -1; - } - return(0); -} + uint32_t starttime = (uint32_t)time(NULL); -// komodo_pricecmp() returns -1 if any of the prices are beyond the tolerance -int32_t komodo_pricecmp(int32_t nHeight,int32_t n,char *maxflags,uint32_t *pricebitsA,uint32_t *pricebitsB,int64_t tolerance) -{ - int32_t i; uint32_t newprice; - for (i=1; i newprice.%u out of tolerance maxflag.%d\n",nHeight,i,n,pricebitsB[i],pricebitsA[i],newprice,maxflags[i]); - return(-1); - } - } - return(0); -} + long fpos = 0; + long lastfpos = 0; + uint32_t indcounter = 0; + uint32_t prevpos100 = 0; -// komodo_priceclamp() clamps any price that is beyond tolerance -int32_t komodo_priceclamp(int32_t n,uint32_t *pricebits,uint32_t *refprices,int64_t tolerance) -{ - int32_t i; uint32_t newprice; char maxflags[KOMODO_MAXPRICES]; - memset(maxflags,0,sizeof(maxflags)); - for (i=1; i %u\n",i,n,refprices[i],pricebits[i],newprice); - pricebits[i] = newprice; - } - } - return(0); -} + std::string indfname(fname); + indfname += ".ind"; + FILE *indfp = fopen(indfname.c_str(), "wb"); + if ( indfp != nullptr ) + fwrite(&prevpos100,1,sizeof(prevpos100),indfp), indcounter++; -// komodo_mineropret() returns a valid pricedata to add to the coinbase opreturn for nHeight -CScript komodo_mineropret(int32_t nHeight) -{ - CScript opret; char maxflags[KOMODO_MAXPRICES]; uint32_t pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES]; int32_t maxflag,i,n,numzero=0; - if ( Mineropret.size() >= PRICES_SIZEBIT0 ) - { - n = (int32_t)(Mineropret.size() / sizeof(uint32_t)); - numzero = 1; - while ( numzero > 0 ) + fprintf(stderr,"processing %s %ldKB, validated.%d\n",fname,datalen/1024,-1); + int32_t func; + while (!ShutdownRequested() && (func= komodo_parsestatefiledata(sp,filedata,&fpos,datalen,symbol,dest)) >= 0) { - memcpy(pricebits,Mineropret.data(),Mineropret.size()); - for (i=numzero=0; i 0 ) + if (ShutdownRequested()) { fclose(indfp); return false; } + if ( indfp != nullptr ) { - memcpy(pricebits,Mineropret.data(),Mineropret.size()); - memset(maxflags,0,sizeof(maxflags)); - if ( komodo_pricecmp(0,n,maxflags,pricebits,prevbits,PRICES_ERRORRATE) < 0 ) - { - // if the new prices are outside tolerance, update Mineropret with clamped prices - komodo_priceclamp(n,pricebits,prevbits,PRICES_ERRORRATE); - //fprintf(stderr,"update Mineropret to clamped prices\n"); - memcpy(Mineropret.data(),pricebits,Mineropret.size()); - } + fclose(indfp); + if ( (fpos= komodo_stateind_validate(0,indfname,filedata,datalen,&prevpos100,&indcounter,symbol,dest)) < 0 ) + printf("unexpected komodostate.ind validate failure %s datalen.%ld\n",indfname.c_str(),datalen); + else + printf("%s validated fpos.%ld\n",indfname.c_str(),fpos); } - int32_t i; - for (i=0; i vopret; char maxflags[KOMODO_MAXPRICES]; uint256 bhash; double btcusd,btcgbp,btceur; uint32_t localbits[KOMODO_MAXPRICES],pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES],newprice; int32_t i,j,prevtime,maxflag,lag,lag2,lag3,n,errflag,iter; uint32_t now; - now = (uint32_t)time(NULL); - if ( ASSETCHAINS_CBOPRET != 0 && nHeight > 0 ) + static uint32_t lastinterest; // prevent needless komodo_interestsum calls + if (komodo_chainactive_timestamp() > lastinterest) { - bhash = block->GetHash(); - GetOpReturnData(scriptPubKey,vopret); - if ( vopret.size() >= PRICES_SIZEBIT0 ) - { - n = (int32_t)(vopret.size() / sizeof(uint32_t)); - memcpy(pricebits,vopret.data(),Mineropret.size()); - memset(maxflags,0,sizeof(maxflags)); - if ( nHeight > 2 ) - { - prevtime = previndex->nTime; - lag = (int32_t)(now - pricebits[0]); - lag2 = (int32_t)(pricebits[0] - prevtime); - lag3 = (int32_t)(block->nTime - pricebits[0]); - if ( lag < -60 ) // avoid data from future - { - fprintf(stderr,"A ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d\n",nHeight,now,prevtime,block->nTime,pricebits[0],lag,lag2,lag3); - return(-1); - } - if ( lag2 < -60 ) //testchain_exemption ) // must be close to last block timestamp - { - fprintf(stderr,"B ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d vs %d cmp.%d\n",nHeight,now,prevtime,block->nTime,pricebits[0],lag,lag2,lag3,ASSETCHAINS_BLOCKTIME,lag2<-ASSETCHAINS_BLOCKTIME); - if ( nHeight > testchain_exemption ) - return(-1); - } - if ( lag3 < -60 || lag3 > ASSETCHAINS_BLOCKTIME ) - { - fprintf(stderr,"C ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d\n",nHeight,now,prevtime,block->nTime,pricebits[0],lag,lag2,lag3); - if ( nHeight > testchain_exemption ) - return(-1); - } - btcusd = (double)pricebits[1]/10000; - btcgbp = (double)pricebits[2]/10000; - btceur = (double)pricebits[3]/10000; - fprintf(stderr,"ht.%d: lag.%d %.4f USD, %.4f GBP, %.4f EUR, GBPUSD %.6f, EURUSD %.6f, EURGBP %.6f [%d]\n",nHeight,lag,btcusd,btcgbp,btceur,btcusd/btcgbp,btcusd/btceur,btcgbp/btceur,lag2); - if ( komodo_heightpricebits(0,prevbits,nHeight-1) > 0 ) - { - if ( nHeight < testchain_exemption ) - { - for (i=0; i= PRICES_SIZEBIT0 ) - { - memcpy(localbits,Mineropret.data(),Mineropret.size()); - if ( nHeight < testchain_exemption ) - { - for (i=0; i 0 && localbits[i] < prevbits[i] ) - { - if ( iter == 0 ) - break; - // second iteration checks recent prices to see if within local volatility - for (j=0; j= prevbits[i] ) - { - fprintf(stderr,"i.%d within recent localprices[%d] %u >= %u\n",i,j,PriceCache[j][i],prevbits[i]); - break; - } - if ( j == KOMODO_LOCALPRICE_CACHESIZE ) - { - komodo_queuelocalprice(1,nHeight,block->nTime,bhash,i,prevbits[i]); - break; - } - } - else if ( maxflag < 0 && localbits[i] > prevbits[i] ) - { - if ( iter == 0 ) - break; - for (j=0; jnTime,bhash,i,prevbits[i]); - break; - } - } - } - } - if ( i != n ) - { - if ( iter == 0 ) - { - fprintf(stderr,"force update prices\n"); - komodo_cbopretupdate(1); - memcpy(localbits,Mineropret.data(),Mineropret.size()); - } else return(-1); - } - } - } - } - if ( bhash == ExtremePrice.blockhash ) - { - fprintf(stderr,"approved a previously extreme price based on new data ht.%d vs %u vs %u\n",ExtremePrice.height,ExtremePrice.timestamp,(uint32_t)block->nTime); - memset(&ExtremePrice,0,sizeof(ExtremePrice)); - } - return(0); - } else fprintf(stderr,"wrong size %d vs %d, scriptPubKey size %d [%02x]\n",(int32_t)vopret.size(),(int32_t)Mineropret.size(),(int32_t)scriptPubKey.size(),scriptPubKey[0]); - return(-1); + komodo_interestsum(); + lastinterest = komodo_chainactive_timestamp(); } - return(0); -} -char *nonportable_path(char *str) -{ - int32_t i; - for (i=0; str[i]!=0; i++) - if ( str[i] == '/' ) - str[i] = '\\'; - return(str); -} - -char *portable_path(char *str) -{ -#ifdef _WIN32 - return(nonportable_path(str)); -#else -#ifdef __PNACL - /*int32_t i,n; - if ( str[0] == '/' ) - return(str); - else - { - n = (int32_t)strlen(str); - for (i=n; i>0; i--) - str[i] = str[i-1]; - str[0] = '/'; - str[n+1] = 0; - }*/ -#endif - return(str); -#endif -} - -void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) -{ - FILE *fp; - long filesize,buflen = *allocsizep; - uint8_t *buf = *bufp; - *lenp = 0; - if ( (fp= fopen(portable_path(fname),"rb")) != 0 ) - { - fseek(fp,0,SEEK_END); - filesize = ftell(fp); - if ( filesize == 0 ) - { - fclose(fp); - *lenp = 0; - //printf("loadfile null size.(%s)\n",fname); - return(0); - } - if ( filesize > buflen ) - { - *allocsizep = filesize; - *bufp = buf = (uint8_t *)realloc(buf,(long)*allocsizep+64); - } - rewind(fp); - if ( buf == 0 ) - printf("Null buf ???\n"); - else - { - if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize ) - printf("error reading filesize.%ld\n",(long)filesize); - buf[filesize] = 0; - } - fclose(fp); - *lenp = filesize; - //printf("loaded.(%s)\n",buf); - } //else printf("OS_loadfile couldnt load.(%s)\n",fname); - return(buf); -} - -void *filestr(long *allocsizep,char *_fname) -{ - long filesize = 0; char *fname,*buf = 0; void *retptr; - *allocsizep = 0; - fname = (char *)malloc(strlen(_fname)+1); - strcpy(fname,_fname); - retptr = loadfile(fname,(uint8_t **)&buf,&filesize,allocsizep); - free(fname); - return(retptr); -} - -cJSON *send_curl(char *url,char *fname) -{ - long fsize; char curlstr[1024],*jsonstr; cJSON *json=0; - sprintf(curlstr,"wget -q \"%s\" -O %s",url,fname); - if ( system(curlstr) == 0 ) - { - if ( (jsonstr= (char *)filestr((long *)&fsize,fname)) != 0 ) - { - json = cJSON_Parse(jsonstr); - free(jsonstr); - } - } - return(json); -} - -// get_urljson just returns the JSON returned by the URL using issue_curl - - -/* -const char *Techstocks[] = -{ "AAPL","ADBE","ADSK","AKAM","AMD","AMZN","ATVI","BB","CDW","CRM","CSCO","CYBR","DBX","EA","FB","GDDY","GOOG","GRMN","GSAT","HPQ","IBM","INFY","INTC","INTU","JNPR","MSFT","MSI","MU","MXL","NATI","NCR","NFLX","NTAP","NVDA","ORCL","PANW","PYPL","QCOM","RHT","S","SHOP","SNAP","SPOT","SYMC","SYNA","T","TRIP","TWTR","TXN","VMW","VOD","VRSN","VZ","WDC","XRX","YELP","YNDX","ZEN" -}; -const char *Metals[] = { "XAU", "XAG", "XPT", "XPD", }; - -const char *Markets[] = { "DJIA", "SPX", "NDX", "VIX" }; -*/ - -cJSON *get_urljson(char *url) -{ - char *jsonstr; cJSON *json = 0; - if ( (jsonstr= issue_curl(url)) != 0 ) - { - //fprintf(stderr,"(%s) -> (%s)\n",url,jsonstr); - json = cJSON_Parse(jsonstr); - free(jsonstr); - } - return(json); -} - -int32_t get_stockprices(uint32_t now,uint32_t *prices,std::vector symbols) -{ - char url[32768],*symbol,*timestr; cJSON *json,*obj; int32_t i,n=0,retval=-1; uint32_t uprice,timestamp; - sprintf(url,"https://api.iextrading.com/1.0/tops/last?symbols=%s",GetArg("-ac_stocks","").c_str()); - fprintf(stderr,"url.(%s)\n",url); - if ( (json= get_urljson(url)) != 0 ) //if ( (json= send_curl(url,(char *)"iex")) != 0 ) // - { - fprintf(stderr,"stocks.(%s)\n",jprint(json,0)); - if ( (n= cJSON_GetArraySize(json)) > 0 ) - { - retval = n; - for (i=0; i now+60 || timestamp < now-ASSETCHAINS_BLOCKTIME ) - { - fprintf(stderr,"time error.%d (%u vs %u)\n",timestamp-now,timestamp,now); - retval = -1; - }*/ - if ( symbols[i] != symbol ) - { - retval = -1; - fprintf(stderr,"MISMATCH."); - } - fprintf(stderr,"(%s %u) ",symbol,uprice); - } - } - fprintf(stderr,"numstocks.%d\n",n); - } - //https://api.iextrading.com/1.0/tops/last?symbols=AAPL -> [{"symbol":"AAPL","price":198.63,"size":100,"time":1555092606076}] - free_json(json); - } - return(retval); -} - -uint32_t get_dailyfx(uint32_t *prices) -{ - //{"base":"USD","rates":{"BGN":1.74344803,"NZD":1.471652701,"ILS":3.6329113924,"RUB":65.1997682296,"CAD":1.3430201462,"USD":1.0,"PHP":52.8641469068,"CHF":0.9970582992,"AUD":1.4129078267,"JPY":110.6792654662,"TRY":5.6523444464,"HKD":7.8499732573,"MYR":4.0824567659,"HRK":6.6232840078,"CZK":22.9862720628,"IDR":14267.4986628633,"DKK":6.6551078624,"NOK":8.6806917454,"HUF":285.131039401,"GBP":0.7626582278,"MXN":19.4183455161,"THB":31.8702085933,"ISK":122.5708682475,"ZAR":14.7033339276,"BRL":3.9750401141,"SGD":1.3573720806,"PLN":3.8286682118,"INR":69.33187734,"KRW":1139.1602781244,"RON":4.2423783206,"CNY":6.7387234801,"SEK":9.3385630237,"EUR":0.8914244963},"date":"2019-03-28"} - char url[512],*datestr; cJSON *json,*rates; int32_t i; uint32_t datenum=0,price = 0; - sprintf(url,"https://api.openrates.io/latest?base=USD"); - if ( (json= get_urljson(url)) != 0 ) //if ( (json= send_curl(url,(char *)"dailyfx")) != 0 ) - { - if ( (rates= jobj(json,(char *)"rates")) != 0 ) - { - for (i=0; i strvec) -{ - int32_t i,errs=0; uint32_t price; char *symbol; - for (i=0; i 333 ) // for debug only! -// ASSETCHAINS_CBOPRET = 7; - size = komodo_cbopretsize(ASSETCHAINS_CBOPRET); - if ( Mineropret.size() < size ) - Mineropret.resize(size); - size = PRICES_SIZEBIT0; - if ( (forceflag != 0 || now > lastbtc+120) && get_btcusd(pricebits) == 0 ) - { - if ( flags == 0 ) - komodo_PriceCache_shift(); - memcpy(PriceCache[0],pricebits,PRICES_SIZEBIT0); - flags |= 1; - } - if ( (ASSETCHAINS_CBOPRET & 2) != 0 ) - { - if ( now > lasttime+3600*5 || forexprices[0] == 0 ) // cant assume timestamp is valid for forex price as it is a daily weekday changing thing anyway. - { - get_dailyfx(forexprices); - if ( flags == 0 ) - komodo_PriceCache_shift(); - flags |= 2; - memcpy(&PriceCache[0][size/sizeof(uint32_t)],forexprices,sizeof(forexprices)); - } - size += (sizeof(Forex)/sizeof(*Forex)) * sizeof(uint32_t); - } - if ( (ASSETCHAINS_CBOPRET & 4) != 0 ) - { - if ( forceflag != 0 || flags != 0 ) - { - get_cryptoprices(pricebuf,Cryptos,(int32_t)(sizeof(Cryptos)/sizeof(*Cryptos)),ASSETCHAINS_PRICES); - if ( flags == 0 ) - komodo_PriceCache_shift(); - memcpy(&PriceCache[0][size/sizeof(uint32_t)],pricebuf,(sizeof(Cryptos)/sizeof(*Cryptos)+ASSETCHAINS_PRICES.size()) * sizeof(uint32_t)); - flags |= 4; // very rarely we can see flags == 6 case - } - size += (sizeof(Cryptos)/sizeof(*Cryptos)+ASSETCHAINS_PRICES.size()) * sizeof(uint32_t); - } - now = (uint32_t)time(NULL); - if ( (ASSETCHAINS_CBOPRET & 8) != 0 ) - { - if ( forceflag != 0 || flags != 0 ) - { - if ( get_stockprices(now,pricebuf,ASSETCHAINS_STOCKS) == ASSETCHAINS_STOCKS.size() ) - { - if ( flags == 0 ) - komodo_PriceCache_shift(); - memcpy(&PriceCache[0][size/sizeof(uint32_t)],pricebuf,ASSETCHAINS_STOCKS.size() * sizeof(uint32_t)); - flags |= 8; // very rarely we can see flags == 10 case - } - } - size += (ASSETCHAINS_STOCKS.size()) * sizeof(uint32_t); - } - if ( flags != 0 ) - { - if ( (flags & 1) != 0 ) - lastbtc = now; - if ( (flags & 2) != 0 ) - lasttime = now; - memcpy(Mineropret.data(),PriceCache[0],size); - if ( ExtremePrice.dir != 0 && ExtremePrice.ind > 0 && ExtremePrice.ind < size/sizeof(uint32_t) && now < ExtremePrice.timestamp+3600 ) - { - fprintf(stderr,"cmp dir.%d PriceCache[0][ExtremePrice.ind] %u >= %u ExtremePrice.pricebits\n",ExtremePrice.dir,PriceCache[0][ExtremePrice.ind],ExtremePrice.pricebits); - if ( (ExtremePrice.dir > 0 && PriceCache[0][ExtremePrice.ind] >= ExtremePrice.pricebits) || (ExtremePrice.dir < 0 && PriceCache[0][ExtremePrice.ind] <= ExtremePrice.pricebits) ) - { - fprintf(stderr,"future price is close enough to allow approving previously rejected block ind.%d %u vs %u\n",ExtremePrice.ind,PriceCache[0][ExtremePrice.ind],ExtremePrice.pricebits); - if ( (pindex= komodo_blockindex(ExtremePrice.blockhash)) != 0 ) - pindex->nStatus &= ~BLOCK_FAILED_MASK; - else fprintf(stderr,"couldnt find block.%s\n",ExtremePrice.blockhash.GetHex().c_str()); - } - } - // high volatility still strands nodes so we need to check new prices to approve a stuck block - // scan list of stuck blocks (one?) and auto reconsiderblock if it changed state - - //int32_t i; for (i=0; i= KOMODO_MAXPRICES ) - return(-1); - mult = komodo_pricemult(ind); - if ( nonzprices != 0 ) - memset(nonzprices,0,sizeof(*nonzprices)*PRICES_DAYWINDOW); - //for (i=0; i= PRICES_DAYWINDOW ) - i = 0; - if ( (price= rawprices[i*rawskip]) == 0 ) - { - fprintf(stderr,"null rawprice.[%d]\n",i); - return(-1); - } - if ( price >= lowprice && price <= highprice ) - { - //fprintf(stderr,"%.1f ",(double)price/10000); - sum += price; - correlation++; - if ( correlation > (PRICES_DAYWINDOW>>1) ) - { - if ( nonzprices == 0 ) - return(refprice * mult); - //fprintf(stderr,"-> %.4f\n",(double)sum*mult/correlation); - //return(sum*mult/correlation); - n = 0; - i = (iter + seed) % PRICES_DAYWINDOW; - for (k=0; k= PRICES_DAYWINDOW ) - i = 0; - if ( n > (PRICES_DAYWINDOW>>1) ) - nonzprices[i] = 0; - else - { - price = rawprices[i*rawskip]; - if ( price < lowprice || price > highprice ) - nonzprices[i] = 0; - else - { - nonzprices[i] = price; - //fprintf(stderr,"(%d %u) ",i,rawprices[i*rawskip]); - n++; - } - } - } - //fprintf(stderr,"ind.%d iter.%d j.%d i.%d n.%d correlation.%d ref %llu -> %llu\n",ind,iter,j,i,n,correlation,(long long)refprice,(long long)sum/correlation); - if ( n != correlation ) - return(-1); - sum = den = n = 0; - for (i=0; i %.8f\n",(long long)firstprice,((double)(sum*mult) / den) / COIN); - return((sum * mult) / den); - } - } - } - if ( correlation > maxcorrelation ) - maxcorrelation = correlation; - } - fprintf(stderr,"ind.%d iter.%d maxcorrelation.%d ref.%llu high.%llu low.%llu\n",ind,iter,maxcorrelation,(long long)refprice,(long long)highprice,(long long)lowprice); - return(0); -} - -int64_t _pairave64(int64_t valA,int64_t valB) -{ - if ( valA != 0 && valB != 0 ) - return((valA + valB) / 2); - else if ( valA != 0 ) return(valA); - else return(valB); -} - -int64_t _pairdiff64(register int64_t valA,register int64_t valB) -{ - if ( valA != 0 && valB != 0 ) - return(valA - valB); - else return(0); -} - -int64_t balanced_ave64(int64_t buf[],int32_t i,int32_t width) -{ - register int32_t nonz,j; register int64_t sum,price; - nonz = 0; - sum = 0; - for (j=-width; j<=width; j++) - { - price = buf[i + j]; - if ( price != 0 ) - { - sum += price; - nonz++; - } - } - if ( nonz != 0 ) - sum /= nonz; - return(sum); -} - -void buf_trioave64(int64_t dest[],int64_t src[],int32_t n) -{ - register int32_t i,j,width = 3; - for (i=0; i<128; i++) - src[i] = 0; - //for (i=n-width-1; i>width; i--) - // dest[i] = balanced_ave(src,i,width); - //for (i=width; i>0; i--) - // dest[i] = balanced_ave(src,i,i); - for (i=1; i price ) // rising prices - sort64(buf,PRICES_DAYWINDOW); - else revsort64(buf,PRICES_DAYWINDOW); - decayprice = buf[0]; - for (i=0; i %.8f\n",halfave 0 && PRICES[0].fp != 0 && createflag != 0 ) - { - fseek(PRICES[0].fp,(2*PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH) * sizeof(uint32_t) * i,SEEK_SET); - fputc(0,PRICES[0].fp); - fflush(PRICES[0].fp); - } - fprintf(stderr,"pricesinit done i.%d num.%d numprices.%d\n",i,num,(int32_t)(komodo_cbopretsize(ASSETCHAINS_CBOPRET)/sizeof(uint32_t))); - if ( i != num || i != komodo_cbopretsize(ASSETCHAINS_CBOPRET)/sizeof(uint32_t) ) - { - fprintf(stderr,"fatal error opening prices files, start shutdown\n"); - StartShutdown(); - } - return(0); -} - -pthread_mutex_t pricemutex; - -// PRICES file layouts -// [0] rawprice32 / timestamp -// [1] correlated -// [2] 24hr ave -// [3] to [7] reserved - -void komodo_pricesupdate(int32_t height,CBlock *pblock) -{ - static int numprices; static uint32_t *ptr32; static int64_t *ptr64,*tmpbuf; - int32_t ind,offset,width; int64_t correlated,smoothed; uint64_t seed,rngval; uint32_t rawprices[KOMODO_MAXPRICES],buf[PRICES_MAXDATAPOINTS*2]; - width = PRICES_DAYWINDOW;//(2*PRICES_DAYWINDOW + PRICES_SMOOTHWIDTH); - if ( numprices == 0 ) - { - pthread_mutex_init(&pricemutex,0); - numprices = (int32_t)(komodo_cbopretsize(ASSETCHAINS_CBOPRET) / sizeof(uint32_t)); - ptr32 = (uint32_t *)calloc(sizeof(uint32_t),numprices * width); - ptr64 = (int64_t *)calloc(sizeof(int64_t),PRICES_DAYWINDOW*PRICES_MAXDATAPOINTS); - tmpbuf = (int64_t *)calloc(sizeof(int64_t),2*PRICES_DAYWINDOW); - fprintf(stderr,"prices update: numprices.%d %p %p\n",numprices,ptr32,ptr64); - } - if ( _komodo_heightpricebits(&seed,rawprices,pblock) == numprices ) - { - //for (ind=0; ind PRICES_DAYWINDOW ) - { - fseek(PRICES[0].fp,(height-width+1) * numprices * sizeof(uint32_t),SEEK_SET); - if ( fread(ptr32,sizeof(uint32_t),width*numprices,PRICES[0].fp) == width*numprices ) - { - rngval = seed; - for (ind=1; ind 0 ) - { - fseek(PRICES[ind].fp,height * sizeof(int64_t) * PRICES_MAXDATAPOINTS,SEEK_SET); - memset(buf,0,sizeof(buf)); - buf[0] = rawprices[ind]; - buf[1] = rawprices[0]; // timestamp - memcpy(&buf[2],&correlated,sizeof(correlated)); - if ( fwrite(buf,1,sizeof(buf),PRICES[ind].fp) != sizeof(buf) ) - fprintf(stderr,"error fwrite buf for ht.%d ind.%d\n",height,ind); - else if ( height > PRICES_DAYWINDOW*2 ) - { - fseek(PRICES[ind].fp,(height-PRICES_DAYWINDOW+1) * PRICES_MAXDATAPOINTS * sizeof(int64_t),SEEK_SET); - if ( fread(ptr64,sizeof(int64_t),PRICES_DAYWINDOW*PRICES_MAXDATAPOINTS,PRICES[ind].fp) == PRICES_DAYWINDOW*PRICES_MAXDATAPOINTS ) - { - if ( (smoothed= komodo_priceave(tmpbuf,&ptr64[(PRICES_DAYWINDOW-1)*PRICES_MAXDATAPOINTS+1],-PRICES_MAXDATAPOINTS)) > 0 ) - { - fseek(PRICES[ind].fp,(height * PRICES_MAXDATAPOINTS + 2) * sizeof(int64_t),SEEK_SET); - if ( fwrite(&smoothed,1,sizeof(smoothed),PRICES[ind].fp) != sizeof(smoothed) ) - fprintf(stderr,"error fwrite smoothed for ht.%d ind.%d\n",height,ind); - else fflush(PRICES[ind].fp); - } else fprintf(stderr,"error price_smoothed ht.%d ind.%d\n",height,ind); - } else fprintf(stderr,"error fread ptr64 for ht.%d ind.%d\n",height,ind); - } - } else fprintf(stderr,"error komodo_pricecorrelated for ht.%d ind.%d\n",height,ind); - } - fprintf(stderr,"height.%d\n",height); - } else fprintf(stderr,"error reading rawprices for ht.%d\n",height); - } else fprintf(stderr,"height.%d <= width.%d\n",height,width); - pthread_mutex_unlock(&pricemutex); - } else fprintf(stderr,"null PRICES[0].fp\n"); - } else fprintf(stderr,"numprices mismatch, height.%d\n",height); -} - -int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblocks) -{ - FILE *fp; int32_t retval = PRICES_MAXDATAPOINTS; - pthread_mutex_lock(&pricemutex); - if ( ind < KOMODO_MAXPRICES && (fp= PRICES[ind].fp) != 0 ) + static bool first_call = true; + if ( first_call ) { - fseek(fp,height * PRICES_MAXDATAPOINTS * sizeof(int64_t),SEEK_SET); - if ( fread(buf64,sizeof(int64_t),numblocks*PRICES_MAXDATAPOINTS,fp) != numblocks*PRICES_MAXDATAPOINTS ) - retval = -1; + first_call = false; + printf("READY for %s RPC calls at %u\n", + chainName.ToString().c_str(), (uint32_t)time(NULL)); } - pthread_mutex_unlock(&pricemutex); - return(retval); } diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 783d812d065..2619a36c43c 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -13,228 +13,49 @@ * * ******************************************************************************/ #pragma once -// paxdeposit equivalent in reverse makes opreturn and KMD does the same in reverse -#include "komodo_defs.h" -#include "komodo_cJSON.h" +#include -int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base); - -void pax_keyset(uint8_t *buf,uint256 txid,uint16_t vout,uint8_t type); - -struct pax_transaction *komodo_paxfind(uint256 txid,uint16_t vout,uint8_t type); - -struct pax_transaction *komodo_paxfinds(uint256 txid,uint16_t vout); - -struct pax_transaction *komodo_paxmark(int32_t height,uint256 txid,uint16_t vout,uint8_t type,int32_t mark); - -void komodo_paxdelete(struct pax_transaction *pax); - -void komodo_gateway_deposit(char *coinaddr,uint64_t value,char *symbol,uint64_t fiatoshis,uint8_t *rmd160,uint256 txid,uint16_t vout,uint8_t type,int32_t height,int32_t otherheight,char *source,int32_t approved); - -int32_t komodo_rwapproval(int32_t rwflag,uint8_t *opretbuf,struct pax_transaction *pax); - -int32_t komodo_issued_opreturn(char *base,uint256 *txids,uint16_t *vouts,int64_t *values,int64_t *srcvalues,int32_t *kmdheights,int32_t *otherheights,int8_t *baseids,uint8_t *rmd160s,uint8_t *opretbuf,int32_t opretlen,int32_t iskomodo); - -int32_t komodo_paxcmp(char *symbol,int32_t kmdheight,uint64_t value,uint64_t checkvalue,uint64_t seed); - -uint64_t komodo_paxtotal(); - -static int _paxorder(const void *a,const void *b) -{ -#define pax_a (*(struct pax_transaction **)a) -#define pax_b (*(struct pax_transaction **)b) - uint64_t aval,bval; - aval = pax_a->fiatoshis + pax_a->komodoshis + pax_a->height; - bval = pax_b->fiatoshis + pax_b->komodoshis + pax_b->height; - if ( bval > aval ) - return(-1); - else if ( bval < aval ) - return(1); - return(0); -#undef pax_a -#undef pax_b -} - -int32_t komodo_pending_withdraws(char *opretstr); - -int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *base,int32_t tokomodo); - -int32_t komodo_checkvout(int32_t vout,int32_t k,int32_t indallvouts); +struct komodo_state; +class CBlock; +/**** + * @brief Check if the n of the vout matches one that is banned + * @param vout the "n" of the vout + * @param k the index in the array of banned txids + * @param indallvouts the index at which all "n"s are banned + * @returns true if vout is banned + */ +bool komodo_checkvout(int32_t vout,int32_t k,int32_t indallvouts); + +/**** + * @brief retrieve list of banned txids + * @param[out] indallvoutsp size of array - 2 + * @param[out] array of txids + * @param[in] max the max size of the array + * @returns the number of txids placed into the array + */ int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max); -void komodo_passport_iteration(); - -int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtime); // verify above block is valid pax pricing - -const char *komodo_opreturn(int32_t height,uint64_t value,uint8_t *opretbuf,int32_t opretlen,uint256 txid,uint16_t vout,char *source); - -int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest); - -void komodo_stateind_set(struct komodo_state *sp,uint32_t *inds,int32_t n,uint8_t *filedata,long datalen,char *symbol,char *dest); - -void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep); - -uint8_t *OS_fileptr(long *allocsizep,const char *fname); - -long komodo_stateind_validate(struct komodo_state *sp,char *indfname,uint8_t *filedata,long datalen,uint32_t *prevpos100p,uint32_t *indcounterp,char *symbol,char *dest); - -long komodo_indfile_update(FILE *indfp,uint32_t *prevpos100p,long lastfpos,long newfpos,uint8_t func,uint32_t *indcounterp); - -int32_t komodo_faststateinit(struct komodo_state *sp,const char *fname,char *symbol,char *dest); - -uint64_t komodo_interestsum(); - -void komodo_passport_iteration(); - -extern std::vector Mineropret; // opreturn data set by the data gathering code -#define PRICES_ERRORRATE (COIN / 100) // maximum acceptable change, set at 1% -#define PRICES_SIZEBIT0 (sizeof(uint32_t) * 4) // 4 uint32_t unixtimestamp, BTCUSD, BTCGBP and BTCEUR -#define KOMODO_LOCALPRICE_CACHESIZE 13 -#define KOMODO_MAXPRICES 2048 -#define PRICES_SMOOTHWIDTH 1 - -#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"CBCOINBASE",cmdstr,0,0,0) - -int32_t komodo_cbopretsize(uint64_t flags); - -void komodo_PriceCache_shift(); - -int32_t _komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,CBlock *block); - -// komodo_heightpricebits() extracts the price data in the coinbase for nHeight -int32_t komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHeight); - -/* - komodo_pricenew() is passed in a reference price, the change tolerance and the proposed price. it needs to return a clipped price if it is too big and also set a flag if it is at or above the limit +/*** + * @brief update wallet balance / interest + * @note called only on KMD chain every 10 seconds ( see ThreadUpdateKomodoInternals() ) */ -uint32_t komodo_pricenew(char *maxflagp,uint32_t price,uint32_t refprice,int64_t tolerance); - -// komodo_pricecmp() returns -1 if any of the prices are beyond the tolerance -int32_t komodo_pricecmp(int32_t nHeight,int32_t n,char *maxflags,uint32_t *pricebitsA,uint32_t *pricebitsB,int64_t tolerance); +void komodo_update_interest(); -// komodo_priceclamp() clamps any price that is beyond tolerance -int32_t komodo_priceclamp(int32_t n,uint32_t *pricebits,uint32_t *refprices,int64_t tolerance); - -// komodo_mineropret() returns a valid pricedata to add to the coinbase opreturn for nHeight -CScript komodo_mineropret(int32_t nHeight); - -/* - komodo_opretvalidate() is the entire price validation! - it prints out some useful info for debugging, like the lag from current time and prev block and the prices encoded in the opreturn. - - The only way komodo_opretvalidate() doesnt return an error is if maxflag is set or it is within tolerance of both the prior block and the local data. The local data validation only happens if it is a recent block and not a block from the past as the local node is only getting the current price data. - +/*** + * @brief verify block is valid pax pricing + * @param height the height of the block + * @param block the block to check + * @returns <0 on error, 0 on success */ - - -void komodo_queuelocalprice(int32_t dir,int32_t height,uint32_t timestamp,uint256 blockhash,int32_t ind,uint32_t pricebits); - -int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,int32_t nHeight,CScript scriptPubKey); - -char *nonportable_path(char *str); - -char *portable_path(char *str); - -void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep); - -void *filestr(long *allocsizep,char *_fname); - -cJSON *send_curl(char *url,char *fname); - -// get_urljson just returns the JSON returned by the URL using issue_curl - - -/* -const char *Techstocks[] = -{ "AAPL","ADBE","ADSK","AKAM","AMD","AMZN","ATVI","BB","CDW","CRM","CSCO","CYBR","DBX","EA","FB","GDDY","GOOG","GRMN","GSAT","HPQ","IBM","INFY","INTC","INTU","JNPR","MSFT","MSI","MU","MXL","NATI","NCR","NFLX","NTAP","NVDA","ORCL","PANW","PYPL","QCOM","RHT","S","SHOP","SNAP","SPOT","SYMC","SYNA","T","TRIP","TWTR","TXN","VMW","VOD","VRSN","VZ","WDC","XRX","YELP","YNDX","ZEN" -}; -const char *Metals[] = { "XAU", "XAG", "XPT", "XPD", }; - -const char *Markets[] = { "DJIA", "SPX", "NDX", "VIX" }; -*/ - -cJSON *get_urljson(char *url); - -int32_t get_stockprices(uint32_t now,uint32_t *prices,std::vector symbols); - -uint32_t get_dailyfx(uint32_t *prices); - -uint32_t get_binanceprice(const char *symbol); - -int32_t get_cryptoprices(uint32_t *prices,const char *list[],int32_t n,std::vector strvec); - -// parse the coindesk specific data. yes, if this changes, it will require an update. However, regardless if the format from the data source changes, then the code that extracts it must be changed. One way to mitigate this is to have a large variety of data sources so that there is only a very remote chance that all of them are not available. Certainly the data gathering needs to be made more robust, but it doesnt really affect the proof of concept for the decentralized trustless oracle. The trustlessness is achieved by having all nodes get the oracle data. - -int32_t get_btcusd(uint32_t pricebits[4]); - -// komodo_cbopretupdate() obtains the external price data and encodes it into Mineropret, which will then be used by the miner and validation -// save history, use new data to approve past rejection, where is the auto-reconsiderblock? - -int32_t komodo_cbopretsize(uint64_t flags); - -void komodo_cbopretupdate(int32_t forceflag); - -int64_t komodo_pricemult(int32_t ind); - -char *komodo_pricename(char *name,int32_t ind); - -// finds index for its symbol name -int32_t komodo_priceind(const char *symbol); - -// returns price value which is in a 10% interval for more than 50% points for the preceding 24 hours -int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int32_t rawskip,uint32_t *nonzprices,int32_t smoothwidth); - -int64_t _pairave64(int64_t valA,int64_t valB); - -int64_t _pairdiff64(register int64_t valA,register int64_t valB); - -int64_t balanced_ave64(int64_t buf[],int32_t i,int32_t width); - -void buf_trioave64(int64_t dest[],int64_t src[],int32_t n); - -void smooth64(int64_t dest[],int64_t src[],int32_t width,int32_t smoothiters); - -// http://www.holoborodko.com/pavel/numerical-methods/noise-robust-smoothing-filter/ -//const int64_t coeffs[7] = { -2, 0, 18, 32, 18, 0, -2 }; -static int cmp_llu(const void *a, const void*b) -{ - if(*(int64_t *)a < *(int64_t *)b) return -1; - else if(*(int64_t *)a > *(int64_t *)b) return 1; - else if ( (uint64_t)a < (uint64_t)b ) // jl777 prevent nondeterminism - return(-1); - else return(1); -} - -static void sort64(int64_t *l, int32_t llen) -{ - qsort(l,llen,sizeof(uint64_t),cmp_llu); -} - -static int revcmp_llu(const void *a, const void*b) -{ - if(*(int64_t *)a < *(int64_t *)b) return 1; - else if(*(int64_t *)a > *(int64_t *)b) return -1; - else if ( (uint64_t)a < (uint64_t)b ) // jl777 prevent nondeterminism - return(-1); - else return(1); -} - -static void revsort64(int64_t *l, int32_t llen) -{ - qsort(l,llen,sizeof(uint64_t),revcmp_llu); -} - -int64_t komodo_priceave(int64_t *buf,int64_t *correlated,int32_t cskip); - -int32_t komodo_pricesinit(); - -// PRICES file layouts -// [0] rawprice32 / timestamp -// [1] correlated -// [2] 24hr ave -// [3] to [7] reserved - -void komodo_pricesupdate(int32_t height,CBlock *pblock); - -int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblocks); +int32_t komodo_check_deposit(int32_t height,const CBlock& block); + +/*** + * @brief read the komodostate file + * @param sp the komodo_state struct + * @param fname the filename + * @param symbol the chain symbol + * @param dest the "parent" chain + * @return true on success + */ +bool komodo_faststateinit(komodo_state *sp,const char *fname,char *symbol, const char *dest); diff --git a/src/komodo_globals.cpp b/src/komodo_globals.cpp index dffafdda929..b7b75e823f4 100644 --- a/src/komodo_globals.cpp +++ b/src/komodo_globals.cpp @@ -12,175 +12,109 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ +#include "komodo_defs.h" #include "komodo_globals.h" +#include "komodo_extern_globals.h" +#include "komodo_notary.h" -int32_t komodo_baseid(char *origbase) -{ - int32_t i; char base[64]; - for (i=0; origbase[i]!=0&&i= 0 && baseid < 32 ) - // cur_money = ASSETCHAINS_GENESISTXVAL + ASSETCHAINS_SUPPLY + nHeight * ASSETCHAINS_REWARD[0] / SATOSHIDEN; - //else - { - // figure out max_money by adding up supply to a maximum of 10,000,000 blocks - cur_money = (ASSETCHAINS_SUPPLY+1) * SATOSHIDEN + (ASSETCHAINS_MAGIC & 0xffffff) + ASSETCHAINS_GENESISTXVAL; - if ( ASSETCHAINS_LASTERA == 0 && ASSETCHAINS_REWARD[0] == 0 ) - { - cur_money += (nHeight * 10000);// / SATOSHIDEN; - } - else - { - for ( int j = 0; j <= ASSETCHAINS_LASTERA; j++ ) - { - // if any condition means we have no more rewards, break - if (j != 0 && (nHeight <= ASSETCHAINS_ENDSUBSIDY[j - 1] || (ASSETCHAINS_ENDSUBSIDY[j - 1] == 0 && - (ASSETCHAINS_REWARD[j] == 0 && (j == ASSETCHAINS_LASTERA || ASSETCHAINS_DECAY[j] != SATOSHIDEN))))) - break; - - // add rewards from this era, up to nHeight - int64_t reward = ASSETCHAINS_REWARD[j]; - - //fprintf(stderr,"last.%d reward %llu period %llu\n",(int32_t)ASSETCHAINS_LASTERA,(long long)reward,(long long)ASSETCHAINS_HALVING[j]); - if ( reward > 0 ) - { - uint64_t lastEnd = j == 0 ? 0 : ASSETCHAINS_ENDSUBSIDY[j - 1]; - uint64_t curEnd = ASSETCHAINS_ENDSUBSIDY[j] == 0 ? nHeight : nHeight > ASSETCHAINS_ENDSUBSIDY[j] ? ASSETCHAINS_ENDSUBSIDY[j] : nHeight; - uint64_t period = ASSETCHAINS_HALVING[j]; - if ( period == 0 ) - period = 210000; - uint32_t nSteps = (curEnd - lastEnd) / period; - uint32_t modulo = (curEnd - lastEnd) % period; - uint64_t decay = ASSETCHAINS_DECAY[j]; - - //fprintf(stderr,"period.%llu cur_money %.8f += %.8f * %d\n",(long long)period,(double)cur_money/COIN,(double)reward/COIN,nHeight); - if ( ASSETCHAINS_HALVING[j] == 0 ) - { - // no halving, straight multiply - cur_money += reward * (nHeight - 1); - //fprintf(stderr,"cur_money %.8f\n",(double)cur_money/COIN); - } - // if exactly SATOSHIDEN, linear decay to zero or to next era, same as: - // (next_era_reward + (starting reward - next_era_reward) / 2) * num_blocks - else if ( decay == SATOSHIDEN ) - { - int64_t lowestSubsidy, subsidyDifference, stepDifference, stepTriangle; - int64_t denominator, modulo=1; - int32_t sign = 1; - - if ( j == ASSETCHAINS_LASTERA ) - { - subsidyDifference = reward; - lowestSubsidy = 0; - } - else - { - // Ex: -ac_eras=3 -ac_reward=0,384,24 -ac_end=1440,260640,0 -ac_halving=1,1440,2103840 -ac_decay 100000000,97750000,0 - subsidyDifference = reward - ASSETCHAINS_REWARD[j + 1]; - if (subsidyDifference < 0) - { - sign = -1; - subsidyDifference *= sign; - lowestSubsidy = reward; - } - else - { - lowestSubsidy = ASSETCHAINS_REWARD[j + 1]; - } - } - - // if we have not finished the current era, we need to caluclate a total as if we are at the end, with the current - // subsidy. we will calculate the total of a linear era as follows. Each item represents an area calculation: - // a) the rectangle from 0 to the lowest reward in the era * the number of blocks - // b) the rectangle of the remainder of blocks from the lowest point of the era to the highest point of the era if any remainder - // c) the minor triangle from the start of transition from the lowest point to the start of transition to the highest point - // d) one halving triangle (half area of one full step) - // - // we also need: - // e) number of steps = (n - erastart) / halving interval - // - // the total supply from era start up to height is: - // a + b + c + (d * e) - - // calculate amount in one step's triangular protrusion over minor triangle's hypotenuse - denominator = nSteps * period; - if ( denominator == 0 ) - denominator = 1; - // difference of one step vs. total - stepDifference = (period * subsidyDifference) / denominator; - - // area == coin holding of one step triangle, protruding from minor triangle's hypotenuse - stepTriangle = (period * stepDifference) >> 1; - - // sign is negative if slope is positive (start is less than end) - if (sign < 0) - { - // use steps minus one for our calculations, and add the potentially partial rectangle - // at the end - cur_money += stepTriangle * (nSteps - 1); - cur_money += stepTriangle * (nSteps - 1) * (nSteps - 1); - - // difference times number of steps is height of rectangle above lowest subsidy - cur_money += modulo * stepDifference * nSteps; - } - else - { - // if negative slope, the minor triangle is the full number of steps, as the highest - // level step is full. lowest subsidy is just the lowest so far - lowestSubsidy = reward - (stepDifference * nSteps); - - // add the step triangles, one per step - cur_money += stepTriangle * nSteps; - - // add the minor triangle - cur_money += stepTriangle * nSteps * nSteps; - } - - // add more for the base rectangle if lowest subsidy is not 0 - cur_money += lowestSubsidy * (curEnd - lastEnd); - } - else - { - for ( int k = lastEnd; k < curEnd; k += period ) - { - cur_money += period * reward; - // if zero, we do straight halving - reward = decay ? (reward * decay) / SATOSHIDEN : reward >> 1; - } - cur_money += modulo * reward; - } - } - } - } - } - if ( KOMODO_BIT63SET(cur_money) != 0 ) - return(KOMODO_MAXNVALUE); - if ( ASSETCHAINS_COMMISSION != 0 ) +unsigned int WITNESS_CACHE_SIZE = _COINBASE_MATURITY+10; +uint256 KOMODO_EARLYTXID; + +bool KOMODO_LOADINGBLOCKS; // defined in pow.cpp, boolean, 1 if currently loading the block index, 0 if not +bool IS_KOMODO_NOTARY; +bool IS_MODE_EXCHANGEWALLET = false; +bool IS_KOMODO_DEALERNODE; +int32_t KOMODO_MININGTHREADS = -1,STAKED_NOTARY_ID,USE_EXTERNAL_PUBKEY,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_REWIND,STAKED_ERA,KOMODO_CONNECTING = -1,KOMODO_EXTRASATOSHI,ASSETCHAINS_FOUNDERS,ASSETCHAINS_CBMATURITY,KOMODO_NSPV; +int32_t KOMODO_INSYNC,KOMODO_LASTMINED,prevKOMODO_LASTMINED,KOMODO_CCACTIVATE,JUMBLR_PAUSE = 1; +std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY,ASSETCHAINS_SCRIPTPUB,NOTARY_ADDRESS,ASSETCHAINS_SELFIMPORT,ASSETCHAINS_CCLIB; +uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEYHASH[20],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW; +int8_t ASSETCHAINS_ADAPTIVEPOW; +std::vector vWhiteListAddress; +char NOTARYADDRS[64][64]; +char NOTARY_ADDRESSES[NUM_KMD_SEASONS][64][64]; + +char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],ASSETCHAINS_USERPASS[4096]; +uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,ASSETCHAINS_BEAMPORT,ASSETCHAINS_CODAPORT; +uint32_t ASSETCHAIN_INIT,ASSETCHAINS_CC,KOMODO_STOPAT,KOMODO_DPOWCONFS = 1,STAKING_MIN_DIFF; +uint32_t ASSETCHAINS_MAGIC = 2387029918; +int64_t ASSETCHAINS_GENESISTXVAL = 5000000000; + +int64_t MAX_MONEY = 200000000 * 100000000LL; + +// consensus variables for coinbase timelock control and timelock transaction support +// time locks are specified enough to enable their use initially to lock specific coinbase transactions for emission control +// to be verifiable, timelocks require additional data that enables them to be validated and their ownership and +// release time determined from the blockchain. to do this, every time locked output according to this +// spec will use an op_return with CLTV at front and anything after |OP_RETURN|PUSH of rest|OPRETTYPE_TIMELOCK|script| +uint64_t ASSETCHAINS_TIMELOCKGTE = _ASSETCHAINS_TIMELOCKOFF; +uint64_t ASSETCHAINS_TIMEUNLOCKFROM = 0, ASSETCHAINS_TIMEUNLOCKTO = 0; + +uint64_t ASSETCHAINS_LASTERA = 1; +uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_DECAY[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS+1]; +uint8_t ASSETCHAINS_CCDISABLES[256]; +std::vector ASSETCHAINS_PRICES,ASSETCHAINS_STOCKS; + +uint32_t ASSETCHAINS_NUMALGOS = 1; +uint32_t ASSETCHAINS_EQUIHASH = _ASSETCHAINS_EQUIHASH; + +const char *ASSETCHAINS_ALGORITHMS[] = { "equihash" }; +uint64_t ASSETCHAINS_NONCEMASK[] = { 0xffff }; +uint32_t ASSETCHAINS_NONCESHIFT[] = { 32 }; +uint32_t ASSETCHAINS_HASHESPERROUND[] = { 1 }; +// min diff returned from GetNextWorkRequired needs to be added here for each algo, so they can work with ac_staked. +uint32_t ASSETCHAINS_MINDIFF[] = { 537857807 }; // KOMODO_MINDIFF_NBITS = 0x200f0f0f + +uint32_t ASSETCHAINS_ALGO = _ASSETCHAINS_EQUIHASH; + +int32_t ASSETCHAINS_SAPLING = -1; +int32_t ASSETCHAINS_OVERWINTER = -1; + +uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; +int32_t ASSETCHAINS_STAKED; +uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY = 10,ASSETCHAINS_FOUNDERS_REWARD; + +uint32_t KOMODO_INITDONE; +char KMDUSERPASS[8192+512+1],BTCUSERPASS[8192]; uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771, DEST_PORT; +uint64_t PENDING_KOMODO_TX; +unsigned int MAX_BLOCK_SIGOPS = 20000; + +bool IS_KOMODO_TESTNODE; +int32_t KOMODO_SNAPSHOT_INTERVAL; +CScript KOMODO_EARLYTXID_SCRIPTPUB; +int32_t ASSETCHAINS_EARLYTXIDCONTRACT; +int32_t ASSETCHAINS_STAKED_SPLIT_PERCENTAGE; + +std::map mapHeightEvalActivate; + + +/** + * @brief Given a currency name, return the index in the KOMODO_STATES array + * + * @param origbase the currency name to look for + * @return 0 for an asset chain, 1 for KMD, or -1 + */ +int32_t komodo_baseid(const char *origbase) +{ + // convert to upper case + std::string base(origbase); + std::transform(base.begin(),base.end(),base.begin(),[](char s){return toupper(s & 0xff);}); + for(size_t i = 0; i < KOMODO_STATES_NUMBER; ++i) { - uint64_t newval = (cur_money + (cur_money/COIN * ASSETCHAINS_COMMISSION)); - if ( KOMODO_BIT63SET(newval) != 0 ) - return(KOMODO_MAXNVALUE); - else if ( newval < cur_money ) // check for underflow - return(KOMODO_MAXNVALUE); - return(newval); + if (KOMODO_STATES[i].symbol == base) + return i; } - //fprintf(stderr,"cur_money %.8f\n",(double)cur_money/COIN); - return(cur_money); + return -1; } + +// todo remove +//#ifndef SATOSHIDEN +//#define SATOSHIDEN ((uint64_t)100000000L) +//#endif diff --git a/src/komodo_globals.h b/src/komodo_globals.h index ecb85b0d46a..49d9e2fadf6 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * + * Copyright © 2021 Komodo Core Developers * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -15,128 +15,106 @@ #pragma once #include #include "komodo_defs.h" -#include "komodo_hardfork.h" +//#include "komodo_hardfork.h" #include "komodo_structs.h" -void komodo_prefetch(FILE *fp); -uint32_t komodo_heightstamp(int32_t height); -void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t kheight,uint32_t ktime,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth); -int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip); -int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp); -char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port); -int32_t komodo_isrealtime(int32_t *kmdheightp); -uint64_t komodo_paxtotal(); -int32_t komodo_longestchain(); -uint64_t komodo_maxallowed(int32_t baseid); -int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max); -int32_t komodo_checkvout(int32_t vout,int32_t k,int32_t indallvouts); - -std::mutex komodo_mutex; -pthread_mutex_t staked_mutex; - #define KOMODO_ELECTION_GAP 2000 //((ASSETCHAINS_SYMBOL[0] == 0) ? 2000 : 100) #define KOMODO_ASSETCHAIN_MAXLEN 65 -struct pax_transaction *PAX; -int32_t NUM_PRICES; uint32_t *PVALS; -struct knotaries_entry *Pubkeys; - -struct komodo_state KOMODO_STATES[34]; -const uint32_t nStakedDecemberHardforkTimestamp = 1576840000; //December 2019 hardfork 12/20/2019 @ 11:06am (UTC) -const int32_t nDecemberHardforkHeight = 1670000; //December 2019 hardfork - -const uint32_t nS4Timestamp = 1592146800; //dPoW Season 4 2020 hardfork Sunday, June 14th, 2020 03:00:00 PM UTC -const int32_t nS4HardforkHeight = 1922000; //dPoW Season 4 2020 hardfork Sunday, June 14th, 2020 - -const uint32_t nS5Timestamp = 1623682800; //dPoW Season 5 Monday, June 14th, 2021 (03:00:00 PM UTC) -const int32_t nS5HardforkHeight = 2437300; //dPoW Season 5 Monday, June 14th, 2021 - -const uint32_t nS6Timestamp = 1656077853; // dPoW Season 6, Fri Jun 24 2022 13:37:33 GMT+0000 -const int32_t nS6HardforkHeight = 2963330; // dPoW Season 6, Fri Jun 24 2022 +extern char CURRENCIES[][8]; + +//extern int COINBASE_MATURITY; +extern unsigned int WITNESS_CACHE_SIZE; + +extern uint256 KOMODO_EARLYTXID; +extern bool IS_KOMODO_NOTARY; + +extern bool IS_MODE_EXCHANGEWALLET; +extern bool IS_KOMODO_DEALERNODE; + +extern int32_t KOMODO_MININGTHREADS; +extern int32_t STAKED_NOTARY_ID; +extern int32_t USE_EXTERNAL_PUBKEY; +extern int32_t KOMODO_REWIND; +extern int32_t STAKED_ERA; +extern int32_t KOMODO_CONNECTING; +extern int32_t KOMODO_EXTRASATOSHI; +extern int32_t ASSETCHAINS_FOUNDERS; +extern int32_t KOMODO_NSPV; +extern int32_t KOMODO_INSYNC; +extern int32_t KOMODO_LASTMINED; +extern int32_t prevKOMODO_LASTMINED; +extern int32_t KOMODO_CCACTIVATE; +extern int32_t JUMBLR_PAUSE; +extern std::string NOTARY_PUBKEY; +extern std::string ASSETCHAINS_OVERRIDE_PUBKEY; +extern std::string DONATION_PUBKEY; +extern std::string ASSETCHAINS_SCRIPTPUB; +extern std::string NOTARY_ADDRESS; +extern std::string ASSETCHAINS_SELFIMPORT; +extern std::string ASSETCHAINS_CCLIB; +extern uint8_t NOTARY_PUBKEY33[33]; +extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33]; +extern uint8_t ASSETCHAINS_OVERRIDE_PUBKEYHASH[20]; +extern uint8_t ASSETCHAINS_PUBLIC; +extern uint8_t ASSETCHAINS_PRIVATE; +extern uint8_t ASSETCHAINS_TXPOW; +extern int8_t ASSETCHAINS_ADAPTIVEPOW; +extern char ASSETCHAINS_USERPASS[4096]; +extern uint16_t ASSETCHAINS_P2PPORT; +extern uint16_t ASSETCHAINS_RPCPORT; +extern uint16_t ASSETCHAINS_BEAMPORT; +extern uint16_t ASSETCHAINS_CODAPORT; +extern uint32_t ASSETCHAIN_INIT; +extern uint32_t ASSETCHAINS_MAGIC; +extern uint64_t ASSETCHAINS_CBOPRET; +extern uint64_t ASSETCHAINS_LASTERA; +extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS+1]; +extern uint64_t ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS+1]; +extern uint8_t ASSETCHAINS_CCDISABLES[256]; +extern std::vector ASSETCHAINS_PRICES; +extern std::vector ASSETCHAINS_STOCKS; + +extern uint32_t ASSETCHAINS_EQUIHASH; +extern uint32_t ASSETCHAINS_ALGO; +extern int32_t ASSETCHAINS_SAPLING; +extern int32_t ASSETCHAINS_OVERWINTER; +extern int32_t ASSETCHAINS_STAKED; +extern uint64_t ASSETCHAINS_COMMISSION; +extern uint64_t ASSETCHAINS_SUPPLY; +extern uint64_t ASSETCHAINS_FOUNDERS_REWARD; +extern uint32_t KOMODO_INITDONE; +extern char KMDUSERPASS[8192+512+1]; +extern char BTCUSERPASS[8192]; +extern uint16_t KMD_PORT; +extern uint16_t BITCOIND_RPCPORT; +extern uint16_t DEST_PORT; + +extern uint32_t ASSETCHAINS_CC; // set by -ac_cc, normally 0/1 +extern uint32_t KOMODO_STOPAT; // set by -stopat, will not add more blocks after specified height +extern uint32_t KOMODO_DPOWCONFS; // set by -dpowconfs, normally 0/1 +extern uint32_t STAKING_MIN_DIFF; // selected entry from ASSETCHAINS_MINDIFF +extern uint32_t ASSETCHAINS_NUMALGOS; // number of supported hash algos +extern uint32_t ASSETCHAINS_MINDIFF[]; // hash algo dependent +extern uint64_t ASSETCHAINS_TIMELOCKGTE; // set by -ac_timelockgte or consensus +extern uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS+1]; // can be set by -ac_end, array of heights indexed by era +extern uint64_t ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS+1]; // can be set by -ac_halving +extern uint64_t ASSETCHAINS_DECAY[ASSETCHAINS_MAX_ERAS+1]; // can be set by -ac_decay +extern uint64_t KOMODO_INTERESTSUM; // calculated value, returned in getinfo() RPC call +extern uint64_t KOMODO_WALLETBALANCE; // pwalletmain->GetBalance(), returned in getinfo() RPC call +extern int64_t ASSETCHAINS_GENESISTXVAL; // used in calculating money supply +extern int64_t MAX_MONEY; // consensus related sanity check. Not max supply. +extern std::mutex komodo_mutex; // seems to protect PAX values and Pubkey array +//extern std::vector Mineropret; // previous miner values +extern pthread_mutex_t KOMODO_CC_mutex; // mutex to help with CryptoConditions +extern CScript KOMODO_EARLYTXID_SCRIPTPUB; // used mainly in cc/prices.cpp -#define _COINBASE_MATURITY 100 -int COINBASE_MATURITY = _COINBASE_MATURITY;//100; -unsigned int WITNESS_CACHE_SIZE = _COINBASE_MATURITY+10; -uint256 KOMODO_EARLYTXID; -bool IS_KOMODO_NOTARY; -bool IS_MODE_EXCHANGEWALLET = false; -bool IS_KOMODO_DEALERNODE; -int32_t KOMODO_MININGTHREADS = -1,STAKED_NOTARY_ID,USE_EXTERNAL_PUBKEY,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE,KOMODO_PAX,KOMODO_REWIND,STAKED_ERA,KOMODO_CONNECTING = -1,KOMODO_EXTRASATOSHI,ASSETCHAINS_FOUNDERS,ASSETCHAINS_CBMATURITY,KOMODO_NSPV; -int32_t KOMODO_INSYNC,KOMODO_LASTMINED,prevKOMODO_LASTMINED,KOMODO_CCACTIVATE,JUMBLR_PAUSE = 1; -std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY,ASSETCHAINS_SCRIPTPUB,NOTARY_ADDRESS,ASSETCHAINS_SELFIMPORT,ASSETCHAINS_CCLIB; -uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEYHASH[20],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW; -int8_t ASSETCHAINS_ADAPTIVEPOW; -std::vector Mineropret; -std::vector vWhiteListAddress; -char NOTARYADDRS[64][64]; -char NOTARY_ADDRESSES[NUM_KMD_SEASONS][64][64]; - -char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],ASSETCHAINS_USERPASS[4096]; -uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,ASSETCHAINS_BEAMPORT,ASSETCHAINS_CODAPORT; -uint32_t ASSETCHAIN_INIT,ASSETCHAINS_CC,KOMODO_STOPAT,KOMODO_DPOWCONFS = 1,STAKING_MIN_DIFF; -uint32_t ASSETCHAINS_MAGIC = 2387029918; -int64_t ASSETCHAINS_GENESISTXVAL = 5000000000; +#define KOMODO_ELECTION_GAP 2000 //((ASSETCHAINS_SYMBOL[0] == 0) ? 2000 : 100) +#define KOMODO_ASSETCHAIN_MAXLEN 65 -int64_t MAX_MONEY = 200000000 * 100000000LL; +#define _COINBASE_MATURITY 100 // defauly maturity -// consensus variables for coinbase timelock control and timelock transaction support -// time locks are specified enough to enable their use initially to lock specific coinbase transactions for emission control -// to be verifiable, timelocks require additional data that enables them to be validated and their ownership and -// release time determined from the blockchain. to do this, every time locked output according to this -// spec will use an op_return with CLTV at front and anything after |OP_RETURN|PUSH of rest|OPRETTYPE_TIMELOCK|script| #define _ASSETCHAINS_TIMELOCKOFF 0xffffffffffffffff -uint64_t ASSETCHAINS_TIMELOCKGTE = _ASSETCHAINS_TIMELOCKOFF; -uint64_t ASSETCHAINS_TIMEUNLOCKFROM = 0, ASSETCHAINS_TIMEUNLOCKTO = 0,ASSETCHAINS_CBOPRET=0; - -uint64_t ASSETCHAINS_LASTERA = 1; -uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_DECAY[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS+1],ASSETCHAINS_PEGSCCPARAMS[3]; -uint8_t ASSETCHAINS_CCDISABLES[256]; -std::vector ASSETCHAINS_PRICES,ASSETCHAINS_STOCKS; #define _ASSETCHAINS_EQUIHASH 0 - -uint32_t ASSETCHAINS_NUMALGOS = 1; -uint32_t ASSETCHAINS_EQUIHASH = _ASSETCHAINS_EQUIHASH; - -const char *ASSETCHAINS_ALGORITHMS[] = { "equihash" }; -uint64_t ASSETCHAINS_NONCEMASK[] = { 0xffff }; -uint32_t ASSETCHAINS_NONCESHIFT[] = { 32 }; -uint32_t ASSETCHAINS_HASHESPERROUND[] = { 1 }; -// min diff returned from GetNextWorkRequired needs to be added here for each algo, so they can work with ac_staked. -uint32_t ASSETCHAINS_MINDIFF[] = { 537857807 }; // KOMODO_MINDIFF_NBITS = 0x200f0f0f - -uint32_t ASSETCHAINS_ALGO = _ASSETCHAINS_EQUIHASH; - -int32_t ASSETCHAINS_SAPLING = -1; -int32_t ASSETCHAINS_OVERWINTER = -1; - -uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; -int32_t ASSETCHAINS_STAKED; -uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY = 10,ASSETCHAINS_FOUNDERS_REWARD; - -uint32_t KOMODO_INITDONE; -char KMDUSERPASS[8192+512+1],BTCUSERPASS[8192]; uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771, DEST_PORT; -uint64_t PENDING_KOMODO_TX; -extern int32_t KOMODO_LOADINGBLOCKS; // defined in pow.cpp, boolean, 1 if currently loading the block index, 0 if not -unsigned int MAX_BLOCK_SIGOPS = 20000; - -bool IS_KOMODO_TESTNODE; -int32_t KOMODO_SNAPSHOT_INTERVAL; -CScript KOMODO_EARLYTXID_SCRIPTPUB; -int32_t ASSETCHAINS_EARLYTXIDCONTRACT; -int32_t ASSETCHAINS_STAKED_SPLIT_PERCENTAGE; - -std::map mapHeightEvalActivate; - -struct komodo_kv *KOMODO_KV; -pthread_mutex_t KOMODO_KV_mutex,KOMODO_CC_mutex; - -#define MAX_CURRENCIES 32 -char CURRENCIES[][8] = { "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", // major currencies - "CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", - "KMD" }; - -int32_t komodo_baseid(char *origbase); - -uint64_t komodo_current_supply(uint32_t nHeight); diff --git a/src/komodo_hardfork.cpp b/src/komodo_hardfork.cpp new file mode 100644 index 00000000000..14d4818ec96 --- /dev/null +++ b/src/komodo_hardfork.cpp @@ -0,0 +1,554 @@ +#include "komodo_hardfork.h" + +const uint32_t nStakedDecemberHardforkTimestamp = 1576840000; //December 2019 hardfork 12/20/2019 @ 11:06am (UTC) +const int32_t nDecemberHardforkHeight = 1670000; //December 2019 hardfork + +const uint32_t nS4Timestamp = 1592146800; //dPoW Season 4 2020 hardfork Sunday, June 14th, 2020 03:00:00 PM UTC +const int32_t nS4HardforkHeight = 1922000; //dPoW Season 4 2020 hardfork Sunday, June 14th, 2020 + +const uint32_t nS5Timestamp = 1623682800; //dPoW Season 5 Monday, June 14th, 2021 (03:00:00 PM UTC) +const int32_t nS5HardforkHeight = 2437300; //dPoW Season 5 Monday, June 14th, 2021 + +const uint32_t nS6Timestamp = 1656077853; // dPoW Season 6, Fri Jun 24 2022 13:37:33 GMT+0000 +const int32_t nS6HardforkHeight = 2963330; // dPoW Season 6, Fri Jun 24 2022 + +const uint32_t nS7Timestamp = 1688132253; // dPoW Season 7, Fri Jun 30 2023 13:37:33 GMT+0000 +const int32_t nS7HardforkHeight = 3484958; // dPoW Season 7, Fri Jun 30 2023 + +// Era array of pubkeys. Add extra seasons to bottom as requried, after adding appropriate info above. +const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = +{ + { + { "0_jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, + { "0_jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" }, + { "0_kolo_testA", "0287aa4b73988ba26cf6565d815786caf0d2c4af704d7883d163ee89cd9977edec" }, + { "artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, + { "artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, + { "artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, + { "artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, + { "badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, + { "badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, + { "badass_SH", "026b49dd3923b78a592c1b475f208e23698d3f085c4c3b4906a59faf659fd9530b" }, + { "crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, // 10 + { "crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, + { "crackers_SH", "02be28310e6312d1dd44651fd96f6a44ccc269a321f907502aae81d246fabdb03e" }, + { "durerus_EU", "02bcbd287670bdca2c31e5d50130adb5dea1b53198f18abeec7211825f47485d57" }, + { "etszombi_AR", "031c79168d15edabf17d9ec99531ea9baa20039d0cdc14d9525863b83341b210e9" }, + { "etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, // 15 + { "etszombi_SH", "025d7a193c0757f7437fad3431f027e7b5ed6c925b77daba52a8755d24bf682dde" }, + { "farl4web_EU", "0300ecf9121cccf14cf9423e2adb5d98ce0c4e251721fa345dec2e03abeffbab3f" }, + { "farl4web_SH", "0396bb5ed3c57aa1221d7775ae0ff751e4c7dc9be220d0917fa8bbdf670586c030" }, + { "fullmoon_AR", "0254b1d64840ce9ff6bec9dd10e33beb92af5f7cee628f999cb6bc0fea833347cc" }, + { "fullmoon_NA", "031fb362323b06e165231c887836a8faadb96eda88a79ca434e28b3520b47d235b" }, // 20 + { "fullmoon_SH", "030e12b42ec33a80e12e570b6c8274ce664565b5c3da106859e96a7208b93afd0d" }, + { "grewal_NA", "03adc0834c203d172bce814df7c7a5e13dc603105e6b0adabc942d0421aefd2132" }, + { "grewal_SH", "03212a73f5d38a675ee3cdc6e82542a96c38c3d1c79d25a1ed2e42fcf6a8be4e68" }, + { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, + { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + { "jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, + { "jsgalt_NA", "027b3fb6fede798cd17c30dbfb7baf9332b3f8b1c7c513f443070874c410232446" }, + { "karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, // 30 + { "kashifali_EU", "033777c52a0190f261c6f66bd0e2bb299d30f012dcb8bfff384103211edb8bb207" }, + { "kolo_AR", "03016d19344c45341e023b72f9fb6e6152fdcfe105f3b4f50b82a4790ff54e9dc6" }, + { "kolo_SH", "02aa24064500756d9b0959b44d5325f2391d8e95c6127e109184937152c384e185" }, + { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + { "movecrypto_AR", "022783d94518e4dc77cbdf1a97915b29f427d7bc15ea867900a76665d3112be6f3" }, + { "movecrypto_EU", "021ab53bc6cf2c46b8a5456759f9d608966eff87384c2b52c0ac4cc8dd51e9cc42" }, + { "movecrypto_NA", "02efb12f4d78f44b0542d1c60146738e4d5506d27ec98a469142c5c84b29de0a80" }, + { "movecrypto_SH", "031f9739a3ebd6037a967ce1582cde66e79ea9a0551c54731c59c6b80f635bc859" }, + { "muros_AR", "022d77402fd7179335da39479c829be73428b0ef33fb360a4de6890f37c2aa005e" }, + { "noashh_AR", "029d93ef78197dc93892d2a30e5a54865f41e0ca3ab7eb8e3dcbc59c8756b6e355" }, // 40 + { "noashh_EU", "02061c6278b91fd4ac5cab4401100ffa3b2d5a277e8f71db23401cc071b3665546" }, + { "noashh_NA", "033c073366152b6b01535e15dd966a3a8039169584d06e27d92a69889b720d44e1" }, + { "nxtswe_EU", "032fb104e5eaa704a38a52c126af8f67e870d70f82977e5b2f093d5c1c21ae5899" }, + { "polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, + { "pondsea_AR", "032e1c213787312099158f2d74a89e8240a991d162d4ce8017d8504d1d7004f735" }, + { "pondsea_EU", "0225aa6f6f19e543180b31153d9e6d55d41bc7ec2ba191fd29f19a2f973544e29d" }, + { "pondsea_NA", "031bcfdbb62268e2ff8dfffeb9ddff7fe95fca46778c77eebff9c3829dfa1bb411" }, + { "pondsea_SH", "02209073bc0943451498de57f802650311b1f12aa6deffcd893da198a544c04f36" }, + { "popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, + { "popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, // 50 + { "ptytrader_NA", "0328c61467148b207400b23875234f8a825cce65b9c4c9b664f47410b8b8e3c222" }, + { "ptytrader_SH", "0250c93c492d8d5a6b565b90c22bee07c2d8701d6118c6267e99a4efd3c7748fa4" }, + { "rnr_AR", "029bdb08f931c0e98c2c4ba4ef45c8e33a34168cb2e6bf953cef335c359d77bfcd" }, + { "rnr_EU", "03f5c08dadffa0ffcafb8dd7ffc38c22887bd02702a6c9ac3440deddcf2837692b" }, + { "rnr_NA", "02e17c5f8c3c80f584ed343b8dcfa6d710dfef0889ec1e7728ce45ce559347c58c" }, + { "rnr_SH", "037536fb9bdfed10251f71543fb42679e7c52308bcd12146b2568b9a818d8b8377" }, + { "titomane_AR", "03cda6ca5c2d02db201488a54a548dbfc10533bdc275d5ea11928e8d6ab33c2185" }, + { "titomane_EU", "02e41feded94f0cc59f55f82f3c2c005d41da024e9a805b41105207ef89aa4bfbd" }, + { "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" }, + { "vanbreuk_EU", "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" }, // 60 + { "xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, + { "xxspot1_XX", "02ef445a392fcaf3ad4176a5da7f43580e8056594e003eba6559a713711a27f955" }, + { "xxspot2_XX", "03d85b221ea72ebcd25373e7961f4983d12add66a92f899deaf07bab1d8b6f5573" } + }, + { + {"0dev1_jl777", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, + {"0dev2_kolo", "030f34af4b908fb8eb2099accb56b8d157d49f6cfb691baa80fdd34f385efed961" }, + {"0dev3_kolo", "025af9d2b2a05338478159e9ac84543968fd18c45fd9307866b56f33898653b014" }, + {"0dev4_decker", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, + {"a-team_SH", "03b59ad322b17cb94080dc8e6dc10a0a865de6d47c16fb5b1a0b5f77f9507f3cce" }, + {"artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, + {"artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, + {"artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, + {"artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, + {"badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, + {"badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, // 10 + {"batman_AR", "033ecb640ec5852f42be24c3bf33ca123fb32ced134bed6aa2ba249cf31b0f2563" }, + {"batman_SH", "02ca5898931181d0b8aafc75ef56fce9c43656c0b6c9f64306e7c8542f6207018c" }, + {"ca333_EU", "03fc87b8c804f12a6bd18efd43b0ba2828e4e38834f6b44c0bfee19f966a12ba99" }, + {"chainmakers_EU", "02f3b08938a7f8d2609d567aebc4989eeded6e2e880c058fdf092c5da82c3bc5ee" }, + {"chainmakers_NA", "0276c6d1c65abc64c8559710b8aff4b9e33787072d3dda4ec9a47b30da0725f57a" }, + {"chainstrike_SH", "0370bcf10575d8fb0291afad7bf3a76929734f888228bc49e35c5c49b336002153" }, + {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, + {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, + {"crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, + {"crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, // 20 + {"dwy_EU", "0259c646288580221fdf0e92dbeecaee214504fdc8bbdf4a3019d6ec18b7540424" }, + {"emmanux_SH", "033f316114d950497fc1d9348f03770cd420f14f662ab2db6172df44c389a2667a" }, + {"etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, + {"fullmoon_AR", "03380314c4f42fa854df8c471618751879f9e8f0ff5dbabda2bd77d0f96cb35676" }, + {"fullmoon_NA", "030216211d8e2a48bae9e5d7eb3a42ca2b7aae8770979a791f883869aea2fa6eef" }, + {"fullmoon_SH", "03f34282fa57ecc7aba8afaf66c30099b5601e98dcbfd0d8a58c86c20d8b692c64" }, + {"goldenman_EU", "02d6f13a8f745921cdb811e32237bb98950af1a5952be7b3d429abd9152f8e388d" }, + {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, // 30 + {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + {"jackson_AR", "038ff7cfe34cb13b524e0941d5cf710beca2ffb7e05ddf15ced7d4f14fbb0a6f69" }, + {"jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, + {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, + {"komodoninja_EU", "038e567b99806b200b267b27bbca2abf6a3e8576406df5f872e3b38d30843cd5ba" }, + {"komodoninja_SH", "033178586896915e8456ebf407b1915351a617f46984001790f0cce3d6f3ada5c2" }, + {"komodopioneers_SH", "033ace50aedf8df70035b962a805431363a61cc4e69d99d90726a2d48fb195f68c" }, + {"libscott_SH", "03301a8248d41bc5dc926088a8cf31b65e2daf49eed7eb26af4fb03aae19682b95" }, + {"lukechilds_AR", "031aa66313ee024bbee8c17915cf7d105656d0ace5b4a43a3ab5eae1e14ec02696" }, + {"madmax_AR", "03891555b4a4393d655bf76f0ad0fb74e5159a615b6925907678edc2aac5e06a75" }, // 40 + {"meshbits_AR", "02957fd48ae6cb361b8a28cdb1b8ccf5067ff68eb1f90cba7df5f7934ed8eb4b2c" }, + {"meshbits_SH", "025c6e94877515dfd7b05682b9cc2fe4a49e076efe291e54fcec3add78183c1edb" }, + {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, + {"patchkez_SH", "0296270f394140640f8fa15684fc11255371abb6b9f253416ea2734e34607799c4" }, + {"pbca26_NA", "0276aca53a058556c485bbb60bdc54b600efe402a8b97f0341a7c04803ce204cb5" }, + {"peer2cloud_AR", "034e5563cb885999ae1530bd66fab728e580016629e8377579493b386bf6cebb15" }, + {"peer2cloud_SH", "03396ac453b3f23e20f30d4793c5b8ab6ded6993242df4f09fd91eb9a4f8aede84" }, + {"polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, + {"hyper_AR", "020f2f984d522051bd5247b61b080b4374a7ab389d959408313e8062acad3266b4" }, // 50 + {"hyper_EU", "03d00cf9ceace209c59fb013e112a786ad583d7de5ca45b1e0df3b4023bb14bf51" }, + {"hyper_SH", "0383d0b37f59f4ee5e3e98a47e461c861d49d0d90c80e9e16f7e63686a2dc071f3" }, + {"hyper_NA", "03d91c43230336c0d4b769c9c940145a8c53168bf62e34d1bccd7f6cfc7e5592de" }, + {"popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, + {"popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, + {"alien_AR", "0348d9b1fc6acf81290405580f525ee49b4749ed4637b51a28b18caa26543b20f0" }, + {"alien_EU", "020aab8308d4df375a846a9e3b1c7e99597b90497efa021d50bcf1bbba23246527" }, + {"thegaltmines_NA", "031bea28bec98b6380958a493a703ddc3353d7b05eb452109a773eefd15a32e421" }, + {"titomane_AR", "029d19215440d8cb9cc6c6b7a4744ae7fb9fb18d986e371b06aeb34b64845f9325" }, + {"titomane_EU", "0360b4805d885ff596f94312eed3e4e17cb56aa8077c6dd78d905f8de89da9499f" }, // 60 + {"titomane_SH", "03573713c5b20c1e682a2e8c0f8437625b3530f278e705af9b6614de29277a435b" }, + {"webworker01_NA", "03bb7d005e052779b1586f071834c5facbb83470094cff5112f0072b64989f97d7" }, + {"xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, + }, + { + {"madmax_NA", "0237e0d3268cebfa235958808db1efc20cc43b31100813b1f3e15cc5aa647ad2c3" }, // 0 + {"alright_AR", "020566fe2fb3874258b2d3cf1809a5d650e0edc7ba746fa5eec72750c5188c9cc9" }, + {"strob_NA", "0206f7a2e972d9dfef1c424c731503a0a27de1ba7a15a91a362dc7ec0d0fb47685" }, + {"dwy_EU", "021c7cf1f10c4dc39d13451123707ab780a741feedab6ac449766affe37515a29e" }, + {"phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, + {"chainmakers_NA", "02285d813c30c0bf7eefdab1ff0a8ad08a07a0d26d8b95b3943ce814ac8e24d885" }, + {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + {"blackjok3r_SH", "021eac26dbad256cbb6f74d41b10763183ee07fb609dbd03480dd50634170547cc" }, + {"chainmakers_EU", "03fdf5a3fce8db7dee89724e706059c32e5aa3f233a6b6cc256fea337f05e3dbf7" }, + {"titomane_AR", "023e3aa9834c46971ff3e7cb86a200ec9c8074a9566a3ea85d400d5739662ee989" }, + {"fullmoon_SH", "023b7252968ea8a955cd63b9e57dee45a74f2d7ba23b4e0595572138ad1fb42d21" }, // 10 + {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, + {"chmex_EU", "0281304ebbcc39e4f09fda85f4232dd8dacd668e20e5fc11fba6b985186c90086e" }, + {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, + {"ca333_DEV", "02856843af2d9457b5b1c907068bef6077ea0904cc8bd4df1ced013f64bf267958" }, + {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, + {"pungocloud_SH", "024dfc76fa1f19b892be9d06e985d0c411e60dbbeb36bd100af9892a39555018f6" }, + {"voskcoin_EU", "034190b1c062a04124ad15b0fa56dfdf34aa06c164c7163b6aec0d654e5f118afb" }, + {"decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, + {"cryptoeconomy_EU", "0290ab4937e85246e048552df3e9a66cba2c1602db76e03763e16c671e750145d1" }, + {"etszombi_EU", "0293ea48d8841af7a419a24d9da11c34b39127ef041f847651bae6ab14dcd1f6b4" }, // 20 + {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, + {"pirate_AR", "03e29c90354815a750db8ea9cb3c1b9550911bb205f83d0355a061ac47c4cf2fde" }, + {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + {"zatjum_SH", "02d6b0c89cacd58a0af038139a9a90c9e02cd1e33803a1f15fceabea1f7e9c263a" }, + {"madmax_AR", "03c5941fe49d673c094bc8e9bb1a95766b4670c88be76d576e915daf2c30a454d3" }, + {"lukechilds_NA", "03f1051e62c2d280212481c62fe52aab0a5b23c95de5b8e9ad5f80d8af4277a64b" }, + {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, + {"tonyl_AR", "02cc8bc862f2b65ad4f99d5f68d3011c138bf517acdc8d4261166b0be8f64189e1" }, + {"infotech_DEV", "0345ad4ab5254782479f6322c369cec77a7535d2f2162d103d666917d5e4f30c4c" }, + {"fullmoon_NA", "032c716701fe3a6a3f90a97b9d874a9d6eedb066419209eed7060b0cc6b710c60b" }, // 30 + {"etszombi_AR", "02e55e104aa94f70cde68165d7df3e162d4410c76afd4643b161dea044aa6d06ce" }, + {"node-9_EU", "0372e5b51e86e2392bb15039bac0c8f975b852b45028a5e43b324c294e9f12e411" }, + {"phba2061_EU", "03f6bd15dba7e986f0c976ea19d8a9093cb7c989d499f1708a0386c5c5659e6c4e" }, + {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + {"and1-89_EU", "02736cbf8d7b50835afd50a319f162dd4beffe65f2b1dc6b90e64b32c8e7849ddd" }, + {"komodopioneers_SH", "032a238a5747777da7e819cfa3c859f3677a2daf14e4dce50916fc65d00ad9c52a" }, + {"komodopioneers_EU", "036d02425916444fff8cc7203fcbfc155c956dda5ceb647505836bef59885b6866" }, + {"d0ct0r_NA", "0303725d8525b6f969122faf04152653eb4bf34e10de92182263321769c334bf58" }, + {"kolo_DEV", "02849e12199dcc27ba09c3902686d2ad0adcbfcee9d67520e9abbdda045ba83227" }, + {"peer2cloud_AR", "02acc001fe1fe8fd68685ba26c0bc245924cb592e10cec71e9917df98b0e9d7c37" }, // 40 + {"webworker01_SH", "031e50ba6de3c16f99d414bb89866e578d963a54bde7916c810608966fb5700776" }, + {"webworker01_NA", "032735e9cad1bb00eaababfa6d27864fa4c1db0300c85e01e52176be2ca6a243ce" }, + {"pbca26_NA", "03a97606153d52338bcffd1bf19bb69ef8ce5a7cbdc2dbc3ff4f89d91ea6bbb4dc" }, + {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + {"pirate_NA", "0255e32d8a56671dee8aa7f717debb00efa7f0086ee802de0692f2d67ee3ee06ee" }, + {"lukechilds_AR", "025c6a73ff6d750b9ddf6755b390948cffdd00f344a639472d398dd5c6b4735d23" }, + {"dragonhound_NA", "0224a9d951d3a06d8e941cc7362b788bb1237bb0d56cc313e797eb027f37c2d375" }, + {"fullmoon_AR", "03da64dd7cd0db4c123c2f79d548a96095a5a103e5b9d956e9832865818ffa7872" }, + {"chainzilla_SH", "0360804b8817fd25ded6e9c0b50e3b0782ac666545b5416644198e18bc3903d9f9" }, + {"titomane_EU", "03772ac0aad6b0e9feec5e591bff5de6775d6132e888633e73d3ba896bdd8e0afb" }, // 50 + {"jeezy_EU", "037f182facbad35684a6e960699f5da4ba89e99f0d0d62a87e8400dd086c8e5dd7" }, + {"titomane_SH", "03850fdddf2413b51790daf51dd30823addb37313c8854b508ea6228205047ef9b" }, + {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, + {"pirate_EU", "03fff24efd5648870a23badf46e26510e96d9e79ce281b27cfe963993039dd1351" }, + {"thegaltmines_NA", "02db1a16c7043f45d6033ccfbd0a51c2d789b32db428902f98b9e155cf0d7910ed" }, + {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4" }, + {"nutellalicka_SH", "02f7d90d0510c598ce45915e6372a9cd0ba72664cb65ce231f25d526fc3c5479fc" }, + {"chainstrike_SH", "03b806be3bf7a1f2f6290ec5c1ea7d3ea57774dcfcf2129a82b2569e585100e1cb" }, + {"dwy_SH", "036536d2d52d85f630b68b050f29ea1d7f90f3b42c10f8c5cdf3dbe1359af80aff" }, + {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, // 60 + {"gt_AR", "0348430538a4944d3162bb4749d8c5ed51299c2434f3ee69c11a1f7815b3f46135" }, + {"patchkez_SH", "03f45e9beb5c4cd46525db8195eb05c1db84ae7ef3603566b3d775770eba3b96ee" }, + {"decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, // 63 + }, + { + // Season 3.5 + {"madmax_NA", "0237e0d3268cebfa235958808db1efc20cc43b31100813b1f3e15cc5aa647ad2c3" }, // 0 + {"alright_AR", "020566fe2fb3874258b2d3cf1809a5d650e0edc7ba746fa5eec72750c5188c9cc9" }, + {"strob_NA", "0206f7a2e972d9dfef1c424c731503a0a27de1ba7a15a91a362dc7ec0d0fb47685" }, + {"hunter_EU", "0378224b4e9d8a0083ce36f2963ec0a4e231ec06b0c780de108e37f41181a89f6a" }, // FIXME verify this, kolo. Change name if you want + {"phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, + {"chainmakers_NA", "02285d813c30c0bf7eefdab1ff0a8ad08a07a0d26d8b95b3943ce814ac8e24d885" }, + {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + {"blackjok3r_SH", "021eac26dbad256cbb6f74d41b10763183ee07fb609dbd03480dd50634170547cc" }, + {"chainmakers_EU", "03fdf5a3fce8db7dee89724e706059c32e5aa3f233a6b6cc256fea337f05e3dbf7" }, + {"titomane_AR", "023e3aa9834c46971ff3e7cb86a200ec9c8074a9566a3ea85d400d5739662ee989" }, + {"fullmoon_SH", "023b7252968ea8a955cd63b9e57dee45a74f2d7ba23b4e0595572138ad1fb42d21" }, // 10 + {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, + {"chmex_EU", "0281304ebbcc39e4f09fda85f4232dd8dacd668e20e5fc11fba6b985186c90086e" }, + {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, + {"ca333_DEV", "02856843af2d9457b5b1c907068bef6077ea0904cc8bd4df1ced013f64bf267958" }, + {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, + {"pungocloud_SH", "024dfc76fa1f19b892be9d06e985d0c411e60dbbeb36bd100af9892a39555018f6" }, + {"voskcoin_EU", "034190b1c062a04124ad15b0fa56dfdf34aa06c164c7163b6aec0d654e5f118afb" }, + {"decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, + {"cryptoeconomy_EU", "0290ab4937e85246e048552df3e9a66cba2c1602db76e03763e16c671e750145d1" }, + {"etszombi_EU", "0293ea48d8841af7a419a24d9da11c34b39127ef041f847651bae6ab14dcd1f6b4" }, // 20 + {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, + {"pirate_AR", "03e29c90354815a750db8ea9cb3c1b9550911bb205f83d0355a061ac47c4cf2fde" }, + {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + {"zatjum_SH", "02d6b0c89cacd58a0af038139a9a90c9e02cd1e33803a1f15fceabea1f7e9c263a" }, + {"madmax_AR", "03c5941fe49d673c094bc8e9bb1a95766b4670c88be76d576e915daf2c30a454d3" }, + {"lukechilds_NA", "03f1051e62c2d280212481c62fe52aab0a5b23c95de5b8e9ad5f80d8af4277a64b" }, + {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, + {"tonyl_AR", "02cc8bc862f2b65ad4f99d5f68d3011c138bf517acdc8d4261166b0be8f64189e1" }, + {"infotech_DEV", "0345ad4ab5254782479f6322c369cec77a7535d2f2162d103d666917d5e4f30c4c" }, + {"fullmoon_NA", "032c716701fe3a6a3f90a97b9d874a9d6eedb066419209eed7060b0cc6b710c60b" }, // 30 + {"etszombi_AR", "02e55e104aa94f70cde68165d7df3e162d4410c76afd4643b161dea044aa6d06ce" }, + {"node-9_EU", "0372e5b51e86e2392bb15039bac0c8f975b852b45028a5e43b324c294e9f12e411" }, + {"phba2061_EU", "03f6bd15dba7e986f0c976ea19d8a9093cb7c989d499f1708a0386c5c5659e6c4e" }, + {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + {"and1-89_EU", "02736cbf8d7b50835afd50a319f162dd4beffe65f2b1dc6b90e64b32c8e7849ddd" }, + {"komodopioneers_SH", "032a238a5747777da7e819cfa3c859f3677a2daf14e4dce50916fc65d00ad9c52a" }, + {"komodopioneers_EU", "036d02425916444fff8cc7203fcbfc155c956dda5ceb647505836bef59885b6866" }, + {"d0ct0r_NA", "0303725d8525b6f969122faf04152653eb4bf34e10de92182263321769c334bf58" }, + {"kolo_DEV", "02849e12199dcc27ba09c3902686d2ad0adcbfcee9d67520e9abbdda045ba83227" }, + {"peer2cloud_AR", "02acc001fe1fe8fd68685ba26c0bc245924cb592e10cec71e9917df98b0e9d7c37" }, // 40 + {"webworker01_SH", "031e50ba6de3c16f99d414bb89866e578d963a54bde7916c810608966fb5700776" }, + {"webworker01_NA", "032735e9cad1bb00eaababfa6d27864fa4c1db0300c85e01e52176be2ca6a243ce" }, + {"pbca26_NA", "03a97606153d52338bcffd1bf19bb69ef8ce5a7cbdc2dbc3ff4f89d91ea6bbb4dc" }, + {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + {"pirate_NA", "0255e32d8a56671dee8aa7f717debb00efa7f0086ee802de0692f2d67ee3ee06ee" }, + {"lukechilds_AR", "025c6a73ff6d750b9ddf6755b390948cffdd00f344a639472d398dd5c6b4735d23" }, + {"dragonhound_NA", "0224a9d951d3a06d8e941cc7362b788bb1237bb0d56cc313e797eb027f37c2d375" }, + {"fullmoon_AR", "03da64dd7cd0db4c123c2f79d548a96095a5a103e5b9d956e9832865818ffa7872" }, + {"chainzilla_SH", "0360804b8817fd25ded6e9c0b50e3b0782ac666545b5416644198e18bc3903d9f9" }, + {"titomane_EU", "03772ac0aad6b0e9feec5e591bff5de6775d6132e888633e73d3ba896bdd8e0afb" }, // 50 + {"jeezy_EU", "037f182facbad35684a6e960699f5da4ba89e99f0d0d62a87e8400dd086c8e5dd7" }, + {"titomane_SH", "03850fdddf2413b51790daf51dd30823addb37313c8854b508ea6228205047ef9b" }, + {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, + {"pirate_EU", "03fff24efd5648870a23badf46e26510e96d9e79ce281b27cfe963993039dd1351" }, + {"thegaltmines_NA", "02db1a16c7043f45d6033ccfbd0a51c2d789b32db428902f98b9e155cf0d7910ed" }, + {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4" }, + {"nutellalicka_SH", "02f7d90d0510c598ce45915e6372a9cd0ba72664cb65ce231f25d526fc3c5479fc" }, + {"chainstrike_SH", "03b806be3bf7a1f2f6290ec5c1ea7d3ea57774dcfcf2129a82b2569e585100e1cb" }, + {"hunter_SH", "02407db70ad30ce4dfaee8b4ae35fae88390cad2b0ba0373fdd6231967537ccfdf" }, + {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, // 60 + {"gt_AR", "0348430538a4944d3162bb4749d8c5ed51299c2434f3ee69c11a1f7815b3f46135" }, + {"patchkez_SH", "03f45e9beb5c4cd46525db8195eb05c1db84ae7ef3603566b3d775770eba3b96ee" }, + {"decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, // 63 + }, + { + // Season 4 + { "alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, + { "alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, + { "strob_NA", "02a1c0bd40b294f06d3e44a52d1b2746c260c475c725e9351f1312e49e01c9a405" }, + { "titomane_SH", "020014ad4eedf6b1aeb0ad3b101a58d0a2fc570719e46530fd98d4e585f63eb4ae" }, + { "fullmoon_AR", "03b251095e747f759505ec745a4bbff9a768b8dce1f65137300b7c21efec01a07a" }, + { "phba2061_EU", "03a9492d2a1601d0d98cfe94d8adf9689d1bb0e600088127a4f6ca937761fb1c66" }, + { "fullmoon_NA", "03931c1d654a99658998ce0ddae108d825943a821d1cddd85e948ac1d483f68fb6" }, + { "fullmoon_SH", "03c2a1ed9ddb7bb8344328946017b9d8d1357b898957dd6aaa8c190ae26740b9ff" }, + { "madmax_AR", "022be5a2829fa0291f9a51ff7aeceef702eef581f2611887c195e29da49092e6de" }, + { "titomane_EU", "0285cf1fdba761daf6f1f611c32d319cd58214972ef822793008b69dde239443dd" }, + { "cipi_NA", "022c6825a24792cc3b010b1531521eba9b5e2662d640ed700fd96167df37e75239" }, + { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + { "decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, + { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + { "madmax_NA", "02997b7ab21b86bbea558ae79acc35d62c9cedf441578f78112f986d72e8eece08" }, + { "chainzilla_SH", "02288ba6dc57936b59d60345e397d62f5d7e7d975f34ed5c2f2e23288325661563" }, + { "peer2cloud_AR", "0250e7e43a3535731b051d1bcc7dc88fbb5163c3fe41c5dee72bd973bcc4dca9f2" }, + { "pirate_EU", "0231c0f50a06655c3d2edf8d7e722d290195d49c78d50de7786b9d196e8820c848" }, + { "webworker01_NA", "02dfd5f3cef1142879a7250752feb91ddd722c497fb98c7377c0fcc5ccc201bd55" }, + { "zatjum_SH", "036066fd638b10e555597623e97e032b28b4d1fa5a13c2b0c80c420dbddad236c2" }, + { "titomane_AR", "0268203a4c80047edcd66385c22e764ea5fb8bc42edae389a438156e7dca9a8251" }, + { "chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d" }, + { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, + { "patchkez_SH", "02cabd6c5fc0b5476c7a01e9d7b907e9f0a051d7f4f731959955d3f6b18ee9a242" }, + { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + { "etszombi_EU", "0341adbf238f33a33cc895633db996c3ad01275313ac6641e046a3db0b27f1c880" }, + { "pirate_NA", "02207f27a13625a0b8caef6a7bb9de613ff16e4a5f232da8d7c235c7c5bad72ffe" }, + { "metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, + { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + { "chainmakers_NA", "029415a1609c33dfe4a1016877ba35f9265d25d737649f307048efe96e76512877" }, + { "mihailo_EU", "037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941" }, + { "tonyl_AR", "0299684d7291abf90975fa493bf53212cf1456c374aa36f83cc94daece89350ae9" }, + { "alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8" }, + { "pungocloud_SH", "025b97d8c23effaca6fa7efacce20bf54df73081b63004a0fe22f3f98fece5669f" }, + { "node9_EU", "029ffa793b5c3248f8ea3da47fa3cf1810dada5af032ecd0e37bab5b92dd63b34e" }, + { "smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac" }, + { "nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b" }, + { "gcharang_SH", "02ec4172eab854a0d8cd32bc691c83e93975a3df5a4a453a866736c56e025dc359" }, + { "cipi_EU", "02f2b6defff1c544202f66e47cfd6909c54d67c7c39b9c2a99f137dbaf6d0bd8fa" }, + { "etszombi_AR", "0329944b0ac65b6760787ede042a2fde0be9fca1d80dd756bc0ee0b98d389b7682" }, + { "pbca26_NA", "0387e0fb6f2ca951154c87e16c6cbf93a69862bb165c1a96bcd8722b3af24fe533" }, + { "mylo_SH", "03b58f57822e90fe105e6efb63fd8666033ea503d6cc165b1e479bbd8c2ba033e8" }, + { "swisscertifiers_EU", "03ebcc71b42d88994b8b2134bcde6cb269bd7e71a9dd7616371d9294ec1c1902c5" }, + { "marmarachain_AR", "035bbd81a098172592fe97f50a0ce13cbbf80e55cc7862eccdbd7310fab8a90c4c" }, + { "karasugoi_NA", "0262cf2559703464151153c12e00c4b67a969e39b330301fdcaa6667d7eb02c57d" }, + { "phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, + { "oszy_EU", "03d1ffd680491b98a3ec5541715681d1a45293c8efb1722c32392a1d792622596a" }, + { "chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005" }, + { "dragonhound_NA", "0227e5cad3731e381df157de189527aac8eb50d82a13ce2bd81153984ebc749515" }, + { "strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a" }, + { "madmax_EU", "02ea0cf4d6d151d0528b07efa79cc7403d77cb9195e2e6c8374f5074b9a787e287" }, + { "dudezmobi_AR", "027ecd974ff2a27a37ee69956cd2e6bb31a608116206f3e31ef186823420182450" }, + { "daemonfox_NA", "022d6f4885f53cbd668ad7d03d4f8e830c233f74e3a918da1ed247edfc71820b3d" }, + { "nutellalicka_SH", "02f4b1e71bc865a79c05fe333952b97cb040d8925d13e83925e170188b3011269b" }, + { "starfleet_EU", "025c7275bd750936862b47793f1f0bb3cbed60fb75a48e7da016e557925fe375eb" }, + { "mrlynch_AR", "031987dc82b087cd53e23df5480e265a5928e9243e0e11849fa12359739d8b18a4" }, + { "greer_NA", "03e0995615d7d3cf1107effa6bdb1133e0876cf1768e923aa533a4e2ee675ec383" }, + { "mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043" }, + { "decker_EU", "03777777caebce56e17ca3aae4e16374335b156f1dd62ee3c7f8799c6b885f5560" }, + { "dappvader_SH", "02962e2e5af746632016bc7b24d444f7c90141a5f42ce54e361b302cf455d90e6a" }, + { "alright_DEV", "02b73a589d61691efa2ada15c006d27bc18493fea867ce6c14db3d3d28751f8ce3" }, + { "artemii235_DEV", "03bb616b12430bdd0483653de18733597a4fd416623c7065c0e21fe9d96460add1" }, + { "tonyl_DEV", "02d5f7fd6e25d34ab2f3318d60cdb89ff3a812ec5d0212c4c113bb12d12616cfdc" }, + { "decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" } + }, + { + // Season 5 + {"alrighttt_DEV", "03483166d8663beeb48a493eec161bf506df1906153b6259f7ca617e4cb8110260"}, // 0 + {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f"}, + {"artempikulin_AR", "026a8ed1e4eeeb023cfb8e003e1c1de6a2b771f37e112745ffb8b6e375a9cbfdec"}, + {"chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005"}, + {"cipi_AR", "033ae024cdb748e083406a2e20037017a1292079ad6a8161ae5b43f398724fea74"}, + {"shadowbit_AR", "02909c79a198179c193fb85bbd4ba09b875a5a9bd481fec284658188b96ed43519"}, + {"goldenman_AR", "0345b888e5de9c11871c080212ccaebf8a3d77b05fe3d535336efc5c7df334bbc7"}, + {"kolo_AR", "0281d3c7bf067088b9572b4d906afca2083a71a38b1011878ecd347651d00af433"}, + {"madmax_AR", "02f729b8df4dacdc8d811416eb32e98a5cc37023b42c81b77d1c00881de879a99a"}, + {"mcrypt_AR", "029bdb33b08f96524082490f4373bc6026b92bcaef9bc521a840a799c73b75ed80"}, + {"mrlynch_AR", "031987dc82b087cd53e23df5480e265a5928e9243e0e11849fa12359739d8b18a4"}, // 10 + {"ocean_AR", "03c2bc8c57a001a788851fedc33ce72797ee8fe26eaa3abb1b807727e4867a3105"}, + {"smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac"}, + {"tokel_AR", "03f3bf697173e47de7bae2ae02b3d3bcf28133a47db72f2a0266061597aaa7779d"}, + {"tonyl_AR", "029ad03929ec295e9164e2bfb9f0e0102c280d5e5212503d079d2d99ab492a9106"}, + {"tonyl_DEV", "02342ec82b31a016b71cd1eb2f482a74f63172e1029ba2fb18f0def3bd4fc0668a"}, + {"artem_DEV", "036b9848396ddcdb9bb58ddab2c24b710b8e4e9b0ee084a00518505ecd9e9fe174"}, + {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd"}, + {"alienx_EU", "026afe5b112d1b39e0edafd5e051e261a676104460581f3673f26ceff7f1e6c56c"}, + {"ca333_EU", "03ffb8072f78304c42ae9b60435f6c3296cbc72de129ae49bba175a65c31c9a7e2"}, + {"chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d"}, // 20 + {"cipi_EU", "03d6e1f3a693b5d69049791005d7cb64c259a1ad85833f5a9c545d4fee29905009"}, + {"cipi2_EU", "0202e430157486503f4bde3d3ca770c8f1e2447cf480a6b273b5265b9620f585e3"}, + {"shadowbit_EU", "02668f5f723584f97f5e6f9196fc31018f36a6cf824c60328ad0c097a785df4745"}, + {"komodopioneers_EU", "0351f7f2a6ecce863e4e774bfafe2e59e151c08bf8f350286763a6b8ed97274b82"}, + {"madmax_EU", "028d04f7ccae0d9d57bfa801c4f1e32c707c17589b3c08a0ce08d44eab637eb66b"}, + {"marmarachain_EU", "023a858bbc3f0c6df5b74243315028e968c2f299d84ea8ecc0b28b5f0e2ad24c3c"}, + {"node-9_EU", "03c375924aac39d0c49de6690199e4d08d10fed6725988dcf5d2486661b5e3a656"}, + {"slyris_EU", "021cb6365c13cb35aad4b70aa18b63a75d1d4b9797a0754d3d0142d6fedc83b24e"}, + {"smdmitry_EU", "02eb3aad81778f8d6f7e5295c44ca224e5c812f5e43fc1e9ce4ebafc23324183c9"}, + {"van_EU", "03af7f8c82f20671ca1978116353839d3e501523e379bfb52b1e05d7816bb5812f"}, // 30 + {"shadowbit_DEV", "02ca882f153e715091a2dbc5409096f8c109d9fe6506ca7a918056dd37162b6f6e"}, + {"gcharang_DEV", "02cb445948bf0d89f8d61102e12a5ee6e98be61ac7c2cb9ba435219ea9db967117"}, + {"alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8"}, + {"alienx_NA", "02f0b3ef87629509441b1ae95f28108f258a81910e483b90e0496205e24e7069b8"}, + {"cipi_NA", "036cc1d7476e4260601927be0fc8b748ae68d8fec8f5c498f71569a01bd92046c5"}, + {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4"}, + {"dragonhound_NA", "02e650819f4d1cabeaad6bc5ec8c0722a89e63059a10f8b5e97c983c321608329b"}, + {"hyper_NA", "030994a303b26df6e7c6ed456f069c5de9e200e1380bebc5ed8ebe0f834f477f3d"}, + {"madmax_NA", "03898aec46014e8619e2369cc85073048dad05d3c5bf696d8b524db78a39ae5beb"}, + {"node-9_NA", "02f697eed99fd21f2f0eaad81d13543a75c576f669bfddbcbeef0f7625fea2e9d5"}, // 40 + {"nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b"}, + {"pbca26_NA", "0332543ff1287604afd67f63af0aa0b263aef14fe1850b85db16b81462eed834fd"}, + {"ptyx_NA", "02cbda9c43a794f2134a11815fe86dca017990269accb139e962d764c011c9a4d7"}, + {"strob_NA", "02a1c0bd40b294f06d3e44a52d1b2746c260c475c725e9351f1312e49e01c9a405"}, + {"karasugoi_NA", "0262cf2559703464151153c12e00c4b67a969e39b330301fdcaa6667d7eb02c57d"}, + {"webworker01_NA", "0376558d13c31cf9c664a1b5e58f4fff7153777069bef7a66ed8c8526b99787a9e"}, + {"yurii_DEV", "03e57c7341d2c8a3be62e1caaa28978d76a8277dea7bb484fdd8c55dc05e4e4e93"}, + {"ca333_DEV", "03d885e292842912bd990299ebce33451a5a01cb14e4874d90770efb22e82ef40f"}, + {"chmex_SH", "02698305eb3c27a2c724efd2152f9250739355116f201656c34b83aac2d3aebd19"}, + {"collider_SH", "03bd0022a55a2ead52fd65b317186743374ad320f3704d459f41797e264d1ec854"}, // 50 + {"dappvader_SH", "02bffea7911e09ad9a7df54af0c225516478d3ba138e65061aa8d4b9756bb4c8f4"}, + {"drkush_SH", "030b31cc9528566422e25f3e9b96541ab3626c0dea0e7aa3c0b0bd96039eae2f5a"}, + {"majora31_SH", "033bf21f039a1c832effad208d564e02e968f11e3a3aa41c42e3b748a232fb33f3"}, + {"mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043"}, + {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309"}, + {"mylo_SH", "03458dca36e800d5bc121d8c0d35f9fc6282880a79fee2d7e050f887b797bc7d6e"}, + {"nutellaLicka_SH", "03a495962a9e9eca06ee3b8ab4cd94e6ea0d87dd39d334ad85a524c4fece1a3db7"}, + {"pbca26_SH", "02c62877e96fc414f2444edf0601abff9d5d2f9078e49fa867ba5305f3c5b3beb0"}, + {"phit_SH", "02a9cef2141fb2af24349c1eea20f5fa8f5dba2835723778d19b23353ddcd877b1"}, + {"sheeba_SH", "03e6578015b7f0ab78a486070435031fff7bae11256ca6a9f3d358ab03029737cb"}, // 60 + {"strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a"}, + {"strobnidan_SH", "02b967fde3686d45056343e488997d4c53f25cd7ad38548cd12b136010a09295ae"}, + {"dragonhound_DEV", "038e010c33c56b61389409eea5597fe17967398731e23185c84c472a16fc5d34ab"} + }, + { + // Season 6 + {"blackice_DEV", "02ca882f153e715091a2dbc5409096f8c109d9fe6506ca7a918056dd37162b6f6e"}, // 0 + {"blackice_AR", "02909c79a198179c193fb85bbd4ba09b875a5a9bd481fec284658188b96ed43519"}, + {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd"}, + {"alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8"}, + {"alien_SH", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f"}, + {"alienx_EU", "026afe5b112d1b39e0edafd5e051e261a676104460581f3673f26ceff7f1e6c56c"}, + {"alienx_NA", "02f0b3ef87629509441b1ae95f28108f258a81910e483b90e0496205e24e7069b8"}, + {"artem.pikulin_AR", "026a8ed1e4eeeb023cfb8e003e1c1de6a2b771f37e112745ffb8b6e375a9cbfdec"}, + {"artem.pikulin_DEV", "036b9848396ddcdb9bb58ddab2c24b710b8e4e9b0ee084a00518505ecd9e9fe174"}, + {"blackice_EU", "02668f5f723584f97f5e6f9196fc31018f36a6cf824c60328ad0c097a785df4745"}, + {"chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005"}, // 10 + {"chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d"}, + {"chmex_NA", "030c2528c29d5328243c910277e3d74aa77c9b4e145308007d2b11550731591dbe"}, + {"chmex_SH", "02698305eb3c27a2c724efd2152f9250739355116f201656c34b83aac2d3aebd19"}, + {"chmex1_SH", "02d27ed1cddfbaff9e47865e7df0165457e8f075f70bbea8c0498598ccf494555d"}, + {"cipi_1_EU", "03d6e1f3a693b5d69049791005d7cb64c259a1ad85833f5a9c545d4fee29905009"}, + {"cipi_2_EU", "0202e430157486503f4bde3d3ca770c8f1e2447cf480a6b273b5265b9620f585e3"}, + {"cipi_AR", "033ae024cdb748e083406a2e20037017a1292079ad6a8161ae5b43f398724fea74"}, + {"cipi_NA", "036cc1d7476e4260601927be0fc8b748ae68d8fec8f5c498f71569a01bd92046c5"}, + {"computergenie_EU", "03a8c071036228e0900e0171f616ce1a58f0a761193551d68c4c20e70534f2e183"}, + {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4"}, // 20 + {"dimxy_AR", "02689d0b77b1e8e8c93a102d8b689fd08179164d70e2dd585543c3896a0916e6a1"}, + {"dimxy_DEV", "039a01cd626d5efbe7fd05a59d8e5fced53bacac589192278f9b00ad31654b6956"}, + {"dragonhound_NA", "02e650819f4d1cabeaad6bc5ec8c0722a89e63059a10f8b5e97c983c321608329b"}, + {"fediakash_AR", "027dfe5403f8870fb0e1b94a2b4204373b31ea73179ba500a88dd56d22855cd03b"}, + {"gcharang_DEV", "033b82b5791c65477dd11095cf33332013df6d2bcb7aa06a6dae5f7b22b6959b0b"}, + {"gcharang_SH", "02cb445948bf0d89f8d61102e12a5ee6e98be61ac7c2cb9ba435219ea9db967117"}, + {"goldenman_AR", "02c11f651df6a03f1a17b9ea0b1a73c0acca7aeacd4081e09bd7dd939690af8ae1"}, + {"kolo_AR", "028431645f923a9e383a4e37cbb7168fa34988da23d43097124fe882bdac6d175f"}, + {"kolo_EU", "03e1287d4c14ad73ce9ddd31361a7de8df4eeeefe9460a1ff9a6b2a1242ad3b7c2"}, + {"kolox_AR", "0289f5f64f4bb18d014c4e9f4c888f4da2b6518e88fd5b7768728c38177b66d305"}, // 30 + {"komodopioneers_EU", "0351f7f2a6ecce863e4e774bfafe2e59e151c08bf8f350286763a6b8ed97274b82"}, + {"madmax_DEV", "027100e6b3db2028034db651946ecde90e45be3799ebc310d39af4496772a850ad"}, + {"marmarachain_EU", "0234e40800500370d43979586ee2cec2e777a0368d10c682e78bca30fd1630c18d"}, + {"mcrypt_AR", "029bdb33b08f96524082490f4373bc6026b92bcaef9bc521a840a799c73b75ed80"}, + {"mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043"}, + {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309"}, + {"mylo_NA", "0365a778014c216401b6ba9c28eec88f116a9a9912e145ba2dbbd065d98b493af5"}, + {"mylo_SH", "03458dca36e800d5bc121d8c0d35f9fc6282880a79fee2d7e050f887b797bc7d6e"}, + {"nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b"}, + {"nutellalicka_AR", "0285be2518bf8d65fceaa5f4d8485002f90d3b7ff274b23bb925fd167128e19589"}, // 40 + {"nutellalicka_SH", "03a8b10c1f74af429fc43ab4eb722f6c2a88087f2d71703e7f0e8001207a966fb5"}, + {"ocean_AR", "03c2bc8c57a001a788851fedc33ce72797ee8fe26eaa3abb1b807727e4867a3105"}, + {"pbca26_NA", "03d8b25536da157d931b159a72c0eeaedb1bf7bb3eb2d02647fa41b2422a2b064e"}, + {"pbca26_SH", "039a55787b742c3725323f0bd81c90a484fbdbf276a16317883bb03eedd9d6aa7c"}, + {"phit_SH", "02a9cef2141fb2af24349c1eea20f5fa8f5dba2835723778d19b23353ddcd877b1"}, + {"ptyx_NA", "0395640e81359526ecbc140716ddd5c9a1ce2a697fb547ca896e17cad3c65e78db"}, + {"ptyx2_NA", "0225ff37e49e443065018736fbcad175ab5993b51b99b846e8de0b8b9abbed2ef2"}, + {"sheeba_SH", "03e6578015b7f0ab78a486070435031fff7bae11256ca6a9f3d358ab03029737cb"}, + {"smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac"}, + {"smdmitry_EU", "02eb3aad81778f8d6f7e5295c44ca224e5c812f5e43fc1e9ce4ebafc23324183c9"}, // 50 + {"smdmitry_SH", "02d01cd6b87cbf5a9795c06968f0d169168c1be0d82cfeb79958b11ae2c30316c1"}, + {"strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a"}, + {"strobnidan_SH", "02b967fde3686d45056343e488997d4c53f25cd7ad38548cd12b136010a09295ae"}, + {"tokel_NA", "02b472713e87fb2560569857051ea0811c65d668a6fe73df165afe152417f774a0"}, + {"tonyl_AR", "029ad03929ec295e9164e2bfb9f0e0102c280d5e5212503d079d2d99ab492a9106"}, + {"tonyl_DEV", "02342ec82b31a016b71cd1eb2f482a74f63172e1029ba2fb18f0def3bd4fc0668a"}, + {"van_EU", "03af7f8c82f20671ca1978116353839d3e501523e379bfb52b1e05d7816bb5812f"}, + {"webworker01_EU", "0321d523645caffd8e762764ba56f7874a61b9bf534837a2cb6e7da219fab15eef"}, + {"webworker01_NA", "0287883ddd8da366401893ebcc1ff7e52d2ad3736984120a0ab01603e02c21dc98"}, + {"who-biz_NA", "02f91a6772fe1a376e2bbe4b190008e3f878d40a8eaf92c65f1a7680b6b42ea47b"}, // 60 + {"yurii-khi_DEV", "03e57c7341d2c8a3be62e1caaa28978d76a8277dea7bb484fdd8c55dc05e4e4e93"}, + {"ca333_EU", "021d6fbe67d12f492a01306c70ab096f8b8581eb5f958d3f5fe3588ae8c7797f42"}, + {"dragonhound_DEV", "038e010c33c56b61389409eea5597fe17967398731e23185c84c472a16fc5d34ab"} + }, + { + // Season 7 + {"blackice_DEV", "03955c7999538cee313bf196a7df59db208c651f6a5a1b0eed94732ba753b4f3f4"}, // 0 + {"blackice_AR", "02bbc5518d27918d77c46b4e3ad0b9df936df520646527ab4c2f206544a2b03967"}, + {"blackice_EU", "02340bf4749a392865b0ddaf37e652195e740c7538aeac87f7a51b8bf2dcdc24ac"}, + {"blackice_NA", "035baa12331ad6c284d5f1b76527c1d6c5eb15a74b9ba369e5d46aefcc9c120938"}, + {"alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8"}, + {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd"}, + {"alien_SH", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f"}, + {"alienx_NA", "02f0b3ef87629509441b1ae95f28108f258a81910e483b90e0496205e24e7069b8"}, + {"alright_EU", "0364f2beba6a91ca88a92e8bf709dc21b444587183256f651a30ad1b932242d4db"}, + {"alright_DEV", "028548847b3bbccff37c9b47bc4154183304902773d514b792ec2adc91e600e3b9"}, + {"artem.pikulin_AR", "026a8ed1e4eeeb023cfb8e003e1c1de6a2b771f37e112745ffb8b6e375a9cbfdec"}, // 10 + {"batman_AR", "02cc9eb0281628256a743570c57b2cedd54333ec79a97a681207b240cab84119fe"}, + {"blackice2_AR", "03d224790d17b881db560759cc9cc73fe5c865136a88af471ea156b7eb6d88ce32"}, + {"ca333_EU", "0335492a24c73844b29b8c724e709b8082424e6296baa1fab4ef86c73f233ccf27"}, + {"caglarkaya_EU", "035667a7e5594095f7b3d392e61da8dd7d0dda610bf8731e7831993a8201d1feea"}, + {"chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005"}, + {"chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d"}, + {"chmex_NA", "030c2528c29d5328243c910277e3d74aa77c9b4e145308007d2b11550731591dbe"}, + {"chmex_SH", "02698305eb3c27a2c724efd2152f9250739355116f201656c34b83aac2d3aebd19"}, + {"chmex2_SH", "02d27ed1cddfbaff9e47865e7df0165457e8f075f70bbea8c0498598ccf494555d"}, + {"cipi_AR", "033ae024cdb748e083406a2e20037017a1292079ad6a8161ae5b43f398724fea74"}, // 20 + {"cipi_EU", "03d6e1f3a693b5d69049791005d7cb64c259a1ad85833f5a9c545d4fee29905009"}, + {"cipi_NA", "036cc1d7476e4260601927be0fc8b748ae68d8fec8f5c498f71569a01bd92046c5"}, + {"colmapol_EU", "020c63078b5f5d27183de6f2bbae9bfe3fc57e017faf89b7d566bb947a92a2e40d"}, + {"computergenie_EU", "03a8c071036228e0900e0171f616ce1a58f0a761193551d68c4c20e70534f2e183"}, + {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4"}, + {"computergenie2_NA", "03e1472f963ba84f3d797015811efbb7ded58cb0de69da463367f4e3281b259fc8"}, + {"dimxy_AR", "02689d0b77b1e8e8c93a102d8b689fd08179164d70e2dd585543c3896a0916e6a1"}, + {"dimxy_DEV", "039a01cd626d5efbe7fd05a59d8e5fced53bacac589192278f9b00ad31654b6956"}, + {"emmaccen_DEV", "02e3672b0ebcc9a524508651cf91c8752880ac2fff760d9373ddab59702b933058"}, + {"fediakash_AR", "027dfe5403f8870fb0e1b94a2b4204373b31ea73179ba500a88dd56d22855cd03b"}, // 30 + {"gcharang_AR", "030de3d833ba049da08231ca6b622c77c7f96b26269963291d9604706bb94031a5"}, + {"gcharang_SH", "02cb445948bf0d89f8d61102e12a5ee6e98be61ac7c2cb9ba435219ea9db967117"}, + {"gcharang_DEV", "033b82b5791c65477dd11095cf33332013df6d2bcb7aa06a6dae5f7b22b6959b0b"}, + {"kmdude_SH", "02116774b25226d0b99f70a24f55c5ce17a7af6d3522071369c233157ecb27b82a"}, + {"marmara_AR", "0335ab9e59d602df5580b964b6451d02cd9cc243ddf01b065db84375488df9f53c"}, + {"marmara_EU", "0234e40800500370d43979586ee2cec2e777a0368d10c682e78bca30fd1630c18d"}, + {"mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043"}, + {"nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b"}, + {"nodeone2_NA", "0397fa321960fda64b86330efaefeba56a7ab0ff4b7f82869b0115ad8bc1c432b0"}, + {"ozkanonur_NA", "02be4ac61cf534b0fb98568ec539ee9e34c5104088f94f21cee2945d37d88373da"}, // 40 + {"pbca26_NA", "021e362556ab07d4f1f75a0adce9709ad87ce1a51da679947b0ad4a6b651e9769b"}, + {"pbca26_SH", "035a9784047f030e00d886dd91c07c82846702595650a2f1de67a8d85dc077d712"}, + {"phit_SH", "02a9cef2141fb2af24349c1eea20f5fa8f5dba2835723778d19b23353ddcd877b1"}, + {"ptyx_SH", "0270dbba1449ab2e76109b147cbbea794f103a625d14743bf9e2aaa74f98e6787f"}, + {"shamardy_SH", "026d378de09ba51d8f56be52bc8d02f5e20bae843406e23686047b76c72412a7b3"}, + {"sheeba_SH", "03e6578015b7f0ab78a486070435031fff7bae11256ca6a9f3d358ab03029737cb"}, + {"sheeba2_SH", "02f016347d952a06f1121bc9445b162d0ba921c7317f6b60211179c1cddef0db57"}, + {"smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac"}, + {"smdmitry_EU", "02eb3aad81778f8d6f7e5295c44ca224e5c812f5e43fc1e9ce4ebafc23324183c9"}, + {"smdmitry_SH", "02d01cd6b87cbf5a9795c06968f0d169168c1be0d82cfeb79958b11ae2c30316c1"}, // 50 + {"smdmitry2_AR", "026e33b213be94fa7c05c781cb1d2fb381e4c4ef6aad40d6a67f0a8ad573d92efe"}, + {"strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a"}, + {"tonyl_AR", "02b10141bf59b192c97f08273547d0cebff7466e8865a09f0da082e52b62de3866"}, + {"tonyl_DEV", "02f92a2592bd791fc09c030401b7d12016a4f878d7bfae6d58e547cf42c717a79a"}, + {"van_EU", "03af7f8c82f20671ca1978116353839d3e501523e379bfb52b1e05d7816bb5812f"}, + {"webworker01_EU", "02ad970d95fdaa296a0ab13b5733216e116030d9147ff33de20f22cb4e75b5073d"}, + {"webworker01_NA", "0324791c836fae78e2a698c53e58e671917cf66b145e9af83d431815a5002fb9a0"}, + {"who-biz_NA", "02f91a6772fe1a376e2bbe4b190008e3f878d40a8eaf92c65f1a7680b6b42ea47b"}, + {"yurri-khi_DEV", "03e57c7341d2c8a3be62e1caaa28978d76a8277dea7bb484fdd8c55dc05e4e4e93"}, + {"dragonhound_AR", "030a72f1a15f67624aea55743c5b777bdd55362596add77b544ee2e582bdebf0c7"}, // 60 + {"dragonhound_EU", "0286d7af8583e18127bd1f45730916b4f48ae3e0c90181b2745174b91b76c6e28b"}, + {"dragonhound_NA", "0306476ea5fb67aec667172a9bb30646dbff195b84c30ac958175af9b475987802"}, + {"dragonhound_DEV", "02f9a7b49282885cd03969f1f5478287497bc8edfceee9eac676053c107c5fcdaf"} + } +}; diff --git a/src/komodo_hardfork.h b/src/komodo_hardfork.h index 5cf20ad35e0..6692c81b121 100644 --- a/src/komodo_hardfork.h +++ b/src/komodo_hardfork.h @@ -1,7 +1,7 @@ #pragma once #include -#define NUM_KMD_SEASONS 7 +#define NUM_KMD_SEASONS 8 #define NUM_KMD_NOTARIES 64 extern const uint32_t nStakedDecemberHardforkTimestamp; //December 2019 hardfork @@ -16,479 +16,13 @@ extern const int32_t nS5HardforkHeight; //dPoW Season 5 June 14th, 2021 hardfo extern const uint32_t nS6Timestamp; // dPoW Season 6, Fri Jun 24 2022 13:37:33 GMT+0000 extern const int32_t nS6HardforkHeight; // dPoW Season 6, Fri Jun 24 2022 -static const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, nStakedDecemberHardforkTimestamp, nS4Timestamp, nS5Timestamp, nS6Timestamp, 1751328000}; -static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {814000, 1444000, nDecemberHardforkHeight, nS4HardforkHeight, nS5HardforkHeight, nS6HardforkHeight, 7113400}; +extern const uint32_t nS7Timestamp; // dPoW Season 7, Fri Jun 30 2023 13:37:33 GMT+0000 +extern const int32_t nS7HardforkHeight; // dPoW Season 7, Fri Jun 30 2023 -// Era array of pubkeys. Add extra seasons to bottom as requried, after adding appropriate info above. -static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = -{ - { - { "0_jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, - { "0_jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" }, - { "0_kolo_testA", "0287aa4b73988ba26cf6565d815786caf0d2c4af704d7883d163ee89cd9977edec" }, - { "artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, - { "artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, - { "artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, - { "artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, - { "badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, - { "badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, - { "badass_SH", "026b49dd3923b78a592c1b475f208e23698d3f085c4c3b4906a59faf659fd9530b" }, - { "crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, // 10 - { "crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, - { "crackers_SH", "02be28310e6312d1dd44651fd96f6a44ccc269a321f907502aae81d246fabdb03e" }, - { "durerus_EU", "02bcbd287670bdca2c31e5d50130adb5dea1b53198f18abeec7211825f47485d57" }, - { "etszombi_AR", "031c79168d15edabf17d9ec99531ea9baa20039d0cdc14d9525863b83341b210e9" }, - { "etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, // 15 - { "etszombi_SH", "025d7a193c0757f7437fad3431f027e7b5ed6c925b77daba52a8755d24bf682dde" }, - { "farl4web_EU", "0300ecf9121cccf14cf9423e2adb5d98ce0c4e251721fa345dec2e03abeffbab3f" }, - { "farl4web_SH", "0396bb5ed3c57aa1221d7775ae0ff751e4c7dc9be220d0917fa8bbdf670586c030" }, - { "fullmoon_AR", "0254b1d64840ce9ff6bec9dd10e33beb92af5f7cee628f999cb6bc0fea833347cc" }, - { "fullmoon_NA", "031fb362323b06e165231c887836a8faadb96eda88a79ca434e28b3520b47d235b" }, // 20 - { "fullmoon_SH", "030e12b42ec33a80e12e570b6c8274ce664565b5c3da106859e96a7208b93afd0d" }, - { "grewal_NA", "03adc0834c203d172bce814df7c7a5e13dc603105e6b0adabc942d0421aefd2132" }, - { "grewal_SH", "03212a73f5d38a675ee3cdc6e82542a96c38c3d1c79d25a1ed2e42fcf6a8be4e68" }, - { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, - { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - { "jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, - { "jsgalt_NA", "027b3fb6fede798cd17c30dbfb7baf9332b3f8b1c7c513f443070874c410232446" }, - { "karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, // 30 - { "kashifali_EU", "033777c52a0190f261c6f66bd0e2bb299d30f012dcb8bfff384103211edb8bb207" }, - { "kolo_AR", "03016d19344c45341e023b72f9fb6e6152fdcfe105f3b4f50b82a4790ff54e9dc6" }, - { "kolo_SH", "02aa24064500756d9b0959b44d5325f2391d8e95c6127e109184937152c384e185" }, - { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - { "movecrypto_AR", "022783d94518e4dc77cbdf1a97915b29f427d7bc15ea867900a76665d3112be6f3" }, - { "movecrypto_EU", "021ab53bc6cf2c46b8a5456759f9d608966eff87384c2b52c0ac4cc8dd51e9cc42" }, - { "movecrypto_NA", "02efb12f4d78f44b0542d1c60146738e4d5506d27ec98a469142c5c84b29de0a80" }, - { "movecrypto_SH", "031f9739a3ebd6037a967ce1582cde66e79ea9a0551c54731c59c6b80f635bc859" }, - { "muros_AR", "022d77402fd7179335da39479c829be73428b0ef33fb360a4de6890f37c2aa005e" }, - { "noashh_AR", "029d93ef78197dc93892d2a30e5a54865f41e0ca3ab7eb8e3dcbc59c8756b6e355" }, // 40 - { "noashh_EU", "02061c6278b91fd4ac5cab4401100ffa3b2d5a277e8f71db23401cc071b3665546" }, - { "noashh_NA", "033c073366152b6b01535e15dd966a3a8039169584d06e27d92a69889b720d44e1" }, - { "nxtswe_EU", "032fb104e5eaa704a38a52c126af8f67e870d70f82977e5b2f093d5c1c21ae5899" }, - { "polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, - { "pondsea_AR", "032e1c213787312099158f2d74a89e8240a991d162d4ce8017d8504d1d7004f735" }, - { "pondsea_EU", "0225aa6f6f19e543180b31153d9e6d55d41bc7ec2ba191fd29f19a2f973544e29d" }, - { "pondsea_NA", "031bcfdbb62268e2ff8dfffeb9ddff7fe95fca46778c77eebff9c3829dfa1bb411" }, - { "pondsea_SH", "02209073bc0943451498de57f802650311b1f12aa6deffcd893da198a544c04f36" }, - { "popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, - { "popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, // 50 - { "ptytrader_NA", "0328c61467148b207400b23875234f8a825cce65b9c4c9b664f47410b8b8e3c222" }, - { "ptytrader_SH", "0250c93c492d8d5a6b565b90c22bee07c2d8701d6118c6267e99a4efd3c7748fa4" }, - { "rnr_AR", "029bdb08f931c0e98c2c4ba4ef45c8e33a34168cb2e6bf953cef335c359d77bfcd" }, - { "rnr_EU", "03f5c08dadffa0ffcafb8dd7ffc38c22887bd02702a6c9ac3440deddcf2837692b" }, - { "rnr_NA", "02e17c5f8c3c80f584ed343b8dcfa6d710dfef0889ec1e7728ce45ce559347c58c" }, - { "rnr_SH", "037536fb9bdfed10251f71543fb42679e7c52308bcd12146b2568b9a818d8b8377" }, - { "titomane_AR", "03cda6ca5c2d02db201488a54a548dbfc10533bdc275d5ea11928e8d6ab33c2185" }, - { "titomane_EU", "02e41feded94f0cc59f55f82f3c2c005d41da024e9a805b41105207ef89aa4bfbd" }, - { "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" }, - { "vanbreuk_EU", "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" }, // 60 - { "xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, - { "xxspot1_XX", "02ef445a392fcaf3ad4176a5da7f43580e8056594e003eba6559a713711a27f955" }, - { "xxspot2_XX", "03d85b221ea72ebcd25373e7961f4983d12add66a92f899deaf07bab1d8b6f5573" } - }, - { - {"0dev1_jl777", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, - {"0dev2_kolo", "030f34af4b908fb8eb2099accb56b8d157d49f6cfb691baa80fdd34f385efed961" }, - {"0dev3_kolo", "025af9d2b2a05338478159e9ac84543968fd18c45fd9307866b56f33898653b014" }, - {"0dev4_decker", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, - {"a-team_SH", "03b59ad322b17cb94080dc8e6dc10a0a865de6d47c16fb5b1a0b5f77f9507f3cce" }, - {"artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, - {"artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, - {"artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, - {"artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, - {"badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, - {"badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, // 10 - {"batman_AR", "033ecb640ec5852f42be24c3bf33ca123fb32ced134bed6aa2ba249cf31b0f2563" }, - {"batman_SH", "02ca5898931181d0b8aafc75ef56fce9c43656c0b6c9f64306e7c8542f6207018c" }, - {"ca333_EU", "03fc87b8c804f12a6bd18efd43b0ba2828e4e38834f6b44c0bfee19f966a12ba99" }, - {"chainmakers_EU", "02f3b08938a7f8d2609d567aebc4989eeded6e2e880c058fdf092c5da82c3bc5ee" }, - {"chainmakers_NA", "0276c6d1c65abc64c8559710b8aff4b9e33787072d3dda4ec9a47b30da0725f57a" }, - {"chainstrike_SH", "0370bcf10575d8fb0291afad7bf3a76929734f888228bc49e35c5c49b336002153" }, - {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, - {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, - {"crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, - {"crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, // 20 - {"dwy_EU", "0259c646288580221fdf0e92dbeecaee214504fdc8bbdf4a3019d6ec18b7540424" }, - {"emmanux_SH", "033f316114d950497fc1d9348f03770cd420f14f662ab2db6172df44c389a2667a" }, - {"etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, - {"fullmoon_AR", "03380314c4f42fa854df8c471618751879f9e8f0ff5dbabda2bd77d0f96cb35676" }, - {"fullmoon_NA", "030216211d8e2a48bae9e5d7eb3a42ca2b7aae8770979a791f883869aea2fa6eef" }, - {"fullmoon_SH", "03f34282fa57ecc7aba8afaf66c30099b5601e98dcbfd0d8a58c86c20d8b692c64" }, - {"goldenman_EU", "02d6f13a8f745921cdb811e32237bb98950af1a5952be7b3d429abd9152f8e388d" }, - {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, // 30 - {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - {"jackson_AR", "038ff7cfe34cb13b524e0941d5cf710beca2ffb7e05ddf15ced7d4f14fbb0a6f69" }, - {"jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, - {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, - {"komodoninja_EU", "038e567b99806b200b267b27bbca2abf6a3e8576406df5f872e3b38d30843cd5ba" }, - {"komodoninja_SH", "033178586896915e8456ebf407b1915351a617f46984001790f0cce3d6f3ada5c2" }, - {"komodopioneers_SH", "033ace50aedf8df70035b962a805431363a61cc4e69d99d90726a2d48fb195f68c" }, - {"libscott_SH", "03301a8248d41bc5dc926088a8cf31b65e2daf49eed7eb26af4fb03aae19682b95" }, - {"lukechilds_AR", "031aa66313ee024bbee8c17915cf7d105656d0ace5b4a43a3ab5eae1e14ec02696" }, - {"madmax_AR", "03891555b4a4393d655bf76f0ad0fb74e5159a615b6925907678edc2aac5e06a75" }, // 40 - {"meshbits_AR", "02957fd48ae6cb361b8a28cdb1b8ccf5067ff68eb1f90cba7df5f7934ed8eb4b2c" }, - {"meshbits_SH", "025c6e94877515dfd7b05682b9cc2fe4a49e076efe291e54fcec3add78183c1edb" }, - {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, - {"patchkez_SH", "0296270f394140640f8fa15684fc11255371abb6b9f253416ea2734e34607799c4" }, - {"pbca26_NA", "0276aca53a058556c485bbb60bdc54b600efe402a8b97f0341a7c04803ce204cb5" }, - {"peer2cloud_AR", "034e5563cb885999ae1530bd66fab728e580016629e8377579493b386bf6cebb15" }, - {"peer2cloud_SH", "03396ac453b3f23e20f30d4793c5b8ab6ded6993242df4f09fd91eb9a4f8aede84" }, - {"polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, - {"hyper_AR", "020f2f984d522051bd5247b61b080b4374a7ab389d959408313e8062acad3266b4" }, // 50 - {"hyper_EU", "03d00cf9ceace209c59fb013e112a786ad583d7de5ca45b1e0df3b4023bb14bf51" }, - {"hyper_SH", "0383d0b37f59f4ee5e3e98a47e461c861d49d0d90c80e9e16f7e63686a2dc071f3" }, - {"hyper_NA", "03d91c43230336c0d4b769c9c940145a8c53168bf62e34d1bccd7f6cfc7e5592de" }, - {"popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, - {"popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, - {"alien_AR", "0348d9b1fc6acf81290405580f525ee49b4749ed4637b51a28b18caa26543b20f0" }, - {"alien_EU", "020aab8308d4df375a846a9e3b1c7e99597b90497efa021d50bcf1bbba23246527" }, - {"thegaltmines_NA", "031bea28bec98b6380958a493a703ddc3353d7b05eb452109a773eefd15a32e421" }, - {"titomane_AR", "029d19215440d8cb9cc6c6b7a4744ae7fb9fb18d986e371b06aeb34b64845f9325" }, - {"titomane_EU", "0360b4805d885ff596f94312eed3e4e17cb56aa8077c6dd78d905f8de89da9499f" }, // 60 - {"titomane_SH", "03573713c5b20c1e682a2e8c0f8437625b3530f278e705af9b6614de29277a435b" }, - {"webworker01_NA", "03bb7d005e052779b1586f071834c5facbb83470094cff5112f0072b64989f97d7" }, - {"xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, - }, - { - {"madmax_NA", "0237e0d3268cebfa235958808db1efc20cc43b31100813b1f3e15cc5aa647ad2c3" }, // 0 - {"alright_AR", "020566fe2fb3874258b2d3cf1809a5d650e0edc7ba746fa5eec72750c5188c9cc9" }, - {"strob_NA", "0206f7a2e972d9dfef1c424c731503a0a27de1ba7a15a91a362dc7ec0d0fb47685" }, - {"dwy_EU", "021c7cf1f10c4dc39d13451123707ab780a741feedab6ac449766affe37515a29e" }, - {"phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, - {"chainmakers_NA", "02285d813c30c0bf7eefdab1ff0a8ad08a07a0d26d8b95b3943ce814ac8e24d885" }, - {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - {"blackjok3r_SH", "021eac26dbad256cbb6f74d41b10763183ee07fb609dbd03480dd50634170547cc" }, - {"chainmakers_EU", "03fdf5a3fce8db7dee89724e706059c32e5aa3f233a6b6cc256fea337f05e3dbf7" }, - {"titomane_AR", "023e3aa9834c46971ff3e7cb86a200ec9c8074a9566a3ea85d400d5739662ee989" }, - {"fullmoon_SH", "023b7252968ea8a955cd63b9e57dee45a74f2d7ba23b4e0595572138ad1fb42d21" }, // 10 - {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, - {"chmex_EU", "0281304ebbcc39e4f09fda85f4232dd8dacd668e20e5fc11fba6b985186c90086e" }, - {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, - {"ca333_DEV", "02856843af2d9457b5b1c907068bef6077ea0904cc8bd4df1ced013f64bf267958" }, - {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, - {"pungocloud_SH", "024dfc76fa1f19b892be9d06e985d0c411e60dbbeb36bd100af9892a39555018f6" }, - {"voskcoin_EU", "034190b1c062a04124ad15b0fa56dfdf34aa06c164c7163b6aec0d654e5f118afb" }, - {"decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, - {"cryptoeconomy_EU", "0290ab4937e85246e048552df3e9a66cba2c1602db76e03763e16c671e750145d1" }, - {"etszombi_EU", "0293ea48d8841af7a419a24d9da11c34b39127ef041f847651bae6ab14dcd1f6b4" }, // 20 - {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, - {"pirate_AR", "03e29c90354815a750db8ea9cb3c1b9550911bb205f83d0355a061ac47c4cf2fde" }, - {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - {"zatjum_SH", "02d6b0c89cacd58a0af038139a9a90c9e02cd1e33803a1f15fceabea1f7e9c263a" }, - {"madmax_AR", "03c5941fe49d673c094bc8e9bb1a95766b4670c88be76d576e915daf2c30a454d3" }, - {"lukechilds_NA", "03f1051e62c2d280212481c62fe52aab0a5b23c95de5b8e9ad5f80d8af4277a64b" }, - {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, - {"tonyl_AR", "02cc8bc862f2b65ad4f99d5f68d3011c138bf517acdc8d4261166b0be8f64189e1" }, - {"infotech_DEV", "0345ad4ab5254782479f6322c369cec77a7535d2f2162d103d666917d5e4f30c4c" }, - {"fullmoon_NA", "032c716701fe3a6a3f90a97b9d874a9d6eedb066419209eed7060b0cc6b710c60b" }, // 30 - {"etszombi_AR", "02e55e104aa94f70cde68165d7df3e162d4410c76afd4643b161dea044aa6d06ce" }, - {"node-9_EU", "0372e5b51e86e2392bb15039bac0c8f975b852b45028a5e43b324c294e9f12e411" }, - {"phba2061_EU", "03f6bd15dba7e986f0c976ea19d8a9093cb7c989d499f1708a0386c5c5659e6c4e" }, - {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - {"and1-89_EU", "02736cbf8d7b50835afd50a319f162dd4beffe65f2b1dc6b90e64b32c8e7849ddd" }, - {"komodopioneers_SH", "032a238a5747777da7e819cfa3c859f3677a2daf14e4dce50916fc65d00ad9c52a" }, - {"komodopioneers_EU", "036d02425916444fff8cc7203fcbfc155c956dda5ceb647505836bef59885b6866" }, - {"d0ct0r_NA", "0303725d8525b6f969122faf04152653eb4bf34e10de92182263321769c334bf58" }, - {"kolo_DEV", "02849e12199dcc27ba09c3902686d2ad0adcbfcee9d67520e9abbdda045ba83227" }, - {"peer2cloud_AR", "02acc001fe1fe8fd68685ba26c0bc245924cb592e10cec71e9917df98b0e9d7c37" }, // 40 - {"webworker01_SH", "031e50ba6de3c16f99d414bb89866e578d963a54bde7916c810608966fb5700776" }, - {"webworker01_NA", "032735e9cad1bb00eaababfa6d27864fa4c1db0300c85e01e52176be2ca6a243ce" }, - {"pbca26_NA", "03a97606153d52338bcffd1bf19bb69ef8ce5a7cbdc2dbc3ff4f89d91ea6bbb4dc" }, - {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - {"pirate_NA", "0255e32d8a56671dee8aa7f717debb00efa7f0086ee802de0692f2d67ee3ee06ee" }, - {"lukechilds_AR", "025c6a73ff6d750b9ddf6755b390948cffdd00f344a639472d398dd5c6b4735d23" }, - {"dragonhound_NA", "0224a9d951d3a06d8e941cc7362b788bb1237bb0d56cc313e797eb027f37c2d375" }, - {"fullmoon_AR", "03da64dd7cd0db4c123c2f79d548a96095a5a103e5b9d956e9832865818ffa7872" }, - {"chainzilla_SH", "0360804b8817fd25ded6e9c0b50e3b0782ac666545b5416644198e18bc3903d9f9" }, - {"titomane_EU", "03772ac0aad6b0e9feec5e591bff5de6775d6132e888633e73d3ba896bdd8e0afb" }, // 50 - {"jeezy_EU", "037f182facbad35684a6e960699f5da4ba89e99f0d0d62a87e8400dd086c8e5dd7" }, - {"titomane_SH", "03850fdddf2413b51790daf51dd30823addb37313c8854b508ea6228205047ef9b" }, - {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, - {"pirate_EU", "03fff24efd5648870a23badf46e26510e96d9e79ce281b27cfe963993039dd1351" }, - {"thegaltmines_NA", "02db1a16c7043f45d6033ccfbd0a51c2d789b32db428902f98b9e155cf0d7910ed" }, - {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4" }, - {"nutellalicka_SH", "02f7d90d0510c598ce45915e6372a9cd0ba72664cb65ce231f25d526fc3c5479fc" }, - {"chainstrike_SH", "03b806be3bf7a1f2f6290ec5c1ea7d3ea57774dcfcf2129a82b2569e585100e1cb" }, - {"dwy_SH", "036536d2d52d85f630b68b050f29ea1d7f90f3b42c10f8c5cdf3dbe1359af80aff" }, - {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, // 60 - {"gt_AR", "0348430538a4944d3162bb4749d8c5ed51299c2434f3ee69c11a1f7815b3f46135" }, - {"patchkez_SH", "03f45e9beb5c4cd46525db8195eb05c1db84ae7ef3603566b3d775770eba3b96ee" }, - {"decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, // 63 - }, - { - // Season 3.5 - {"madmax_NA", "0237e0d3268cebfa235958808db1efc20cc43b31100813b1f3e15cc5aa647ad2c3" }, // 0 - {"alright_AR", "020566fe2fb3874258b2d3cf1809a5d650e0edc7ba746fa5eec72750c5188c9cc9" }, - {"strob_NA", "0206f7a2e972d9dfef1c424c731503a0a27de1ba7a15a91a362dc7ec0d0fb47685" }, - {"hunter_EU", "0378224b4e9d8a0083ce36f2963ec0a4e231ec06b0c780de108e37f41181a89f6a" }, // FIXME verify this, kolo. Change name if you want - {"phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, - {"chainmakers_NA", "02285d813c30c0bf7eefdab1ff0a8ad08a07a0d26d8b95b3943ce814ac8e24d885" }, - {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - {"blackjok3r_SH", "021eac26dbad256cbb6f74d41b10763183ee07fb609dbd03480dd50634170547cc" }, - {"chainmakers_EU", "03fdf5a3fce8db7dee89724e706059c32e5aa3f233a6b6cc256fea337f05e3dbf7" }, - {"titomane_AR", "023e3aa9834c46971ff3e7cb86a200ec9c8074a9566a3ea85d400d5739662ee989" }, - {"fullmoon_SH", "023b7252968ea8a955cd63b9e57dee45a74f2d7ba23b4e0595572138ad1fb42d21" }, // 10 - {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, - {"chmex_EU", "0281304ebbcc39e4f09fda85f4232dd8dacd668e20e5fc11fba6b985186c90086e" }, - {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, - {"ca333_DEV", "02856843af2d9457b5b1c907068bef6077ea0904cc8bd4df1ced013f64bf267958" }, - {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, - {"pungocloud_SH", "024dfc76fa1f19b892be9d06e985d0c411e60dbbeb36bd100af9892a39555018f6" }, - {"voskcoin_EU", "034190b1c062a04124ad15b0fa56dfdf34aa06c164c7163b6aec0d654e5f118afb" }, - {"decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, - {"cryptoeconomy_EU", "0290ab4937e85246e048552df3e9a66cba2c1602db76e03763e16c671e750145d1" }, - {"etszombi_EU", "0293ea48d8841af7a419a24d9da11c34b39127ef041f847651bae6ab14dcd1f6b4" }, // 20 - {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, - {"pirate_AR", "03e29c90354815a750db8ea9cb3c1b9550911bb205f83d0355a061ac47c4cf2fde" }, - {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - {"zatjum_SH", "02d6b0c89cacd58a0af038139a9a90c9e02cd1e33803a1f15fceabea1f7e9c263a" }, - {"madmax_AR", "03c5941fe49d673c094bc8e9bb1a95766b4670c88be76d576e915daf2c30a454d3" }, - {"lukechilds_NA", "03f1051e62c2d280212481c62fe52aab0a5b23c95de5b8e9ad5f80d8af4277a64b" }, - {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, - {"tonyl_AR", "02cc8bc862f2b65ad4f99d5f68d3011c138bf517acdc8d4261166b0be8f64189e1" }, - {"infotech_DEV", "0345ad4ab5254782479f6322c369cec77a7535d2f2162d103d666917d5e4f30c4c" }, - {"fullmoon_NA", "032c716701fe3a6a3f90a97b9d874a9d6eedb066419209eed7060b0cc6b710c60b" }, // 30 - {"etszombi_AR", "02e55e104aa94f70cde68165d7df3e162d4410c76afd4643b161dea044aa6d06ce" }, - {"node-9_EU", "0372e5b51e86e2392bb15039bac0c8f975b852b45028a5e43b324c294e9f12e411" }, - {"phba2061_EU", "03f6bd15dba7e986f0c976ea19d8a9093cb7c989d499f1708a0386c5c5659e6c4e" }, - {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - {"and1-89_EU", "02736cbf8d7b50835afd50a319f162dd4beffe65f2b1dc6b90e64b32c8e7849ddd" }, - {"komodopioneers_SH", "032a238a5747777da7e819cfa3c859f3677a2daf14e4dce50916fc65d00ad9c52a" }, - {"komodopioneers_EU", "036d02425916444fff8cc7203fcbfc155c956dda5ceb647505836bef59885b6866" }, - {"d0ct0r_NA", "0303725d8525b6f969122faf04152653eb4bf34e10de92182263321769c334bf58" }, - {"kolo_DEV", "02849e12199dcc27ba09c3902686d2ad0adcbfcee9d67520e9abbdda045ba83227" }, - {"peer2cloud_AR", "02acc001fe1fe8fd68685ba26c0bc245924cb592e10cec71e9917df98b0e9d7c37" }, // 40 - {"webworker01_SH", "031e50ba6de3c16f99d414bb89866e578d963a54bde7916c810608966fb5700776" }, - {"webworker01_NA", "032735e9cad1bb00eaababfa6d27864fa4c1db0300c85e01e52176be2ca6a243ce" }, - {"pbca26_NA", "03a97606153d52338bcffd1bf19bb69ef8ce5a7cbdc2dbc3ff4f89d91ea6bbb4dc" }, - {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - {"pirate_NA", "0255e32d8a56671dee8aa7f717debb00efa7f0086ee802de0692f2d67ee3ee06ee" }, - {"lukechilds_AR", "025c6a73ff6d750b9ddf6755b390948cffdd00f344a639472d398dd5c6b4735d23" }, - {"dragonhound_NA", "0224a9d951d3a06d8e941cc7362b788bb1237bb0d56cc313e797eb027f37c2d375" }, - {"fullmoon_AR", "03da64dd7cd0db4c123c2f79d548a96095a5a103e5b9d956e9832865818ffa7872" }, - {"chainzilla_SH", "0360804b8817fd25ded6e9c0b50e3b0782ac666545b5416644198e18bc3903d9f9" }, - {"titomane_EU", "03772ac0aad6b0e9feec5e591bff5de6775d6132e888633e73d3ba896bdd8e0afb" }, // 50 - {"jeezy_EU", "037f182facbad35684a6e960699f5da4ba89e99f0d0d62a87e8400dd086c8e5dd7" }, - {"titomane_SH", "03850fdddf2413b51790daf51dd30823addb37313c8854b508ea6228205047ef9b" }, - {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, - {"pirate_EU", "03fff24efd5648870a23badf46e26510e96d9e79ce281b27cfe963993039dd1351" }, - {"thegaltmines_NA", "02db1a16c7043f45d6033ccfbd0a51c2d789b32db428902f98b9e155cf0d7910ed" }, - {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4" }, - {"nutellalicka_SH", "02f7d90d0510c598ce45915e6372a9cd0ba72664cb65ce231f25d526fc3c5479fc" }, - {"chainstrike_SH", "03b806be3bf7a1f2f6290ec5c1ea7d3ea57774dcfcf2129a82b2569e585100e1cb" }, - {"hunter_SH", "02407db70ad30ce4dfaee8b4ae35fae88390cad2b0ba0373fdd6231967537ccfdf" }, - {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, // 60 - {"gt_AR", "0348430538a4944d3162bb4749d8c5ed51299c2434f3ee69c11a1f7815b3f46135" }, - {"patchkez_SH", "03f45e9beb5c4cd46525db8195eb05c1db84ae7ef3603566b3d775770eba3b96ee" }, - {"decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, // 63 - }, - { - // Season 4 - { "alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, - { "alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, - { "strob_NA", "02a1c0bd40b294f06d3e44a52d1b2746c260c475c725e9351f1312e49e01c9a405" }, - { "titomane_SH", "020014ad4eedf6b1aeb0ad3b101a58d0a2fc570719e46530fd98d4e585f63eb4ae" }, - { "fullmoon_AR", "03b251095e747f759505ec745a4bbff9a768b8dce1f65137300b7c21efec01a07a" }, - { "phba2061_EU", "03a9492d2a1601d0d98cfe94d8adf9689d1bb0e600088127a4f6ca937761fb1c66" }, - { "fullmoon_NA", "03931c1d654a99658998ce0ddae108d825943a821d1cddd85e948ac1d483f68fb6" }, - { "fullmoon_SH", "03c2a1ed9ddb7bb8344328946017b9d8d1357b898957dd6aaa8c190ae26740b9ff" }, - { "madmax_AR", "022be5a2829fa0291f9a51ff7aeceef702eef581f2611887c195e29da49092e6de" }, - { "titomane_EU", "0285cf1fdba761daf6f1f611c32d319cd58214972ef822793008b69dde239443dd" }, - { "cipi_NA", "022c6825a24792cc3b010b1531521eba9b5e2662d640ed700fd96167df37e75239" }, - { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - { "decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, - { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - { "madmax_NA", "02997b7ab21b86bbea558ae79acc35d62c9cedf441578f78112f986d72e8eece08" }, - { "chainzilla_SH", "02288ba6dc57936b59d60345e397d62f5d7e7d975f34ed5c2f2e23288325661563" }, - { "peer2cloud_AR", "0250e7e43a3535731b051d1bcc7dc88fbb5163c3fe41c5dee72bd973bcc4dca9f2" }, - { "pirate_EU", "0231c0f50a06655c3d2edf8d7e722d290195d49c78d50de7786b9d196e8820c848" }, - { "webworker01_NA", "02dfd5f3cef1142879a7250752feb91ddd722c497fb98c7377c0fcc5ccc201bd55" }, - { "zatjum_SH", "036066fd638b10e555597623e97e032b28b4d1fa5a13c2b0c80c420dbddad236c2" }, - { "titomane_AR", "0268203a4c80047edcd66385c22e764ea5fb8bc42edae389a438156e7dca9a8251" }, - { "chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d" }, - { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, - { "patchkez_SH", "02cabd6c5fc0b5476c7a01e9d7b907e9f0a051d7f4f731959955d3f6b18ee9a242" }, - { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - { "etszombi_EU", "0341adbf238f33a33cc895633db996c3ad01275313ac6641e046a3db0b27f1c880" }, - { "pirate_NA", "02207f27a13625a0b8caef6a7bb9de613ff16e4a5f232da8d7c235c7c5bad72ffe" }, - { "metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, - { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - { "chainmakers_NA", "029415a1609c33dfe4a1016877ba35f9265d25d737649f307048efe96e76512877" }, - { "mihailo_EU", "037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941" }, - { "tonyl_AR", "0299684d7291abf90975fa493bf53212cf1456c374aa36f83cc94daece89350ae9" }, - { "alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8" }, - { "pungocloud_SH", "025b97d8c23effaca6fa7efacce20bf54df73081b63004a0fe22f3f98fece5669f" }, - { "node9_EU", "029ffa793b5c3248f8ea3da47fa3cf1810dada5af032ecd0e37bab5b92dd63b34e" }, - { "smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac" }, - { "nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b" }, - { "gcharang_SH", "02ec4172eab854a0d8cd32bc691c83e93975a3df5a4a453a866736c56e025dc359" }, - { "cipi_EU", "02f2b6defff1c544202f66e47cfd6909c54d67c7c39b9c2a99f137dbaf6d0bd8fa" }, - { "etszombi_AR", "0329944b0ac65b6760787ede042a2fde0be9fca1d80dd756bc0ee0b98d389b7682" }, - { "pbca26_NA", "0387e0fb6f2ca951154c87e16c6cbf93a69862bb165c1a96bcd8722b3af24fe533" }, - { "mylo_SH", "03b58f57822e90fe105e6efb63fd8666033ea503d6cc165b1e479bbd8c2ba033e8" }, - { "swisscertifiers_EU", "03ebcc71b42d88994b8b2134bcde6cb269bd7e71a9dd7616371d9294ec1c1902c5" }, - { "marmarachain_AR", "035bbd81a098172592fe97f50a0ce13cbbf80e55cc7862eccdbd7310fab8a90c4c" }, - { "karasugoi_NA", "0262cf2559703464151153c12e00c4b67a969e39b330301fdcaa6667d7eb02c57d" }, - { "phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, - { "oszy_EU", "03d1ffd680491b98a3ec5541715681d1a45293c8efb1722c32392a1d792622596a" }, - { "chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005" }, - { "dragonhound_NA", "0227e5cad3731e381df157de189527aac8eb50d82a13ce2bd81153984ebc749515" }, - { "strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a" }, - { "madmax_EU", "02ea0cf4d6d151d0528b07efa79cc7403d77cb9195e2e6c8374f5074b9a787e287" }, - { "dudezmobi_AR", "027ecd974ff2a27a37ee69956cd2e6bb31a608116206f3e31ef186823420182450" }, - { "daemonfox_NA", "022d6f4885f53cbd668ad7d03d4f8e830c233f74e3a918da1ed247edfc71820b3d" }, - { "nutellalicka_SH", "02f4b1e71bc865a79c05fe333952b97cb040d8925d13e83925e170188b3011269b" }, - { "starfleet_EU", "025c7275bd750936862b47793f1f0bb3cbed60fb75a48e7da016e557925fe375eb" }, - { "mrlynch_AR", "031987dc82b087cd53e23df5480e265a5928e9243e0e11849fa12359739d8b18a4" }, - { "greer_NA", "03e0995615d7d3cf1107effa6bdb1133e0876cf1768e923aa533a4e2ee675ec383" }, - { "mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043" }, - { "decker_EU", "03777777caebce56e17ca3aae4e16374335b156f1dd62ee3c7f8799c6b885f5560" }, - { "dappvader_SH", "02962e2e5af746632016bc7b24d444f7c90141a5f42ce54e361b302cf455d90e6a" }, - { "alright_DEV", "02b73a589d61691efa2ada15c006d27bc18493fea867ce6c14db3d3d28751f8ce3" }, - { "artemii235_DEV", "03bb616b12430bdd0483653de18733597a4fd416623c7065c0e21fe9d96460add1" }, - { "tonyl_DEV", "02d5f7fd6e25d34ab2f3318d60cdb89ff3a812ec5d0212c4c113bb12d12616cfdc" }, - { "decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" } - }, - { - // Season 5 - {"alrighttt_DEV", "03483166d8663beeb48a493eec161bf506df1906153b6259f7ca617e4cb8110260"}, // 0 - {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f"}, - {"artempikulin_AR", "026a8ed1e4eeeb023cfb8e003e1c1de6a2b771f37e112745ffb8b6e375a9cbfdec"}, - {"chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005"}, - {"cipi_AR", "033ae024cdb748e083406a2e20037017a1292079ad6a8161ae5b43f398724fea74"}, - {"shadowbit_AR", "02909c79a198179c193fb85bbd4ba09b875a5a9bd481fec284658188b96ed43519"}, - {"goldenman_AR", "0345b888e5de9c11871c080212ccaebf8a3d77b05fe3d535336efc5c7df334bbc7"}, - {"kolo_AR", "0281d3c7bf067088b9572b4d906afca2083a71a38b1011878ecd347651d00af433"}, - {"madmax_AR", "02f729b8df4dacdc8d811416eb32e98a5cc37023b42c81b77d1c00881de879a99a"}, - {"mcrypt_AR", "029bdb33b08f96524082490f4373bc6026b92bcaef9bc521a840a799c73b75ed80"}, - {"mrlynch_AR", "031987dc82b087cd53e23df5480e265a5928e9243e0e11849fa12359739d8b18a4"}, // 10 - {"ocean_AR", "03c2bc8c57a001a788851fedc33ce72797ee8fe26eaa3abb1b807727e4867a3105"}, - {"smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac"}, - {"tokel_AR", "03f3bf697173e47de7bae2ae02b3d3bcf28133a47db72f2a0266061597aaa7779d"}, - {"tonyl_AR", "029ad03929ec295e9164e2bfb9f0e0102c280d5e5212503d079d2d99ab492a9106"}, - {"tonyl_DEV", "02342ec82b31a016b71cd1eb2f482a74f63172e1029ba2fb18f0def3bd4fc0668a"}, - {"artem_DEV", "036b9848396ddcdb9bb58ddab2c24b710b8e4e9b0ee084a00518505ecd9e9fe174"}, - {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd"}, - {"alienx_EU", "026afe5b112d1b39e0edafd5e051e261a676104460581f3673f26ceff7f1e6c56c"}, - {"ca333_EU", "03ffb8072f78304c42ae9b60435f6c3296cbc72de129ae49bba175a65c31c9a7e2"}, - {"chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d"}, // 20 - {"cipi_EU", "03d6e1f3a693b5d69049791005d7cb64c259a1ad85833f5a9c545d4fee29905009"}, - {"cipi2_EU", "0202e430157486503f4bde3d3ca770c8f1e2447cf480a6b273b5265b9620f585e3"}, - {"shadowbit_EU", "02668f5f723584f97f5e6f9196fc31018f36a6cf824c60328ad0c097a785df4745"}, - {"komodopioneers_EU", "0351f7f2a6ecce863e4e774bfafe2e59e151c08bf8f350286763a6b8ed97274b82"}, - {"madmax_EU", "028d04f7ccae0d9d57bfa801c4f1e32c707c17589b3c08a0ce08d44eab637eb66b"}, - {"marmarachain_EU", "023a858bbc3f0c6df5b74243315028e968c2f299d84ea8ecc0b28b5f0e2ad24c3c"}, - {"node-9_EU", "03c375924aac39d0c49de6690199e4d08d10fed6725988dcf5d2486661b5e3a656"}, - {"slyris_EU", "021cb6365c13cb35aad4b70aa18b63a75d1d4b9797a0754d3d0142d6fedc83b24e"}, - {"smdmitry_EU", "02eb3aad81778f8d6f7e5295c44ca224e5c812f5e43fc1e9ce4ebafc23324183c9"}, - {"van_EU", "03af7f8c82f20671ca1978116353839d3e501523e379bfb52b1e05d7816bb5812f"}, // 30 - {"shadowbit_DEV", "02ca882f153e715091a2dbc5409096f8c109d9fe6506ca7a918056dd37162b6f6e"}, - {"gcharang_DEV", "02cb445948bf0d89f8d61102e12a5ee6e98be61ac7c2cb9ba435219ea9db967117"}, - {"alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8"}, - {"alienx_NA", "02f0b3ef87629509441b1ae95f28108f258a81910e483b90e0496205e24e7069b8"}, - {"cipi_NA", "036cc1d7476e4260601927be0fc8b748ae68d8fec8f5c498f71569a01bd92046c5"}, - {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4"}, - {"dragonhound_NA", "02e650819f4d1cabeaad6bc5ec8c0722a89e63059a10f8b5e97c983c321608329b"}, - {"hyper_NA", "030994a303b26df6e7c6ed456f069c5de9e200e1380bebc5ed8ebe0f834f477f3d"}, - {"madmax_NA", "03898aec46014e8619e2369cc85073048dad05d3c5bf696d8b524db78a39ae5beb"}, - {"node-9_NA", "02f697eed99fd21f2f0eaad81d13543a75c576f669bfddbcbeef0f7625fea2e9d5"}, // 40 - {"nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b"}, - {"pbca26_NA", "0332543ff1287604afd67f63af0aa0b263aef14fe1850b85db16b81462eed834fd"}, - {"ptyx_NA", "02cbda9c43a794f2134a11815fe86dca017990269accb139e962d764c011c9a4d7"}, - {"strob_NA", "02a1c0bd40b294f06d3e44a52d1b2746c260c475c725e9351f1312e49e01c9a405"}, - {"karasugoi_NA", "0262cf2559703464151153c12e00c4b67a969e39b330301fdcaa6667d7eb02c57d"}, - {"webworker01_NA", "0376558d13c31cf9c664a1b5e58f4fff7153777069bef7a66ed8c8526b99787a9e"}, - {"yurii_DEV", "03e57c7341d2c8a3be62e1caaa28978d76a8277dea7bb484fdd8c55dc05e4e4e93"}, - {"ca333_DEV", "03d885e292842912bd990299ebce33451a5a01cb14e4874d90770efb22e82ef40f"}, - {"chmex_SH", "02698305eb3c27a2c724efd2152f9250739355116f201656c34b83aac2d3aebd19"}, - {"collider_SH", "03bd0022a55a2ead52fd65b317186743374ad320f3704d459f41797e264d1ec854"}, // 50 - {"dappvader_SH", "02bffea7911e09ad9a7df54af0c225516478d3ba138e65061aa8d4b9756bb4c8f4"}, - {"drkush_SH", "030b31cc9528566422e25f3e9b96541ab3626c0dea0e7aa3c0b0bd96039eae2f5a"}, - {"majora31_SH", "033bf21f039a1c832effad208d564e02e968f11e3a3aa41c42e3b748a232fb33f3"}, - {"mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043"}, - {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309"}, - {"mylo_SH", "03458dca36e800d5bc121d8c0d35f9fc6282880a79fee2d7e050f887b797bc7d6e"}, - {"nutellaLicka_SH", "03a495962a9e9eca06ee3b8ab4cd94e6ea0d87dd39d334ad85a524c4fece1a3db7"}, - {"pbca26_SH", "02c62877e96fc414f2444edf0601abff9d5d2f9078e49fa867ba5305f3c5b3beb0"}, - {"phit_SH", "02a9cef2141fb2af24349c1eea20f5fa8f5dba2835723778d19b23353ddcd877b1"}, - {"sheeba_SH", "03e6578015b7f0ab78a486070435031fff7bae11256ca6a9f3d358ab03029737cb"}, // 60 - {"strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a"}, - {"strobnidan_SH", "02b967fde3686d45056343e488997d4c53f25cd7ad38548cd12b136010a09295ae"}, - {"dragonhound_DEV", "038e010c33c56b61389409eea5597fe17967398731e23185c84c472a16fc5d34ab"} - }, - { - // Season 6 - {"blackice_DEV", "02ca882f153e715091a2dbc5409096f8c109d9fe6506ca7a918056dd37162b6f6e"}, // 0 - {"blackice_AR", "02909c79a198179c193fb85bbd4ba09b875a5a9bd481fec284658188b96ed43519"}, - {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd"}, - {"alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8"}, - {"alien_SH", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f"}, - {"alienx_EU", "026afe5b112d1b39e0edafd5e051e261a676104460581f3673f26ceff7f1e6c56c"}, - {"alienx_NA", "02f0b3ef87629509441b1ae95f28108f258a81910e483b90e0496205e24e7069b8"}, - {"artem.pikulin_AR", "026a8ed1e4eeeb023cfb8e003e1c1de6a2b771f37e112745ffb8b6e375a9cbfdec"}, - {"artem.pikulin_DEV", "036b9848396ddcdb9bb58ddab2c24b710b8e4e9b0ee084a00518505ecd9e9fe174"}, - {"blackice_EU", "02668f5f723584f97f5e6f9196fc31018f36a6cf824c60328ad0c097a785df4745"}, - {"chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005"}, // 10 - {"chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d"}, - {"chmex_NA", "030c2528c29d5328243c910277e3d74aa77c9b4e145308007d2b11550731591dbe"}, - {"chmex_SH", "02698305eb3c27a2c724efd2152f9250739355116f201656c34b83aac2d3aebd19"}, - {"chmex1_SH", "02d27ed1cddfbaff9e47865e7df0165457e8f075f70bbea8c0498598ccf494555d"}, - {"cipi_1_EU", "03d6e1f3a693b5d69049791005d7cb64c259a1ad85833f5a9c545d4fee29905009"}, - {"cipi_2_EU", "0202e430157486503f4bde3d3ca770c8f1e2447cf480a6b273b5265b9620f585e3"}, - {"cipi_AR", "033ae024cdb748e083406a2e20037017a1292079ad6a8161ae5b43f398724fea74"}, - {"cipi_NA", "036cc1d7476e4260601927be0fc8b748ae68d8fec8f5c498f71569a01bd92046c5"}, - {"computergenie_EU", "03a8c071036228e0900e0171f616ce1a58f0a761193551d68c4c20e70534f2e183"}, - {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4"}, // 20 - {"dimxy_AR", "02689d0b77b1e8e8c93a102d8b689fd08179164d70e2dd585543c3896a0916e6a1"}, - {"dimxy_DEV", "039a01cd626d5efbe7fd05a59d8e5fced53bacac589192278f9b00ad31654b6956"}, - {"dragonhound_NA", "02e650819f4d1cabeaad6bc5ec8c0722a89e63059a10f8b5e97c983c321608329b"}, - {"fediakash_AR", "027dfe5403f8870fb0e1b94a2b4204373b31ea73179ba500a88dd56d22855cd03b"}, - {"gcharang_DEV", "033b82b5791c65477dd11095cf33332013df6d2bcb7aa06a6dae5f7b22b6959b0b"}, - {"gcharang_SH", "02cb445948bf0d89f8d61102e12a5ee6e98be61ac7c2cb9ba435219ea9db967117"}, - {"goldenman_AR", "02c11f651df6a03f1a17b9ea0b1a73c0acca7aeacd4081e09bd7dd939690af8ae1"}, - {"kolo_AR", "028431645f923a9e383a4e37cbb7168fa34988da23d43097124fe882bdac6d175f"}, - {"kolo_EU", "03e1287d4c14ad73ce9ddd31361a7de8df4eeeefe9460a1ff9a6b2a1242ad3b7c2"}, - {"kolox_AR", "0289f5f64f4bb18d014c4e9f4c888f4da2b6518e88fd5b7768728c38177b66d305"}, // 30 - {"komodopioneers_EU", "0351f7f2a6ecce863e4e774bfafe2e59e151c08bf8f350286763a6b8ed97274b82"}, - {"madmax_DEV", "027100e6b3db2028034db651946ecde90e45be3799ebc310d39af4496772a850ad"}, - {"marmarachain_EU", "0234e40800500370d43979586ee2cec2e777a0368d10c682e78bca30fd1630c18d"}, - {"mcrypt_AR", "029bdb33b08f96524082490f4373bc6026b92bcaef9bc521a840a799c73b75ed80"}, - {"mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043"}, - {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309"}, - {"mylo_NA", "0365a778014c216401b6ba9c28eec88f116a9a9912e145ba2dbbd065d98b493af5"}, - {"mylo_SH", "03458dca36e800d5bc121d8c0d35f9fc6282880a79fee2d7e050f887b797bc7d6e"}, - {"nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b"}, - {"nutellalicka_AR", "0285be2518bf8d65fceaa5f4d8485002f90d3b7ff274b23bb925fd167128e19589"}, // 40 - {"nutellalicka_SH", "03a8b10c1f74af429fc43ab4eb722f6c2a88087f2d71703e7f0e8001207a966fb5"}, - {"ocean_AR", "03c2bc8c57a001a788851fedc33ce72797ee8fe26eaa3abb1b807727e4867a3105"}, - {"pbca26_NA", "03d8b25536da157d931b159a72c0eeaedb1bf7bb3eb2d02647fa41b2422a2b064e"}, - {"pbca26_SH", "039a55787b742c3725323f0bd81c90a484fbdbf276a16317883bb03eedd9d6aa7c"}, - {"phit_SH", "02a9cef2141fb2af24349c1eea20f5fa8f5dba2835723778d19b23353ddcd877b1"}, - {"ptyx_NA", "0395640e81359526ecbc140716ddd5c9a1ce2a697fb547ca896e17cad3c65e78db"}, - {"ptyx2_NA", "0225ff37e49e443065018736fbcad175ab5993b51b99b846e8de0b8b9abbed2ef2"}, - {"sheeba_SH", "03e6578015b7f0ab78a486070435031fff7bae11256ca6a9f3d358ab03029737cb"}, - {"smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac"}, - {"smdmitry_EU", "02eb3aad81778f8d6f7e5295c44ca224e5c812f5e43fc1e9ce4ebafc23324183c9"}, // 50 - {"smdmitry_SH", "02d01cd6b87cbf5a9795c06968f0d169168c1be0d82cfeb79958b11ae2c30316c1"}, - {"strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a"}, - {"strobnidan_SH", "02b967fde3686d45056343e488997d4c53f25cd7ad38548cd12b136010a09295ae"}, - {"tokel_NA", "02b472713e87fb2560569857051ea0811c65d668a6fe73df165afe152417f774a0"}, - {"tonyl_AR", "029ad03929ec295e9164e2bfb9f0e0102c280d5e5212503d079d2d99ab492a9106"}, - {"tonyl_DEV", "02342ec82b31a016b71cd1eb2f482a74f63172e1029ba2fb18f0def3bd4fc0668a"}, - {"van_EU", "03af7f8c82f20671ca1978116353839d3e501523e379bfb52b1e05d7816bb5812f"}, - {"webworker01_EU", "0321d523645caffd8e762764ba56f7874a61b9bf534837a2cb6e7da219fab15eef"}, - {"webworker01_NA", "0287883ddd8da366401893ebcc1ff7e52d2ad3736984120a0ab01603e02c21dc98"}, - {"who-biz_NA", "02f91a6772fe1a376e2bbe4b190008e3f878d40a8eaf92c65f1a7680b6b42ea47b"}, // 60 - {"yurii-khi_DEV", "03e57c7341d2c8a3be62e1caaa28978d76a8277dea7bb484fdd8c55dc05e4e4e93"}, - {"ca333_EU", "021d6fbe67d12f492a01306c70ab096f8b8581eb5f958d3f5fe3588ae8c7797f42"}, - {"dragonhound_DEV", "038e010c33c56b61389409eea5597fe17967398731e23185c84c472a16fc5d34ab"} - } -}; +static const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, nStakedDecemberHardforkTimestamp, nS4Timestamp, nS5Timestamp, nS6Timestamp, nS7Timestamp, 1951328000}; +static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {814000, 1444000, nDecemberHardforkHeight, nS4HardforkHeight, nS5HardforkHeight, nS6HardforkHeight, nS7HardforkHeight, 8113400}; extern char NOTARYADDRS[64][64]; -extern char NOTARY_ADDRESSES[NUM_KMD_SEASONS][64][64]; \ No newline at end of file +extern char NOTARY_ADDRESSES[NUM_KMD_SEASONS][64][64]; + +extern const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2]; diff --git a/src/komodo_interest.cpp b/src/komodo_interest.cpp index b862272132b..94dc5da3af4 100644 --- a/src/komodo_interest.cpp +++ b/src/komodo_interest.cpp @@ -13,125 +13,226 @@ * * ******************************************************************************/ #include "komodo_interest.h" +#include "komodo_bitcoind.h" +#include "komodo_utils.h" // dstr() +#include "komodo_hardfork.h" + +#define KOMODO_INTEREST ((uint64_t)5000000) //((uint64_t)(0.05 * COIN)) // 5% uint64_t _komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime) { - int32_t minutes; uint64_t interest = 0; - if ( nLockTime >= LOCKTIME_THRESHOLD && tiptime > nLockTime && (minutes= (tiptime - nLockTime) / 60) >= (KOMODO_MAXMEMPOOLTIME/60) ) + int32_t minutes; + if ( nLockTime >= LOCKTIME_THRESHOLD + && tiptime > nLockTime + && (minutes= (tiptime - nLockTime) / 60) >= (KOMODO_MAXMEMPOOLTIME/60) ) { if ( minutes > 365 * 24 * 60 ) minutes = 365 * 24 * 60; if ( txheight >= 1000000 && minutes > 31 * 24 * 60 ) minutes = 31 * 24 * 60; minutes -= ((KOMODO_MAXMEMPOOLTIME/60) - 1); - interest = ((nValue / 10512000) * minutes); + uint64_t res = (nValue / 10512000) * minutes; + if (txheight >= nS7HardforkHeight) + res /= 500; // KIP-0001 implementation, reduce AUR from 5% to 0.01% + return res; } - return(interest); + return 0; } +/**** + * @brief evidently a new way to calculate interest + * @param txheight + * @param nValue + * @param nLockTime + * @param tiptime + * @return interest calculated + */ uint64_t komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime) { - uint64_t interest = 0; - if ( txheight < KOMODO_ENDOFERA && nLockTime >= LOCKTIME_THRESHOLD && tiptime != 0 && nLockTime < tiptime && nValue >= 10*COIN ) //komodo_moneysupply(txheight) < MAX_MONEY && - interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); - return(interest); + if ( txheight < KOMODO_ENDOFERA + && nLockTime >= LOCKTIME_THRESHOLD + && tiptime != 0 + && nLockTime < tiptime + && nValue >= 10*COIN ) + return _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + return 0; } +/**** + * @brief calculate interest + * @param txheight + * @param nValue + * @param nLockTime + * @param tiptime + * @returns the interest + */ uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime) { int32_t minutes,exception; uint64_t interestnew,numerator,denominator,interest = 0; uint32_t activation; activation = 1491350400; // 1491350400 5th April - if ( ASSETCHAINS_SYMBOL[0] != 0 ) + if ( !chainName.isKMD() ) return(0); if ( txheight >= KOMODO_ENDOFERA ) - return(0); - if ( nLockTime >= LOCKTIME_THRESHOLD && tiptime != 0 && nLockTime < tiptime && nValue >= 10*COIN ) //komodo_moneysupply(txheight) < MAX_MONEY && + return 0; + + if ( nLockTime >= LOCKTIME_THRESHOLD && tiptime != 0 && nLockTime < tiptime && nValue >= 10*COIN ) { - if ( (minutes= (tiptime - nLockTime) / 60) >= 60 ) + int32_t minutes = (tiptime - nLockTime) / 60; + if ( minutes >= 60 ) { if ( minutes > 365 * 24 * 60 ) minutes = 365 * 24 * 60; if ( txheight >= 250000 ) minutes -= 59; - denominator = (((uint64_t)365 * 24 * 60) / minutes); + uint64_t denominator = (((uint64_t)365 * 24 * 60) / minutes); if ( denominator == 0 ) denominator = 1; // max KOMODO_INTEREST per transfer, do it at least annually! if ( nValue > 25000LL*COIN ) { - exception = 0; + bool exception = false; if ( txheight <= 155949 ) { if ( (txheight == 116607 && nValue == 2502721100000LL) || - (txheight == 126891 && nValue == 2879650000000LL) || - (txheight == 129510 && nValue == 3000000000000LL) || - (txheight == 141549 && nValue == 3500000000000LL) || - (txheight == 154473 && nValue == 3983399350000LL) || - (txheight == 154736 && nValue == 3983406748175LL) || - (txheight == 155013 && nValue == 3983414006565LL) || - (txheight == 155492 && nValue == 3983427592291LL) || - (txheight == 155613 && nValue == 9997409999999797LL) || - (txheight == 157927 && nValue == 9997410667451072LL) || - (txheight == 155613 && nValue == 2590000000000LL) || - (txheight == 155949 && nValue == 4000000000000LL) ) - exception = 1; - if ( exception == 0 || nValue == 4000000000000LL ) - printf(">>>>>>>>>>>> exception.%d txheight.%d %.8f locktime %u vs tiptime %u <<<<<<<<<\n",exception,txheight,(double)nValue/COIN,nLockTime,tiptime); + (txheight == 126891 && nValue == 2879650000000LL) || + (txheight == 129510 && nValue == 3000000000000LL) || + (txheight == 141549 && nValue == 3500000000000LL) || + (txheight == 154473 && nValue == 3983399350000LL) || + (txheight == 154736 && nValue == 3983406748175LL) || + (txheight == 155013 && nValue == 3983414006565LL) || + (txheight == 155492 && nValue == 3983427592291LL) || + (txheight == 155613 && nValue == 9997409999999797LL) || + (txheight == 157927 && nValue == 9997410667451072LL) || + (txheight == 155613 && nValue == 2590000000000LL) || + (txheight == 155949 && nValue == 4000000000000LL) ) + { + exception = true; + } + if ( exception || nValue == 4000000000000LL ) + printf(">>>>>>>>>>>> exception.%d txheight.%d %.8f locktime %u vs tiptime %u <<<<<<<<<\n",(int32_t)exception,txheight,(double)nValue/COIN,nLockTime,tiptime); } - //if ( nValue == 4000000000000LL ) - // printf(">>>>>>>>>>>> exception.%d txheight.%d %.8f locktime %u vs tiptime %u <<<<<<<<<\n",exception,txheight,(double)nValue/COIN,nLockTime,tiptime); - if ( exception == 0 ) + if ( !exception ) { - numerator = (nValue / 20); // assumes 5%! + uint64_t numerator = (nValue / 20); // assumes 5%! if ( txheight < 250000 ) interest = (numerator / denominator); else if ( txheight < 1000000 ) { interest = (numerator * minutes) / ((uint64_t)365 * 24 * 60); - interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + uint64_t interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); if ( interest < interestnew ) - printf("pathA current interest %.8f vs new %.8f for ht.%d %.8f locktime.%u tiptime.%u\n",dstr(interest),dstr(interestnew),txheight,dstr(nValue),nLockTime,tiptime); + printf("pathA current interest %.8f vs new %.8f for ht.%d %.8f locktime.%u tiptime.%u\n", + dstr(interest),dstr(interestnew),txheight,dstr(nValue),nLockTime,tiptime); } - else interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + else + interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); } else if ( txheight < 1000000 ) { - numerator = (nValue * KOMODO_INTEREST); + uint64_t numerator = (nValue * KOMODO_INTEREST); interest = (numerator / denominator) / COIN; - interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + uint64_t interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); if ( interest < interestnew ) printf("pathB current interest %.8f vs new %.8f for ht.%d %.8f locktime.%u tiptime.%u\n",dstr(interest),dstr(interestnew),txheight,dstr(nValue),nLockTime,tiptime); } - else interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + else + interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); } else { - /* 250000 algo - numerator = (nValue * KOMODO_INTEREST); - if ( txheight < 250000 || numerator * minutes < 365 * 24 * 60 ) - interest = (numerator / denominator) / COIN; - else interest = ((numerator * minutes) / ((uint64_t)365 * 24 * 60)) / COIN; - */ - numerator = (nValue * KOMODO_INTEREST); + uint64_t numerator = (nValue * KOMODO_INTEREST); if ( txheight < 250000 || tiptime < activation ) { if ( txheight < 250000 || numerator * minutes < 365 * 24 * 60 ) interest = (numerator / denominator) / COIN; - else interest = ((numerator * minutes) / ((uint64_t)365 * 24 * 60)) / COIN; + else + interest = ((numerator * minutes) / ((uint64_t)365 * 24 * 60)) / COIN; } else if ( txheight < 1000000 ) { - numerator = (nValue / 20); // assumes 5%! + uint64_t numerator = (nValue / 20); // assumes 5%! interest = ((numerator * minutes) / ((uint64_t)365 * 24 * 60)); - //fprintf(stderr,"interest %llu %.8f <- numerator.%llu minutes.%d\n",(long long)interest,(double)interest/COIN,(long long)numerator,(int32_t)minutes); - interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + uint64_t interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); if ( interest < interestnew ) fprintf(stderr,"pathC current interest %.8f vs new %.8f for ht.%d %.8f locktime.%u tiptime.%u\n",dstr(interest),dstr(interestnew),txheight,dstr(nValue),nLockTime,tiptime); } - else interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + else + interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); } - if ( 0 && numerator == (nValue * KOMODO_INTEREST) ) - fprintf(stderr,"komodo_interest.%d %lld %.8f nLockTime.%u tiptime.%u minutes.%d interest %lld %.8f (%llu / %llu) prod.%llu\n",txheight,(long long)nValue,(double)nValue/COIN,nLockTime,tiptime,minutes,(long long)interest,(double)interest/COIN,(long long)numerator,(long long)denominator,(long long)(numerator * minutes)); } } - return(interest); + return interest; } + +/**** + * @brief get information needed for interest calculation from a particular tx + * @param txheighttimep time of block + * @param txheightp height of block + * @param tiptimep time of tip + * @param valuep value of out at n + * @param hash the transaction hash + * @param n the vout to look for + * @returns locktime + */ +uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep, + uint256 hash,int32_t n) +{ + *txheighttimep = *txheightp = *tiptimep = 0; + *valuep = 0; + + LOCK(cs_main); + CTransaction tx; + uint256 hashBlock; + if ( !GetTransaction(hash,tx,hashBlock,true) ) + return(0); + uint32_t locktime = 0; + if ( n < tx.vout.size() ) + { + CBlockIndex *pindex = komodo_getblockindex(hashBlock); + if ( pindex != nullptr ) + { + *valuep = tx.vout[n].nValue; + *txheightp = pindex->nHeight; + *txheighttimep = pindex->nTime; + CBlockIndex *tipindex; + if ( *tiptimep == 0 && (tipindex= chainActive.Tip()) != 0 ) + *tiptimep = (uint32_t)tipindex->nTime; + locktime = tx.nLockTime; + } + } + return(locktime); +} + +/**** + * @brief get accrued interest + * @param[out] txheightp + * @param[out] locktimep + * @param[in] hash + * @param[in] n + * @param[in] checkheight + * @param[in] checkvalue + * @param[in] tipheight + * @return the interest calculated + */ +uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n, + int32_t checkheight,uint64_t checkvalue,int32_t tipheight) +{ + uint32_t tiptime=0; + CBlockIndex *pindex = chainActive[tipheight]; + if ( pindex != nullptr ) + tiptime = (uint32_t)pindex->nTime; + else + fprintf(stderr,"cant find height[%d]\n",tipheight); + + uint32_t txheighttimep; + uint64_t value; + *locktimep = komodo_interest_args(&txheighttimep, txheightp, &tiptime, &value, hash, n); + if ( *locktimep != 0 ) + { + if ( (checkvalue == 0 || value == checkvalue) && (checkheight == 0 || *txheightp == checkheight) ) + return komodo_interest(*txheightp,value,*locktimep,tiptime); + else + fprintf(stderr,"komodo_accrued_interest value mismatch %llu vs %llu or height mismatch %d vs %d\n",(long long)value,(long long)checkvalue,*txheightp,checkheight); + } + return 0; +} + diff --git a/src/komodo_interest.h b/src/komodo_interest.h index d8c7ed7859d..24fc8c7650a 100644 --- a/src/komodo_interest.h +++ b/src/komodo_interest.h @@ -12,19 +12,42 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ +#include "uint256.h" +#include -#include "komodo_defs.h" - -#define SATOSHIDEN ((uint64_t)100000000L) -#define dstr(x) ((double)(x) / SATOSHIDEN) - +// each era of this many blocks reduces block reward from 3 to 2 to 1 #define KOMODO_ENDOFERA 7777777 -#define KOMODO_INTEREST ((uint64_t)5000000) //((uint64_t)(0.05 * COIN)) // 5% -extern int64_t MAX_MONEY; -extern uint8_t NOTARY_PUBKEY33[]; - -uint64_t _komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); +/**** + * @brief evidently a new way to calculate interest + * @param txheight + * @param nValue + * @param nLockTime + * @param tiptime + * @return interest calculated + */ uint64_t komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); +/**** + * @brief calculate interest + * @param txheight + * @param nValue + * @param nLockTime + * @param tiptime + * @returns the interest + */ uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); + +/**** + * @brief get accrued interest + * @param[out] txheightp + * @param[out] locktimep + * @param[in] hash + * @param[in] n + * @param[in] checkheight + * @param[in] checkvalue + * @param[in] tipheight + * @return the interest calculated + */ +uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n, + int32_t checkheight,uint64_t checkvalue,int32_t tipheight); diff --git a/src/komodo_jumblr.cpp b/src/komodo_jumblr.cpp deleted file mode 100644 index 8cf5e94b523..00000000000 --- a/src/komodo_jumblr.cpp +++ /dev/null @@ -1,764 +0,0 @@ -/****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * - * * - * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * - * the top-level directory of this distribution for the individual copyright * - * holder information and the developer policies on copyright and licensing. * - * * - * Unless otherwise agreed in a custom licensing agreement, no part of the * - * SuperNET software, including this file may be copied, modified, propagated * - * or distributed except according to the terms contained in the LICENSE file * - * * - * Removal or modification of this copyright notice is prohibited. * - * * - ******************************************************************************/ -#include "komodo_jumblr.h" -#include "komodo_extern_globals.h" -#include "komodo_bitcoind.h" // komodo_issuemethod -#include "komodo_utils.h" // clonestr - -char Jumblr_secretaddrs[JUMBLR_MAXSECRETADDRS][64],Jumblr_deposit[64]; -int32_t Jumblr_numsecretaddrs; // if 0 -> run silent mode -jumblr_item *Jumblrs; - -char *jumblr_issuemethod(char *userpass,char *method,char *params,uint16_t port) -{ - cJSON *retjson,*resjson = 0; char *retstr; - if ( (retstr= komodo_issuemethod(userpass,method,params,port)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( jobj(retjson,(char *)"result") != 0 ) - resjson = jduplicate(jobj(retjson,(char *)"result")); - else if ( jobj(retjson,(char *)"error") != 0 ) - resjson = jduplicate(jobj(retjson,(char *)"error")); - else - { - resjson = cJSON_CreateObject(); - jaddstr(resjson,(char *)"error",(char *)"cant parse return"); - } - free_json(retjson); - } - free(retstr); - } - if ( resjson != 0 ) - return(jprint(resjson,1)); - else return(clonestr((char *)"{\"error\":\"unknown error\"}")); -} - -char *jumblr_importaddress(char *address) -{ - char params[1024]; - sprintf(params,"[\"%s\", \"%s\", false]",address,address); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"importaddress",params,BITCOIND_RPCPORT)); -} - -char *jumblr_validateaddress(char *addr) -{ - char params[1024]; - sprintf(params,"[\"%s\"]",addr); - printf("validateaddress.%s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"validateaddress",params,BITCOIND_RPCPORT)); -} - -int32_t Jumblr_secretaddrfind(char *searchaddr) -{ - int32_t i; - for (i=0; i 0 ) - { - OS_randombytes((uint8_t *)&r,sizeof(r)); - r %= Jumblr_numsecretaddrs; - safecopy(secretaddr,Jumblr_secretaddrs[r],64); - } - return(r); -} - -int32_t jumblr_addresstype(char *addr) -{ - if ( addr[0] == '"' && addr[strlen(addr)-1] == '"' ) - { - addr[strlen(addr)-1] = 0; - addr++; - } - if ( addr[0] == 'z' && addr[1] == 'c' && strlen(addr) >= 40 ) - return('z'); - else if ( strlen(addr) < 40 ) - return('t'); - printf("strange.(%s)\n",addr); - return(-1); -} - -struct jumblr_item *jumblr_opidfind(char *opid) -{ - struct jumblr_item *ptr; - HASH_FIND(hh,Jumblrs,opid,(int32_t)strlen(opid),ptr); - return(ptr); -} - -struct jumblr_item *jumblr_opidadd(char *opid) -{ - struct jumblr_item *ptr = 0; - if ( opid != 0 && (ptr= jumblr_opidfind(opid)) == 0 ) - { - ptr = (struct jumblr_item *)calloc(1,sizeof(*ptr)); - safecopy(ptr->opid,opid,sizeof(ptr->opid)); - HASH_ADD_KEYPTR(hh,Jumblrs,ptr->opid,(int32_t)strlen(ptr->opid),ptr); - if ( ptr != jumblr_opidfind(opid) ) - printf("jumblr_opidadd.(%s) ERROR, couldnt find after add\n",opid); - } - return(ptr); -} - -char *jumblr_zgetnewaddress() -{ - char params[1024]; - sprintf(params,"[]"); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getnewaddress",params,BITCOIND_RPCPORT)); -} - -char *jumblr_zlistoperationids() -{ - char params[1024]; - sprintf(params,"[]"); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listoperationids",params,BITCOIND_RPCPORT)); -} - -char *jumblr_zgetoperationresult(char *opid) -{ - char params[1024]; - sprintf(params,"[[\"%s\"]]",opid); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getoperationresult",params,BITCOIND_RPCPORT)); -} - -char *jumblr_zgetoperationstatus(char *opid) -{ - char params[1024]; - sprintf(params,"[[\"%s\"]]",opid); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getoperationstatus",params,BITCOIND_RPCPORT)); -} - -char *jumblr_sendt_to_z(char *taddr,char *zaddr,double amount) -{ - char params[1024]; double fee = ((amount-3*JUMBLR_TXFEE) * JUMBLR_FEE) * 1.5; - if ( jumblr_addresstype(zaddr) != 'z' || jumblr_addresstype(taddr) != 't' ) - return(clonestr((char *)"{\"error\":\"illegal address in t to z\"}")); - sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",taddr,zaddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); - printf("t -> z: %s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); -} - -char *jumblr_sendz_to_z(char *zaddrS,char *zaddrD,double amount) -{ - char params[1024]; double fee = (amount-2*JUMBLR_TXFEE) * JUMBLR_FEE; - if ( jumblr_addresstype(zaddrS) != 'z' || jumblr_addresstype(zaddrD) != 'z' ) - return(clonestr((char *)"{\"error\":\"illegal address in z to z\"}")); - //sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); - sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_TXFEE); - printf("z -> z: %s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); -} - -char *jumblr_sendz_to_t(char *zaddr,char *taddr,double amount) -{ - char params[1024]; double fee = ((amount-JUMBLR_TXFEE) * JUMBLR_FEE) * 1.5; - if ( jumblr_addresstype(zaddr) != 'z' || jumblr_addresstype(taddr) != 't' ) - return(clonestr((char *)"{\"error\":\"illegal address in z to t\"}")); - sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddr,taddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); - printf("z -> t: %s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); -} - -char *jumblr_zlistaddresses() -{ - char params[1024]; - sprintf(params,"[]"); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listaddresses",params,BITCOIND_RPCPORT)); -} - -char *jumblr_zlistreceivedbyaddress(char *addr) -{ - char params[1024]; - sprintf(params,"[\"%s\", 1]",addr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listreceivedbyaddress",params,BITCOIND_RPCPORT)); -} - -char *jumblr_getreceivedbyaddress(char *addr) -{ - char params[1024]; - sprintf(params,"[\"%s\", 1]",addr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"getreceivedbyaddress",params,BITCOIND_RPCPORT)); -} - -char *jumblr_importprivkey(char *wifstr) -{ - char params[1024]; - sprintf(params,"[\"%s\", \"\", false]",wifstr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"importprivkey",params,BITCOIND_RPCPORT)); -} - -char *jumblr_zgetbalance(char *addr) -{ - char params[1024]; - sprintf(params,"[\"%s\", 1]",addr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getbalance",params,BITCOIND_RPCPORT)); -} - -char *jumblr_listunspent(char *coinaddr) -{ - char params[1024]; - sprintf(params,"[1, 99999999, [\"%s\"]]",coinaddr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"listunspent",params,BITCOIND_RPCPORT)); -} - -char *jumblr_gettransaction(char *txidstr) -{ - char params[1024]; - sprintf(params,"[\"%s\", 1]",txidstr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,BITCOIND_RPCPORT)); -} - -int32_t jumblr_numvins(bits256 txid) -{ - char txidstr[65],params[1024],*retstr; cJSON *retjson,*vins; int32_t n,numvins = -1; - bits256_str(txidstr,txid); - if ( (retstr= jumblr_gettransaction(txidstr)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( jobj(retjson,(char *)"vin") != 0 && ((vins= jarray(&n,retjson,(char *)"vin")) == 0 || n == 0) ) - { - numvins = n; - //printf("numvins.%d\n",n); - } //else printf("no vin.(%s)\n",retstr); - free_json(retjson); - } - free(retstr); - } - return(numvins); -} - -int64_t jumblr_receivedby(char *addr) -{ - char *retstr; int64_t total = 0; - if ( (retstr= jumblr_getreceivedbyaddress(addr)) != 0 ) - { - total = atof(retstr) * SATOSHIDEN; - free(retstr); - } - return(total); -} - -int64_t jumblr_balance(char *addr) -{ - char *retstr; double val; int64_t balance = 0; //cJSON *retjson; int32_t i,n; - /*if ( jumblr_addresstype(addr) == 't' ) - { - if ( (retstr= jumblr_listunspent(addr)) != 0 ) - { - //printf("jumblr.[%s].(%s)\n","KMD",retstr); - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( (n= cJSON_GetArraySize(retjson)) > 0 && cJSON_IsArray(retjson) != 0 ) - for (i=0; i SMALLVAL ) - balance = val * SATOSHIDEN; - free(retstr); - } - return(balance); -} - -int32_t jumblr_itemset(struct jumblr_item *ptr,cJSON *item,char *status) -{ - cJSON *params,*amounts,*dest; char *from,*addr; int32_t i,n; int64_t amount; - /*"params" : { - "fromaddress" : "RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5", - "amounts" : [ - { - "address" : "zc9s3UdkDFTnnwHrMCr1vYy2WmkjhmTxXNiqC42s7BjeKBVUwk766TTSsrRPKfnX31Bbu8wbrTqnjDqskYGwx48FZMPHvft", - "amount" : 3.00000000 - } - ], - "minconf" : 1, - "fee" : 0.00010000 - }*/ - if ( (params= jobj(item,(char *)"params")) != 0 ) - { - //printf("params.(%s)\n",jprint(params,0)); - if ( (from= jstr(params,(char *)"fromaddress")) != 0 ) - { - safecopy(ptr->src,from,sizeof(ptr->src)); - } - if ( (amounts= jarray(&n,params,(char *)"amounts")) != 0 ) - { - for (i=0; i 0 ) - { - if ( strcmp(addr,JUMBLR_ADDR) == 0 ) - ptr->fee = amount; - else - { - ptr->amount = amount; - safecopy(ptr->dest,addr,sizeof(ptr->dest)); - } - } - } - } - ptr->txfee = jdouble(params,(char *)"fee") * SATOSHIDEN; - } - return(1); -} - -void jumblr_opidupdate(struct jumblr_item *ptr) -{ - char *retstr,*status; cJSON *retjson,*item; - if ( ptr->status == 0 ) - { - if ( (retstr= jumblr_zgetoperationstatus(ptr->opid)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( cJSON_GetArraySize(retjson) == 1 && cJSON_IsArray(retjson) != 0 ) - { - item = jitem(retjson,0); - //printf("%s\n",jprint(item,0)); - if ( (status= jstr(item,(char *)"status")) != 0 ) - { - if ( strcmp(status,(char *)"success") == 0 ) - { - ptr->status = jumblr_itemset(ptr,item,status); - if ( (jumblr_addresstype(ptr->src) == 't' && jumblr_addresstype(ptr->src) == 'z' && strcmp(ptr->src,Jumblr_deposit) != 0) || (jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->src) == 't' && Jumblr_secretaddrfind(ptr->dest) < 0) ) - { - printf("a non-jumblr t->z pruned\n"); - free(jumblr_zgetoperationresult(ptr->opid)); - ptr->status = -1; - } - - } - else if ( strcmp(status,(char *)"failed") == 0 ) - { - printf("jumblr_opidupdate %s failed\n",ptr->opid); - free(jumblr_zgetoperationresult(ptr->opid)); - ptr->status = -1; - } - } - } - free_json(retjson); - } - free(retstr); - } - } -} - -void jumblr_prune(struct jumblr_item *ptr) -{ - struct jumblr_item *tmp; char oldsrc[128]; int32_t flag = 1; - if ( is_hexstr(ptr->opid,0) == 64 ) - return; - printf("jumblr_prune %s\n",ptr->opid); - strcpy(oldsrc,ptr->src); - free(jumblr_zgetoperationresult(ptr->opid)); - while ( flag != 0 ) - { - flag = 0; - HASH_ITER(hh,Jumblrs,ptr,tmp) - { - if ( strcmp(oldsrc,ptr->dest) == 0 ) - { - if ( is_hexstr(ptr->opid,0) != 64 ) - { - printf("jumblr_prune %s (%s -> %s) matched oldsrc\n",ptr->opid,ptr->src,ptr->dest); - free(jumblr_zgetoperationresult(ptr->opid)); - strcpy(oldsrc,ptr->src); - flag = 1; - break; - } - } - } - } -} - - -bits256 jbits256(cJSON *json,char *field); - - -void jumblr_zaddrinit(char *zaddr) -{ - struct jumblr_item *ptr; char *retstr,*totalstr; cJSON *item,*array; double total; bits256 txid; char txidstr[65],t_z,z_z; - if ( (totalstr= jumblr_zgetbalance(zaddr)) != 0 ) - { - if ( (total= atof(totalstr)) > SMALLVAL ) - { - if ( (retstr= jumblr_zlistreceivedbyaddress(zaddr)) != 0 ) - { - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - t_z = z_z = 0; - if ( cJSON_GetArraySize(array) == 1 && cJSON_IsArray(array) != 0 ) - { - item = jitem(array,0); - if ( (uint64_t)((total+0.0000000049) * SATOSHIDEN) == (uint64_t)((jdouble(item,(char *)"amount")+0.0000000049) * SATOSHIDEN) ) - { - txid = jbits256(item,(char *)"txid"); - bits256_str(txidstr,txid); - if ( (ptr= jumblr_opidadd(txidstr)) != 0 ) - { - ptr->amount = (total * SATOSHIDEN); - ptr->status = 1; - strcpy(ptr->dest,zaddr); - if ( jumblr_addresstype(ptr->dest) != 'z' ) - printf("error setting dest type to Z: %s\n",jprint(item,0)); - if ( jumblr_numvins(txid) == 0 ) - { - z_z = 1; - strcpy(ptr->src,zaddr); - ptr->src[3] = '0'; - ptr->src[4] = '0'; - ptr->src[5] = '0'; - if ( jumblr_addresstype(ptr->src) != 'z' ) - printf("error setting address type to Z: %s\n",jprint(item,0)); - } - else - { - t_z = 1; - strcpy(ptr->src,"taddr"); - if ( jumblr_addresstype(ptr->src) != 't' ) - printf("error setting address type to T: %s\n",jprint(item,0)); - } - printf("%s %s %.8f t_z.%d z_z.%d\n",zaddr,txidstr,total,t_z,z_z); // cant be z->t from spend - } - } else printf("mismatched %s %s total %.8f vs %.8f -> %lld\n",zaddr,totalstr,dstr(SATOSHIDEN * total),dstr(SATOSHIDEN * jdouble(item,(char *)"amount")),(long long)((uint64_t)(total * SATOSHIDEN) - (uint64_t)(jdouble(item,(char *)"amount") * SATOSHIDEN))); - } - free_json(array); - } - free(retstr); - } - } - free(totalstr); - } -} - -void jumblr_opidsupdate() -{ - char *retstr; cJSON *array; int32_t i,n; struct jumblr_item *ptr; - if ( (retstr= jumblr_zlistoperationids()) != 0 ) - { - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - if ( (n= cJSON_GetArraySize(array)) > 0 && cJSON_IsArray(array) != 0 ) - { - //printf("%s -> n%d\n",retstr,n); - for (i=0; istatus == 0 ) - jumblr_opidupdate(ptr); - //printf("%d: %s -> %s %.8f\n",ptr->status,ptr->src,ptr->dest,dstr(ptr->amount)); - if ( jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->dest) == 't' ) - jumblr_prune(ptr); - } - } - } - free_json(array); - } - free(retstr); - } -} - -uint64_t jumblr_increment(uint8_t r,int32_t height,uint64_t total,uint64_t biggest,uint64_t medium, uint64_t smallest) -{ - int32_t i,n; uint64_t incrs[1000],remains = total; - height /= JUMBLR_SYNCHRONIZED_BLOCKS; - if ( (height % JUMBLR_SYNCHRONIZED_BLOCKS) == 0 || total >= 100*biggest ) - { - if ( total >= biggest ) - return(biggest); - else if ( total >= medium ) - return(medium); - else if ( total >= smallest ) - return(smallest); - else return(0); - } - else - { - n = 0; - while ( remains > smallest && n < sizeof(incrs)/sizeof(*incrs) ) - { - if ( remains >= biggest ) - incrs[n] = biggest; - else if ( remains >= medium ) - incrs[n] = medium; - else if ( remains >= smallest ) - incrs[n] = smallest; - else break; - remains -= incrs[n]; - n++; - } - if ( n > 0 ) - { - r %= n; - for (i=0; i %.8f\n",n,r,dstr(incrs[r])); - return(incrs[r]); - } - } - return(0); -} - -void jumblr_iteration() -{ - static int32_t lastheight; static uint32_t lasttime; - char *zaddr,*addr,*retstr=0,secretaddr[64]; cJSON *array; int32_t i,iter,height,acpublic,counter,chosen_one,n; uint64_t smallest,medium,biggest,amount=0,total=0; double fee; struct jumblr_item *ptr,*tmp; uint16_t r,s; - acpublic = ASSETCHAINS_PUBLIC; - if ( ASSETCHAINS_SYMBOL[0] == 0 && GetTime() >= KOMODO_SAPLING_DEADLINE ) - acpublic = 1; - if ( JUMBLR_PAUSE != 0 || acpublic != 0 ) - return; - if ( lasttime == 0 ) - { - if ( (retstr= jumblr_zlistaddresses()) != 0 ) - { - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - if ( (n= cJSON_GetArraySize(array)) > 0 && cJSON_IsArray(array) != 0 ) - { - for (i=0; inHeight; - if ( time(NULL) < lasttime+40 ) - return; - lasttime = (uint32_t)time(NULL); - if ( lastheight == height ) - return; - lastheight = height; - if ( (height % JUMBLR_SYNCHRONIZED_BLOCKS) != JUMBLR_SYNCHRONIZED_BLOCKS-3 ) - return; - fee = JUMBLR_INCR * JUMBLR_FEE; - smallest = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE); - medium = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE); - biggest = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*777 + 3*JUMBLR_TXFEE); - OS_randombytes((uint8_t *)&r,sizeof(r)); - s = (r % 3); - //printf("jumblr_iteration r.%u s.%u\n",r,s); - switch ( s ) - { - case 0: // t -> z - default: - if ( Jumblr_deposit[0] != 0 && (total= jumblr_balance(Jumblr_deposit)) >= smallest ) - { - if ( (zaddr= jumblr_zgetnewaddress()) != 0 ) - { - if ( zaddr[0] == '"' && zaddr[strlen(zaddr)-1] == '"' ) - { - zaddr[strlen(zaddr)-1] = 0; - addr = zaddr+1; - } else addr = zaddr; - amount = jumblr_increment(r/3,height,total,biggest,medium,smallest); - /* - amount = 0; - if ( (height % (JUMBLR_SYNCHRONIZED_BLOCKS*JUMBLR_SYNCHRONIZED_BLOCKS)) == 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE) ) - amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE); - else if ( (r & 3) == 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE) ) - amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE); - else amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE);*/ - if ( amount > 0 && (retstr= jumblr_sendt_to_z(Jumblr_deposit,addr,dstr(amount))) != 0 ) - { - printf("sendt_to_z.(%s)\n",retstr); - free(retstr), retstr = 0; - } - free(zaddr); - } else printf("no zaddr from jumblr_zgetnewaddress\n"); - } - else if ( Jumblr_deposit[0] != 0 ) - printf("%s total %.8f vs %.8f\n",Jumblr_deposit,dstr(total),(JUMBLR_INCR + 3*(fee+JUMBLR_TXFEE))); - break; - case 1: // z -> z - jumblr_opidsupdate(); - chosen_one = -1; - for (iter=counter=0; iter<2; iter++) - { - counter = n = 0; - HASH_ITER(hh,Jumblrs,ptr,tmp) - { - if ( ptr->spent == 0 && ptr->status > 0 && jumblr_addresstype(ptr->src) == 't' && jumblr_addresstype(ptr->dest) == 'z' ) - { - if ( (total= jumblr_balance(ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) - { - if ( iter == 1 && counter == chosen_one ) - { - if ( (zaddr= jumblr_zgetnewaddress()) != 0 ) - { - if ( zaddr[0] == '"' && zaddr[strlen(zaddr)-1] == '"' ) - { - zaddr[strlen(zaddr)-1] = 0; - addr = zaddr+1; - } else addr = zaddr; - if ( (retstr= jumblr_sendz_to_z(ptr->dest,addr,dstr(total))) != 0 ) - { - printf("n.%d counter.%d chosen_one.%d send z_to_z.(%s)\n",n,counter,chosen_one,retstr); - free(retstr), retstr = 0; - } - ptr->spent = (uint32_t)time(NULL); - free(zaddr); - break; - } - } - counter++; - } - } - n++; - } - if ( counter == 0 ) - break; - if ( iter == 0 ) - { - OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one)); - if ( chosen_one < 0 ) - chosen_one = -chosen_one; - chosen_one %= counter; - printf("jumblr z->z chosen_one.%d of %d, from %d\n",chosen_one,counter,n); - } - } - break; - case 2: // z -> t - if ( Jumblr_numsecretaddrs > 0 ) - { - jumblr_opidsupdate(); - chosen_one = -1; - for (iter=0; iter<2; iter++) - { - counter = n = 0; - HASH_ITER(hh,Jumblrs,ptr,tmp) - { - //printf("status.%d %c %c %.8f\n",ptr->status,jumblr_addresstype(ptr->src),jumblr_addresstype(ptr->dest),dstr(ptr->amount)); - if ( ptr->spent == 0 && ptr->status > 0 && jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->dest) == 'z' ) - { - if ( (total= jumblr_balance(ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) - { - if ( iter == 1 && counter == chosen_one ) - { - Jumblr_secretaddr(secretaddr); - if ( (retstr= jumblr_sendz_to_t(ptr->dest,secretaddr,dstr(total))) != 0 ) - { - printf("%s send z_to_t.(%s)\n",secretaddr,retstr); - free(retstr), retstr = 0; - } else printf("null return from jumblr_sendz_to_t\n"); - ptr->spent = (uint32_t)time(NULL); - break; - } - counter++; - } //else printf("z->t spent.%u total %.8f error\n",ptr->spent,dstr(total)); - } - n++; - } - if ( counter == 0 ) - break; - if ( iter == 0 ) - { - OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one)); - if ( chosen_one < 0 ) - chosen_one = -chosen_one; - chosen_one %= counter; - printf("jumblr z->t chosen_one.%d of %d, from %d\n",chosen_one,counter,n); - } //else printf("n.%d counter.%d chosen.%d\n",n,counter,chosen_one); - } - } - break; - } -} diff --git a/src/komodo_jumblr.h b/src/komodo_jumblr.h deleted file mode 100644 index 0ddd99b3403..00000000000 --- a/src/komodo_jumblr.h +++ /dev/null @@ -1,112 +0,0 @@ -/****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * - * * - * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * - * the top-level directory of this distribution for the individual copyright * - * holder information and the developer policies on copyright and licensing. * - * * - * Unless otherwise agreed in a custom licensing agreement, no part of the * - * SuperNET software, including this file may be copied, modified, propagated * - * or distributed except according to the terms contained in the LICENSE file * - * * - * Removal or modification of this copyright notice is prohibited. * - * * - ******************************************************************************/ -#pragma once -#include "uthash.h" // UT_hash_handle -#include "komodo_cJSON.h" -#include "komodo_defs.h" - -#ifdef _WIN32 -#include -#endif - -#define JUMBLR_ADDR "RGhxXpXSSBTBm9EvNsXnTQczthMCxHX91t" -#define JUMBLR_BTCADDR "18RmTJe9qMech8siuhYfMtHo8RtcN1obC6" -#define JUMBLR_MAXSECRETADDRS 777 -#define JUMBLR_SYNCHRONIZED_BLOCKS 10 -#define JUMBLR_INCR 9.965 -#define JUMBLR_FEE 0.001 -#define JUMBLR_TXFEE 0.01 -#define SMALLVAL 0.000000000000001 - -#define JUMBLR_ERROR_DUPLICATEDEPOSIT -1 -#define JUMBLR_ERROR_SECRETCANTBEDEPOSIT -2 -#define JUMBLR_ERROR_TOOMANYSECRETS -3 -#define JUMBLR_ERROR_NOTINWALLET -4 - -struct jumblr_item -{ - UT_hash_handle hh; - int64_t amount,fee,txfee; // fee and txfee not really used (yet) - uint32_t spent,pad; - char opid[66],src[128],dest[128],status; -}; - -char *jumblr_issuemethod(char *userpass,char *method,char *params,uint16_t port); - -char *jumblr_importaddress(char *address); - -char *jumblr_validateaddress(char *addr); - -int32_t Jumblr_secretaddrfind(char *searchaddr); - -int32_t Jumblr_secretaddradd(char *secretaddr); // external - -int32_t Jumblr_depositaddradd(char *depositaddr); // external - -int32_t Jumblr_secretaddr(char *secretaddr); - -int32_t jumblr_addresstype(char *addr); - -struct jumblr_item *jumblr_opidfind(char *opid); - -struct jumblr_item *jumblr_opidadd(char *opid); - -char *jumblr_zgetnewaddress(); - -char *jumblr_zlistoperationids(); - -char *jumblr_zgetoperationresult(char *opid); - -char *jumblr_zgetoperationstatus(char *opid); - -char *jumblr_sendt_to_z(char *taddr,char *zaddr,double amount); - -char *jumblr_sendz_to_z(char *zaddrS,char *zaddrD,double amount); - -char *jumblr_sendz_to_t(char *zaddr,char *taddr,double amount); - -char *jumblr_zlistaddresses(); - -char *jumblr_zlistreceivedbyaddress(char *addr); - -char *jumblr_getreceivedbyaddress(char *addr); - -char *jumblr_importprivkey(char *wifstr); - -char *jumblr_zgetbalance(char *addr); - -char *jumblr_listunspent(char *coinaddr); - -char *jumblr_gettransaction(char *txidstr); - -int32_t jumblr_numvins(bits256 txid); - -int64_t jumblr_receivedby(char *addr); - -int64_t jumblr_balance(char *addr); - -int32_t jumblr_itemset(struct jumblr_item *ptr,cJSON *item,char *status); - -void jumblr_opidupdate(struct jumblr_item *ptr); - -void jumblr_prune(struct jumblr_item *ptr); - -void jumblr_zaddrinit(char *zaddr); - -void jumblr_opidsupdate(); - -uint64_t jumblr_increment(uint8_t r,int32_t height,uint64_t total,uint64_t biggest,uint64_t medium, uint64_t smallest); - -void jumblr_iteration(); diff --git a/src/komodo_kv.cpp b/src/komodo_kv.cpp index 0e51ef969d9..8a1600b744a 100644 --- a/src/komodo_kv.cpp +++ b/src/komodo_kv.cpp @@ -13,21 +13,98 @@ * * ******************************************************************************/ #include "komodo_kv.h" -#include "komodo_extern_globals.h" +#include "komodo_globals.h" #include "komodo_utils.h" // portable_mutex_lock -#include "komodo_curve25519.h" // komodo_kvsigverify +#include "komodo_curve25519.h" // for komodo_kvsigverify +#include -int32_t komodo_kvcmp(uint8_t *refvalue,uint16_t refvaluesize,uint8_t *value,uint16_t valuesize) +std::mutex kv_mutex; + +struct komodo_kv +{ + UT_hash_handle hh; + bits256 pubkey; + uint8_t *key; + uint8_t *value; + int32_t height; + uint32_t flags; + uint16_t keylen; + uint16_t valuesize; +}; + +komodo_kv *KOMODO_KV; + +/**** + * @brief build a private key from the public key and passphrase + * @param pubkeyp the public key + * @param passphrase the passphrase + * @return a private key + */ +uint256 komodo_kvprivkey(uint256 *pubkeyp,char *passphrase) +{ + uint256 privkey; + conv_NXTpassword((uint8_t *)&privkey,(uint8_t *)pubkeyp,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); + return privkey; +} + +/**** + * @brief sign + * @param buf what to sign + * @param len the length of buf + * @param _privkey the key to sign with + */ +uint256 komodo_kvsig(uint8_t *buf,int32_t len,uint256 _privkey) { - if ( refvalue == 0 && value == 0 ) - return(0); - else if ( refvalue == 0 || value == 0 ) - return(-1); - else if ( refvaluesize != valuesize ) - return(-1); - else return(memcmp(refvalue,value,valuesize)); + // get the private key in the format we need + bits256 privkey; + memcpy(&privkey,&_privkey,sizeof(privkey)); + // hash the contents of buf + bits256 hash; + vcalc_sha256(0,hash.bytes,buf,len); + bits256 otherpub = curve25519(hash,curve25519_basepoint9()); + bits256 pubkey = curve25519(privkey,curve25519_basepoint9()); + bits256 sig = curve25519_shared(privkey,otherpub); + bits256 checksig = curve25519_shared(hash,pubkey); // is this needed? + uint256 usig; + memcpy(&usig,&sig,sizeof(usig)); + return usig; +} + +/**** + * @brief verify the signature + * @param buf the message + * @param len the length of the message + * @param _pubkey who signed + * @param sig the signature + * @return -1 on error, otherwise 0 + */ +int32_t komodo_kvsigverify(uint8_t *buf,int32_t len,uint256 _pubkey,uint256 sig) +{ + bits256 hash; + bits256 checksig; + + static uint256 zeroes; + if (_pubkey == zeroes) + return -1; + + // get the public key in the right format + bits256 pubkey; + memcpy(&pubkey,&_pubkey,sizeof(pubkey)); + + // validate the signature + vcalc_sha256(0,hash.bytes,buf,len); + checksig = curve25519_shared(hash,pubkey); + if ( memcmp(&checksig,&sig,sizeof(sig)) != 0 ) + return -1; + + return 0; } +/*** + * @brief get duration from flags + * @param flags + * @returns duration in days + */ int32_t komodo_kvnumdays(uint32_t flags) { int32_t numdays; @@ -36,11 +113,23 @@ int32_t komodo_kvnumdays(uint32_t flags) return(numdays); } +/*** + * @brief calculate the duration in minutes + * @param flags + * @return the duration + */ int32_t komodo_kvduration(uint32_t flags) { return(komodo_kvnumdays(flags) * KOMODO_KVDURATION); } +/*** + * @brief calculate the required fee + * @param flags + * @param opretlen + * @param keylen + * @return the fee + */ uint64_t komodo_kvfee(uint32_t flags,int32_t opretlen,int32_t keylen) { int32_t numdays,k; uint64_t fee; @@ -52,20 +141,35 @@ uint64_t komodo_kvfee(uint32_t flags,int32_t opretlen,int32_t keylen) return(fee); } -int32_t komodo_kvsearch(uint256 *pubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen) +/*** + * @brief find a value + * @param[out] pubkeyp the found pubkey + * @param current_height current chain height + * @param[out] flagsp flags found within the value + * @param[out] heightp height + * @param[out] value the value + * @param key the key + * @param keylen the length of the key + * @return -1 on error, otherwise size of value + */ +int32_t komodo_kvsearch(uint256 *pubkeyp, int32_t current_height, uint32_t *flagsp, + int32_t *heightp, uint8_t value[IGUANA_MAXSCRIPTSIZE], uint8_t *key, int32_t keylen) { - struct komodo_kv *ptr; int32_t duration,retval = -1; *heightp = -1; *flagsp = 0; + + komodo_kv *ptr; + int32_t retval = -1; memset(pubkeyp,0,sizeof(*pubkeyp)); - portable_mutex_lock(&KOMODO_KV_mutex); + std::lock_guard lock(kv_mutex); + // look in hashtable for key HASH_FIND(hh,KOMODO_KV,key,keylen,ptr); - if ( ptr != 0 ) + if ( ptr != nullptr ) { - duration = komodo_kvduration(ptr->flags); - //fprintf(stderr,"duration.%d flags.%d current.%d ht.%d keylen.%d valuesize.%d\n",duration,ptr->flags,current_height,ptr->height,ptr->keylen,ptr->valuesize); + int32_t duration = komodo_kvduration(ptr->flags); if ( current_height > (ptr->height + duration) ) { + // entry has expired, remove it HASH_DELETE(hh,KOMODO_KV,ptr); if ( ptr->value != 0 ) free(ptr->value); @@ -75,38 +179,48 @@ int32_t komodo_kvsearch(uint256 *pubkeyp,int32_t current_height,uint32_t *flagsp } else { + // place values into parameters *heightp = ptr->height; *flagsp = ptr->flags; - int32_t i; for (i=0; i<32; i++) + for (int32_t i=0; i<32; i++) { - //printf("%02x",((uint8_t *)&ptr->pubkey)[31-i]); ((uint8_t *)pubkeyp)[i] = ((uint8_t *)&ptr->pubkey)[31-i]; } - //printf(" ptr->pubkey\n"); memcpy(pubkeyp,&ptr->pubkey,sizeof(*pubkeyp)); if ( (retval= ptr->valuesize) > 0 ) memcpy(value,ptr->value,retval); } - } //else fprintf(stderr,"couldnt find (%s)\n",(char *)key); - portable_mutex_unlock(&KOMODO_KV_mutex); + } if ( retval < 0 ) { // search rawmempool } - return(retval); + return retval; } +/**** + * @brief update value + * @param opretbuf what to write + * @param opretlen length of opretbuf + * @param value the value to be related to the key + */ void komodo_kvupdate(uint8_t *opretbuf,int32_t opretlen,uint64_t value) { static uint256 zeroes; - uint32_t flags; uint256 pubkey,refpubkey,sig; int32_t i,refvaluesize,hassig,coresize,haspubkey,height,kvheight; uint16_t keylen,valuesize,newflag = 0; uint8_t *key,*valueptr,keyvalue[IGUANA_MAXSCRIPTSIZE*8]; struct komodo_kv *ptr; char *transferpubstr,*tstr; uint64_t fee; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) // disable KV for KMD + + if (chainName.isKMD()) // disable KV for KMD return; + + // parse opretbuf + uint16_t keylen; + uint16_t valuesize; + int32_t height; + uint32_t flags; iguana_rwnum(0,&opretbuf[1],sizeof(keylen),&keylen); iguana_rwnum(0,&opretbuf[3],sizeof(valuesize),&valuesize); iguana_rwnum(0,&opretbuf[5],sizeof(height),&height); iguana_rwnum(0,&opretbuf[9],sizeof(flags),&flags); - key = &opretbuf[13]; + uint8_t *key = &opretbuf[13]; if ( keylen+13 > opretlen ) { static uint32_t counter; @@ -114,85 +228,104 @@ void komodo_kvupdate(uint8_t *opretbuf,int32_t opretlen,uint64_t value) fprintf(stderr,"komodo_kvupdate: keylen.%d + 13 > opretlen.%d, this can be ignored\n",keylen,opretlen); return; } - valueptr = &key[keylen]; - fee = komodo_kvfee(flags,opretlen,keylen); - //fprintf(stderr,"fee %.8f vs %.8f flags.%d keylen.%d valuesize.%d height.%d (%02x %02x %02x) (%02x %02x %02x)\n",(double)fee/COIN,(double)value/COIN,flags,keylen,valuesize,height,key[0],key[1],key[2],valueptr[0],valueptr[1],valueptr[2]); + uint8_t *valueptr = &key[keylen]; + uint64_t fee = komodo_kvfee(flags,opretlen,keylen); if ( value >= fee ) { - coresize = (int32_t)(sizeof(flags)+sizeof(height)+sizeof(keylen)+sizeof(valuesize)+keylen+valuesize+1); - if ( opretlen == coresize || opretlen == coresize+sizeof(uint256) || opretlen == coresize+2*sizeof(uint256) ) + // we have enough for the fee + int32_t coresize = (int32_t)(sizeof(flags) + +sizeof(height) + +sizeof(keylen) + +sizeof(valuesize) + +keylen+valuesize+1); + uint256 pubkey; + if ( opretlen == coresize + || opretlen == coresize+sizeof(uint256) + || opretlen == coresize+2*sizeof(uint256) ) { - memset(&pubkey,0,sizeof(pubkey)); - memset(&sig,0,sizeof(sig)); - if ( (haspubkey= (opretlen >= coresize+sizeof(uint256))) != 0 ) + // end could be pubkey or pubkey+signature + if ( opretlen >= coresize+sizeof(uint256) ) { - for (i=0; i<32; i++) + for (uint8_t i=0; i<32; i++) ((uint8_t *)&pubkey)[i] = opretbuf[coresize+i]; } - if ( (hassig= (opretlen == coresize+sizeof(uint256)*2)) != 0 ) + uint256 sig; + if ( opretlen == coresize+sizeof(uint256)*2 ) { - for (i=0; i<32; i++) + for (uint8_t i=0; i<32; i++) ((uint8_t *)&sig)[i] = opretbuf[coresize+sizeof(uint256)+i]; } + + uint8_t keyvalue[IGUANA_MAXSCRIPTSIZE*8]; memcpy(keyvalue,key,keylen); - if ( (refvaluesize= komodo_kvsearch((uint256 *)&refpubkey,height,&flags,&kvheight,&keyvalue[keylen],key,keylen)) >= 0 ) + uint256 refpubkey; + int32_t kvheight; + int32_t refvaluesize = komodo_kvsearch(&refpubkey,height, + &flags,&kvheight,&keyvalue[keylen],key,keylen); + if ( refvaluesize >= 0 ) { - if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 ) + if ( zeroes != refpubkey ) { + // validate signature if ( komodo_kvsigverify(keyvalue,keylen+refvaluesize,refpubkey,sig) < 0 ) { - //fprintf(stderr,"komodo_kvsigverify error [%d]\n",coresize-13); return; } } } - portable_mutex_lock(&KOMODO_KV_mutex); + // with validation complete, update internal storage + std::lock_guard lock(kv_mutex); + komodo_kv *ptr; + bool newflag = false; HASH_FIND(hh,KOMODO_KV,key,keylen,ptr); if ( ptr != 0 ) { - //fprintf(stderr,"(%s) already there\n",(char *)key); - //if ( (ptr->flags & KOMODO_KVPROTECTED) != 0 ) + // We are updating an existing entry + // if we are doing a transfer, log it and insert the pubkey + char *tstr = (char *)"transfer:"; + char *transferpubstr = (char *)&valueptr[strlen(tstr)]; + if ( strncmp(tstr,(char *)valueptr,strlen(tstr)) == 0 && is_hexstr(transferpubstr,0) == 64 ) { - tstr = (char *)"transfer:"; - transferpubstr = (char *)&valueptr[strlen(tstr)]; - if ( strncmp(tstr,(char *)valueptr,strlen(tstr)) == 0 && is_hexstr(transferpubstr,0) == 64 ) - { - printf("transfer.(%s) to [%s]? ishex.%d\n",key,transferpubstr,is_hexstr(transferpubstr,0)); - for (i=0; i<32; i++) - ((uint8_t *)&pubkey)[31-i] = _decode_hex(&transferpubstr[i*2]); - } + printf("transfer.(%s) to [%s]? ishex.%d\n",key,transferpubstr,is_hexstr(transferpubstr,0)); + for (uint8_t i=0; i<32; i++) + ((uint8_t *)&pubkey)[31-i] = _decode_hex(&transferpubstr[i*2]); } } else if ( ptr == 0 ) { - ptr = (struct komodo_kv *)calloc(1,sizeof(*ptr)); + // add a new entry to the hashtable + ptr = (komodo_kv *)calloc(1,sizeof(*ptr)); ptr->key = (uint8_t *)calloc(1,keylen); ptr->keylen = keylen; memcpy(ptr->key,key,keylen); - newflag = 1; + newflag = true; HASH_ADD_KEYPTR(hh,KOMODO_KV,ptr->key,ptr->keylen,ptr); - //fprintf(stderr,"KV add.(%s) (%s)\n",ptr->key,valueptr); } - if ( newflag != 0 || (ptr->flags & KOMODO_KVPROTECTED) == 0 ) + if ( newflag || (ptr->flags & KOMODO_KVPROTECTED) == 0 ) // can we edit the value? { - if ( ptr->value != 0 ) - free(ptr->value), ptr->value = 0; + if ( ptr->value != nullptr ) + { + // clear out old value + free(ptr->value); + ptr->value = nullptr; + } if ( (ptr->valuesize= valuesize) != 0 ) { + // add value ptr->value = (uint8_t *)calloc(1,valuesize); memcpy(ptr->value,valueptr,valuesize); } - } else fprintf(stderr,"newflag.%d zero or protected %d\n",newflag,(ptr->flags & KOMODO_KVPROTECTED)); - /*for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&ptr->pubkey)[i]); - printf(" <- "); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&pubkey)[i]); - printf(" new pubkey\n");*/ + } + else + fprintf(stderr,"newflag.%d zero or protected %d\n",(uint16_t)newflag, + (ptr->flags & KOMODO_KVPROTECTED)); memcpy(&ptr->pubkey,&pubkey,sizeof(ptr->pubkey)); ptr->height = height; ptr->flags = flags; // jl777 used to or in KVPROTECTED - portable_mutex_unlock(&KOMODO_KV_mutex); - } else fprintf(stderr,"KV update size mismatch %d vs %d\n",opretlen,coresize); - } else fprintf(stderr,"not enough fee\n"); + } + else + fprintf(stderr,"KV update size mismatch %d vs %d\n",opretlen,coresize); + } + else + fprintf(stderr,"not enough fee\n"); } diff --git a/src/komodo_kv.h b/src/komodo_kv.h index 86c6904392a..c6cdf4916f3 100644 --- a/src/komodo_kv.h +++ b/src/komodo_kv.h @@ -13,18 +13,70 @@ * * ******************************************************************************/ #pragma once - +#include "uint256.h" #include "komodo_defs.h" -#include "hex.h" - -int32_t komodo_kvcmp(uint8_t *refvalue,uint16_t refvaluesize,uint8_t *value,uint16_t valuesize); - -int32_t komodo_kvnumdays(uint32_t flags); +#include +/*** + * @brief calculate the duration in minutes + * @param flags + * @return the duration + */ int32_t komodo_kvduration(uint32_t flags); +/*** + * @brief calculate the required fee + * @param flags + * @param opretlen + * @param keylen + * @return the fee + */ uint64_t komodo_kvfee(uint32_t flags,int32_t opretlen,int32_t keylen); -int32_t komodo_kvsearch(uint256 *pubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); +/*** + * @brief find a value + * @param[out] pubkeyp the found pubkey + * @param current_height current chain height + * @param[out] flagsp flags found within the value + * @param[out] heightp height + * @param[out] value the value + * @param key the key + * @param keylen the length of the key + * @return -1 on error, otherwise size of value + */ +int32_t komodo_kvsearch(uint256 *pubkeyp,int32_t current_height,uint32_t *flagsp, + int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); +/**** + * @brief update value + * @param opretbuf what to write + * @param opretlen length of opretbuf + * @param value the value to be related to the key + */ void komodo_kvupdate(uint8_t *opretbuf,int32_t opretlen,uint64_t value); + +/**** + * @brief build a private key from the public key and passphrase + * @param pubkeyp the public key + * @param passphrase the passphrase + * @return a private key + */ +uint256 komodo_kvprivkey(uint256 *pubkeyp,char *passphrase); + +/**** + * @brief sign + * @param buf what to sign + * @param len the length of buf + * @param _privkey the key to sign with + */ +uint256 komodo_kvsig(uint8_t *buf,int32_t len,uint256 _privkey); + +/**** + * @brief verify the signature + * @param buf the message + * @param len the length of the message + * @param _pubkey who signed + * @param sig the signature + * @return -1 on error, otherwise 0 + */ +int32_t komodo_kvsigverify(uint8_t *buf,int32_t len,uint256 _pubkey,uint256 sig); diff --git a/src/komodo_nSPV.h b/src/komodo_nSPV.h index fe4d784cb9f..cc2c0748143 100644 --- a/src/komodo_nSPV.h +++ b/src/komodo_nSPV.h @@ -441,8 +441,10 @@ int32_t NSPV_rwremoterpcresp(int32_t rwflag,uint8_t *serialized,struct NSPV_remo void NSPV_remoterpc_purge(struct NSPV_remoterpcresp *ptr) { - if ( ptr != 0 ) + if ( ptr != 0 ) { + if (ptr->json) free (ptr->json); memset(ptr,0,sizeof(*ptr)); + } } // useful utility functions @@ -559,7 +561,7 @@ int32_t NSPV_notariescount(CTransaction tx,uint8_t elected[64][33]) return(numsigs); } -uint256 NSPV_opretextract(int32_t *heightp,uint256 *blockhashp,char *symbol,std::vector opret,uint256 txid) +uint256 NSPV_opretextract(int32_t *heightp,uint256 *blockhashp,const char *symbol,std::vector opret,uint256 txid) { uint256 desttxid; int32_t i; iguana_rwnum(0,&opret[32],sizeof(*heightp),heightp); @@ -574,15 +576,14 @@ uint256 NSPV_opretextract(int32_t *heightp,uint256 *blockhashp,char *symbol,std: int32_t NSPV_notarizationextract(int32_t verifyntz,int32_t *ntzheightp,uint256 *blockhashp,uint256 *desttxidp,CTransaction tx) { - int32_t numsigs=0; uint8_t elected[64][33]; char *symbol; std::vector opret; uint32_t nTime; + int32_t numsigs=0; uint8_t elected[64][33]; std::vector opret; uint32_t nTime; if ( tx.vout.size() >= 2 ) { - symbol = (ASSETCHAINS_SYMBOL[0] == 0) ? (char *)"KMD" : ASSETCHAINS_SYMBOL; GetOpReturnData(tx.vout[1].scriptPubKey,opret); if ( opret.size() >= 32*2+4 ) { //sleep(1); // needed to avoid no pnodes error - *desttxidp = NSPV_opretextract(ntzheightp,blockhashp,symbol,opret,tx.GetHash()); + *desttxidp = NSPV_opretextract(ntzheightp,blockhashp,chainName.ToString().c_str(),opret,tx.GetHash()); nTime = NSPV_blocktime(*ntzheightp); komodo_notaries(elected,*ntzheightp,nTime); if ( verifyntz != 0 && (numsigs= NSPV_fastnotariescount(tx,elected,nTime)) < 12 ) diff --git a/src/komodo_nSPV_defs.h b/src/komodo_nSPV_defs.h index 40d9dc02229..307a29ea907 100644 --- a/src/komodo_nSPV_defs.h +++ b/src/komodo_nSPV_defs.h @@ -22,7 +22,6 @@ #define NSPV_POLLMICROS 50000 #define NSPV_MAXVINS 64 #define NSPV_AUTOLOGOUT 777 -#define NSPV_BRANCHID 0x76b809bb // nSPV defines and struct definitions with serialization and purge functions @@ -55,6 +54,16 @@ #define NSPV_REMOTERPC 0x14 #define NSPV_REMOTERPCRESP 0x15 +extern int32_t KOMODO_NSPV; + +#ifndef KOMODO_NSPV_FULLNODE +#define KOMODO_NSPV_FULLNODE (KOMODO_NSPV <= 0) +#endif + +#ifndef KOMODO_NSPV_SUPERLITE +#define KOMODO_NSPV_SUPERLITE (KOMODO_NSPV > 0) +#endif + int32_t NSPV_gettransaction(int32_t skipvalidation,int32_t vout,uint256 txid,int32_t height,CTransaction &tx,uint256 &hashblock,int32_t &txheight,int32_t ¤theight,int64_t extradata,uint32_t tiptime,int64_t &rewardsum); UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis); extern uint256 SIG_TXHASH; @@ -185,8 +194,9 @@ struct NSPV_CCmtxinfo struct NSPV_remoterpcresp { + NSPV_remoterpcresp() { method[0] = '\0'; json = nullptr; } char method[64]; - char json[11000]; + char *json; }; #endif // KOMODO_NSPV_DEFSH diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index ccf595eb0a8..7176977870d 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -21,6 +21,7 @@ #include "notarisationdb.h" #include "rpc/server.h" +#include "komodo_bitcoind.h" static std::map nspv_remote_commands = {{"channelsopen", true},{"channelspayment", true},{"channelsclose", true},{"channelsrefund", true}, {"channelslist", true},{"channelsinfo", true},{"oraclescreate", true},{"oraclesfund", true},{"oraclesregister", true},{"oraclessubscribe", true}, @@ -36,19 +37,19 @@ struct NSPV_ntzargs int32_t NSPV_notarization_find(struct NSPV_ntzargs *args,int32_t height,int32_t dir) { - int32_t ntzheight = 0; uint256 hashBlock; CTransaction tx; Notarisation nota; char *symbol; std::vector opret; - symbol = (ASSETCHAINS_SYMBOL[0] == 0) ? (char *)"KMD" : ASSETCHAINS_SYMBOL; + int32_t ntzheight = 0; uint256 hashBlock; CTransaction tx; Notarisation nota; + std::vector opret; memset(args,0,sizeof(*args)); if ( dir > 0 ) height += 10; - if ( (args->txidht= ScanNotarisationsDB(height,symbol,1440,nota)) == 0 ) + if ( (args->txidht= ScanNotarisationsDB(height,chainName.ToString(),1440,nota)) == 0 ) return(-1); args->txid = nota.first; if ( !GetTransaction(args->txid,tx,hashBlock,false) || tx.vout.size() < 2 ) return(-2); GetOpReturnData(tx.vout[1].scriptPubKey,opret); if ( opret.size() >= 32*2+4 ) - args->desttxid = NSPV_opretextract(&args->ntzheight,&args->blockhash,symbol,opret,args->txid); + args->desttxid = NSPV_opretextract(&args->ntzheight,&args->blockhash,chainName.ToString().c_str(),opret,args->txid); return(args->ntzheight); } @@ -90,7 +91,7 @@ int32_t NSPV_ntzextract(struct NSPV_ntz *ptr,uint256 ntztxid,int32_t txidht,uint int32_t NSPV_getntzsresp(struct NSPV_ntzsresp *ptr,int32_t origreqheight) { struct NSPV_ntzargs prev,next; int32_t reqheight = origreqheight; - if ( reqheight < chainActive.LastTip()->nHeight ) + if ( reqheight < chainActive.Tip()->nHeight ) reqheight++; if ( NSPV_notarized_bracket(&prev,&next,reqheight) == 0 ) { @@ -123,7 +124,7 @@ int32_t NSPV_setequihdr(struct NSPV_equihdr *hdr,int32_t height) hdr->nTime = pindex->nTime; hdr->nBits = pindex->nBits; hdr->nNonce = pindex->nNonce; - memcpy(hdr->nSolution,&pindex->nSolution[0],sizeof(hdr->nSolution)); + memcpy(hdr->nSolution,&pindex->GetBlockHeader().nSolution[0],sizeof(hdr->nSolution)); return(sizeof(*hdr)); } return(-1); @@ -132,7 +133,7 @@ int32_t NSPV_setequihdr(struct NSPV_equihdr *hdr,int32_t height) int32_t NSPV_getinfo(struct NSPV_inforesp *ptr,int32_t reqheight) { int32_t prevMoMheight,len = 0; CBlockIndex *pindex, *pindex2; struct NSPV_ntzsresp pair; - if ( (pindex= chainActive.LastTip()) != 0 ) + if ( (pindex= chainActive.Tip()) != 0 ) { ptr->height = pindex->nHeight; ptr->blockhash = pindex->GetBlockHash(); @@ -167,7 +168,7 @@ int32_t NSPV_getaddressutxos(struct NSPV_utxosresp *ptr,char *coinaddr,bool isCC skipcount = 0; if ( (ptr->numutxos= (int32_t)unspentOutputs.size()) >= 0 && ptr->numutxos < maxlen ) { - tipheight = chainActive.LastTip()->nHeight; + tipheight = chainActive.Tip()->nHeight; ptr->nodeheight = tipheight; if ( skipcount >= ptr->numutxos ) skipcount = ptr->numutxos-1; @@ -185,7 +186,7 @@ int32_t NSPV_getaddressutxos(struct NSPV_utxosresp *ptr,char *coinaddr,bool isCC ptr->utxos[ind].vout = (int32_t)it->first.index; ptr->utxos[ind].satoshis = it->second.satoshis; ptr->utxos[ind].height = it->second.blockHeight; - if ( ASSETCHAINS_SYMBOL[0] == 0 && it->second.satoshis >= 10*COIN ) + if ( chainName.isKMD() && it->second.satoshis >= 10*COIN ) { ptr->utxos[n].extradata = komodo_accrued_interest(&txheight,&locktime,ptr->utxos[ind].txid,ptr->utxos[ind].vout,ptr->utxos[ind].height,ptr->utxos[ind].satoshis,tipheight); interest += ptr->utxos[ind].extradata; @@ -333,7 +334,7 @@ int32_t NSPV_getccmoduleutxos(struct NSPV_utxosresp *ptr, char *coinaddr, int64_ ptr->numutxos = 0; strncpy(ptr->coinaddr, coinaddr, sizeof(ptr->coinaddr) - 1); ptr->CCflag = 1; - tipheight = chainActive.LastTip()->nHeight; + tipheight = chainActive.Tip()->nHeight; ptr->nodeheight = tipheight; // will be checked in libnspv //} @@ -441,7 +442,7 @@ int32_t NSPV_getaddresstxids(struct NSPV_txidsresp *ptr,char *coinaddr,bool isCC int32_t maxlen,txheight,ind=0,n = 0,len = 0; CTransaction tx; uint256 hashBlock; std::vector > txids; SetCCtxids(txids,coinaddr,isCC); - ptr->nodeheight = chainActive.LastTip()->nHeight; + ptr->nodeheight = chainActive.Tip()->nHeight; maxlen = MAX_BLOCK_SIZE(ptr->nodeheight) - 512; maxlen /= sizeof(*ptr->txids); strncpy(ptr->coinaddr,coinaddr,sizeof(ptr->coinaddr)-1); @@ -519,7 +520,7 @@ int32_t NSPV_mempoolfuncs(bits256 *satoshisp,int32_t *vindexp,std::vector> e; ss >> f; ss >> tmp_txid;); if (e!=eval || (txid!=zeroid && txid!=tmp_txid) || (func!=0 && f!=func)) continue; break; @@ -624,7 +625,7 @@ int32_t NSPV_mempoolfuncs(bits256 *satoshisp,int32_t *vindexp,std::vector txids; bits256 satoshis; uint256 tmp,tmpdest; int32_t i,len = 0; - ptr->nodeheight = chainActive.LastTip()->nHeight; + ptr->nodeheight = chainActive.Tip()->nHeight; strncpy(ptr->coinaddr,coinaddr,sizeof(ptr->coinaddr)-1); ptr->CCflag = isCC; ptr->txid = txid; @@ -689,6 +690,9 @@ int32_t NSPV_remoterpc(struct NSPV_remoterpcresp *ptr,char *json,int n) { rpc_result = JSONRPCReplyObj(result, NullUniValue, jreq.id); response=rpc_result.write(); + ptr->json = (char*)malloc(response.size()); + if (ptr->json == nullptr) + throw JSONRPCError(RPC_OUT_OF_MEMORY, "Cannot allocate memory for response"); memcpy(ptr->json,response.c_str(),response.size()); len+=response.size(); return (len); @@ -710,6 +714,7 @@ int32_t NSPV_remoterpc(struct NSPV_remoterpcresp *ptr,char *json,int n) rpc_result = JSONRPCReplyObj(NullUniValue,JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id); response=rpc_result.write(); } + ptr->json = (char*)malloc(response.size()); // only not a big size error responses are here memcpy(ptr->json,response.c_str(),response.size()); len+=response.size(); return (len); diff --git a/src/komodo_nSPV_superlite.h b/src/komodo_nSPV_superlite.h index 3d56d44ba8a..350d59808b8 100644 --- a/src/komodo_nSPV_superlite.h +++ b/src/komodo_nSPV_superlite.h @@ -23,7 +23,7 @@ CAmount AmountFromValue(const UniValue& value); -int32_t bitcoin_base58decode(uint8_t *data,char *coinaddr); +int32_t bitcoin_base58decode(uint8_t *data,const char *coinaddr); uint32_t NSPV_lastinfo,NSPV_logintime,NSPV_tiptime; CKey NSPV_key; @@ -391,7 +391,7 @@ UniValue NSPV_utxoresp_json(struct NSPV_utxoresp *utxos,int32_t numutxos) item.push_back(Pair("txid",utxos[i].txid.GetHex())); item.push_back(Pair("vout",(int64_t)utxos[i].vout)); item.push_back(Pair("value",(double)utxos[i].satoshis/COIN)); - if ( ASSETCHAINS_SYMBOL[0] == 0 ) + if ( chainName.isKMD() ) item.push_back(Pair("interest",(double)utxos[i].extradata/COIN)); array.push_back(item); } @@ -408,7 +408,7 @@ UniValue NSPV_utxosresp_json(struct NSPV_utxosresp *ptr) result.push_back(Pair("height",(int64_t)ptr->nodeheight)); result.push_back(Pair("numutxos",(int64_t)ptr->numutxos)); result.push_back(Pair("balance",(double)ptr->total/COIN)); - if ( ASSETCHAINS_SYMBOL[0] == 0 ) + if ( chainName.isKMD() ) result.push_back(Pair("interest",(double)ptr->interest/COIN)); result.push_back(Pair("filter",(int64_t)ptr->filter)); result.push_back(Pair("lastpeer",NSPV_lastpeer)); diff --git a/src/komodo_nSPV_wallet.h b/src/komodo_nSPV_wallet.h index f745629b747..35e0e6b132a 100644 --- a/src/komodo_nSPV_wallet.h +++ b/src/komodo_nSPV_wallet.h @@ -17,8 +17,11 @@ #ifndef KOMODO_NSPVWALLET_H #define KOMODO_NSPVWALLET_H +#include "komodo_interest.h" + // nSPV wallet uses superlite functions (and some komodod built in functions) to implement nSPV_spend -extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); +#include "komodo_bitcoind.h" +#include "rpc/rawtransaction.h" int32_t NSPV_validatehdrs(struct NSPV_ntzsproofresp *ptr) { @@ -83,7 +86,7 @@ int32_t NSPV_gettransaction(int32_t skipvalidation,int32_t vout,uint256 txid,int retval = -2001; else if ( skipvalidation == 0 && ptr->unspentvalue <= 0 ) retval = -2002; - else if ( ASSETCHAINS_SYMBOL[0] == 0 && tiptime != 0 ) + else if ( chainName.isKMD() && tiptime != 0 ) { rewards = komodo_interestnew(height,tx.vout[vout].nValue,tx.nLockTime,tiptime); if ( rewards != extradata ) @@ -236,6 +239,8 @@ int64_t NSPV_addinputs(struct NSPV_utxoresp *used,CMutableTransaction &mtx,int64 return(0); } +#define NSPV_BRANCHID 0x76b809bb + bool NSPV_SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScript scriptPubKey,uint32_t nTime) { CTransaction txNewConst(mtx); SignatureData sigdata; CBasicKeyStore keystore; int64_t branchid = NSPV_BRANCHID; @@ -388,8 +393,8 @@ UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis) // what its a mtx.nExpiryHeight = 0; mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; mtx.nVersion = SAPLING_TX_VERSION; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) { - if ( !komodo_hardfork_active((uint32_t)chainActive.LastTip()->nTime) ) + if ( chainName.isKMD() ) { + if ( !komodo_hardfork_active((uint32_t)chainActive.Tip()->nTime) ) mtx.nLockTime = (uint32_t)time(NULL) - 777; else mtx.nLockTime = (uint32_t)chainActive.Tip()->GetMedianTimePast(); @@ -407,7 +412,7 @@ UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis) // what its a return(result); } hex = NSPV_signtx(rewardsum,interestsum,retcodes,mtx,txfee,opret,used); - if ( ASSETCHAINS_SYMBOL[0] == 0 ) + if ( chainName.isKMD() ) { char numstr[64]; sprintf(numstr,"%.8f",(double)interestsum/COIN); diff --git a/src/komodo_notary.cpp b/src/komodo_notary.cpp index dec27f3abe1..3cc9dde9663 100644 --- a/src/komodo_notary.cpp +++ b/src/komodo_notary.cpp @@ -13,89 +13,135 @@ * * ******************************************************************************/ #include "komodo_notary.h" +#include "komodo_globals.h" #include "komodo_extern_globals.h" #include "komodo.h" // komodo_stateupdate() #include "komodo_structs.h" // KOMODO_NOTARIES_HARDCODED #include "komodo_utils.h" // komodo_stateptr +#include "komodo_bitcoind.h" + +//struct knotaries_entry *Pubkeys; // todo remove + +// statics used within this .cpp for caching purposes +static int didinit; // see komodo_init +static uint8_t kmd_pubkeys[NUM_KMD_SEASONS][64][33]; // see komodo_notaries +static int32_t hwmheight; // highest height ever passed to komodo_notariesinit +static int32_t hadnotarization; // used in komodo_dpowconfs +static bool didinit_NOTARIES[NUM_KMD_SEASONS]; // komodo_notaries() -const char *Notaries_genesis[][2] = -{ - { "jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, - { "jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" }, - { "pondsea_SH", "02209073bc0943451498de57f802650311b1f12aa6deffcd893da198a544c04f36" }, - { "crackers_EU", "0340c66cf2c41c41efb420af57867baa765e8468c12aa996bfd816e1e07e410728" }, - { "pondsea_EU", "0225aa6f6f19e543180b31153d9e6d55d41bc7ec2ba191fd29f19a2f973544e29d" }, - { "locomb_EU", "025c6d26649b9d397e63323d96db42a9d3caad82e1d6076970efe5056c00c0779b" }, - { "fullmoon_AE", "0204a908350b8142698fdb6fabefc97fe0e04f537adc7522ba7a1e8f3bec003d4a" }, - { "movecrypto_EU", "021ab53bc6cf2c46b8a5456759f9d608966eff87384c2b52c0ac4cc8dd51e9cc42" }, - { "badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, - { "crackers_NA", "029e1c01131974f4cd3f564cc0c00eb87a0f9721043fbc1ca60f9bd0a1f73f64a1" }, - { "proto_EU", "03681ffdf17c8f4f0008cefb7fa0779c5e888339cdf932f0974483787a4d6747c1" }, // 10 - { "jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, - { "farl4web_EU", "035caa40684ace968677dca3f09098aa02b70e533da32390a7654c626e0cf908e1" }, - { "nxtswe_EU", "032fb104e5eaa704a38a52c126af8f67e870d70f82977e5b2f093d5c1c21ae5899" }, - { "traderbill_EU", "03196e8de3e2e5d872f31d79d6a859c8704a2198baf0af9c7b21e29656a7eb455f" }, - { "vanbreuk_EU", "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" }, // 15 - { "titomane_EU", "03517fcac101fed480ae4f2caf775560065957930d8c1facc83e30077e45bdd199" }, - { "supernet_AE", "029d93ef78197dc93892d2a30e5a54865f41e0ca3ab7eb8e3dcbc59c8756b6e355" }, - { "supernet_EU", "02061c6278b91fd4ac5cab4401100ffa3b2d5a277e8f71db23401cc071b3665546" }, - { "supernet_NA", "033c073366152b6b01535e15dd966a3a8039169584d06e27d92a69889b720d44e1" }, - { "yassin_EU", "033fb7231bb66484081952890d9a03f91164fb27d392d9152ec41336b71b15fbd0" }, // 20 - { "durerus_EU", "02bcbd287670bdca2c31e5d50130adb5dea1b53198f18abeec7211825f47485d57" }, - { "badass_SH", "026b49dd3923b78a592c1b475f208e23698d3f085c4c3b4906a59faf659fd9530b" }, - { "badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, - { "pondsea_NA", "031bcfdbb62268e2ff8dfffeb9ddff7fe95fca46778c77eebff9c3829dfa1bb411" }, - { "rnr_EU", "0287aa4b73988ba26cf6565d815786caf0d2c4af704d7883d163ee89cd9977edec" }, - { "crackers_SH", "02313d72f9a16055737e14cfc528dcd5d0ef094cfce23d0348fe974b6b1a32e5f0" }, - { "grewal_SH", "03212a73f5d38a675ee3cdc6e82542a96c38c3d1c79d25a1ed2e42fcf6a8be4e68" }, - { "polycryptoblock_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, - { "titomane_NA", "0387046d9745414fb58a0fa3599078af5073e10347e4657ef7259a99cb4f10ad47" }, - { "titomane_AE", "03cda6ca5c2d02db201488a54a548dbfc10533bdc275d5ea11928e8d6ab33c2185" }, - { "kolo_EU", "03f5c08dadffa0ffcafb8dd7ffc38c22887bd02702a6c9ac3440deddcf2837692b" }, - { "artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, - { "eclips_EU", "0339369c1f5a2028d44be7be6f8ec3b907fdec814f87d2dead97cab4edb71a42e9" }, - { "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" }, -}; +/**** + * @brief get the kmd season based on height (used on the KMD chain) + * @param height the chain height + * @returns the KMD season (returns 0 if the height is above the range) + */ int32_t getkmdseason(int32_t height) { if ( height <= KMD_SEASON_HEIGHTS[0] ) - return(1); + return 1; for (int32_t i = 1; i < NUM_KMD_SEASONS; i++) { if ( height <= KMD_SEASON_HEIGHTS[i] && height > KMD_SEASON_HEIGHTS[i-1] ) - return(i+1); + return i+1; } - return(0); + return 0; } +/**** + * @brief get the season based on timestamp (used for alternate chains) + * @param timestamp the time + * @returns the KMD season (returns 0 if timestamp is above the range) + */ int32_t getacseason(uint32_t timestamp) { if ( timestamp <= KMD_SEASON_TIMESTAMPS[0] ) - return(1); + return 1; for (int32_t i = 1; i < NUM_KMD_SEASONS; i++) { if ( timestamp <= KMD_SEASON_TIMESTAMPS[i] && timestamp > KMD_SEASON_TIMESTAMPS[i-1] ) - return(i+1); + return i+1; + } + return 0; +} + +/***** + * 2 Helpers for unit tests that reset statics (among other things) + * DO NOT USE for anything other than unit tests + */ +//void undo_init_STAKED(); // see notaries_staked.cpp +/*void undo_init_notaries() +{ + undo_init_STAKED(); + memset(didinit_notaries, 0, NUM_KMD_SEASONS * sizeof(bool) ); + if (Pubkeys != nullptr) + { + free(Pubkeys); + Pubkeys = nullptr; + } + hwmheight = 0; + didinit = false; +}*/ + +/**** + * Calculate the height index (how notaries are stored) based on the height + * @param height the height + * @returns the height index + */ +int32_t ht_index_from_height(int32_t height) +{ + int32_t htind = height / KOMODO_ELECTION_GAP; + if ( htind >= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) + htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; + return htind; +} + + +//char NOTARY_ADDRESSES[NUM_KMD_SEASONS][64][64]; //todo remove + +// ARRR notary exception +int32_t komodo_isnotaryvout(char *coinaddr,uint32_t tiptime) // from ac_private chains only +{ + int32_t season = getacseason(tiptime); + if ( NOTARY_ADDRESSES[season-1][0][0] == 0 ) + { + uint8_t pubkeys[64][33]; + komodo_notaries(pubkeys,0,tiptime); + } + if ( strcmp(coinaddr,CRYPTO777_KMDADDR) == 0 ) + return(1); + for (int32_t i = 0; i < NUM_KMD_NOTARIES; i++) + { + if ( strcmp(coinaddr,NOTARY_ADDRESSES[season-1][i]) == 0 ) + { + //fprintf(stderr, "coinaddr.%s notaryaddress[%i].%s\n",coinaddr,i,NOTARY_ADDRESSES[season-1][i]); + return(1); + } } return(0); } +/*** + * @brief Given a height or timestamp, get the appropriate notary keys + * @param[out] pubkeys the results + * @param[in] height the height + * @param[in] timestamp the timestamp + * @returns the number of notaries + */ int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp) { - int32_t i,htind,n; uint64_t mask = 0; struct knotary_entry *kp,*tmp; - static uint8_t kmd_pubkeys[NUM_KMD_SEASONS][64][33],didinit[NUM_KMD_SEASONS]; - - if ( timestamp == 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - timestamp = komodo_heightstamp(height); - else if ( ASSETCHAINS_SYMBOL[0] == 0 ) - timestamp = 0; + // calculate timestamp if necessary (only height passed in and non-KMD chain) + // TODO: check if this logic changed okay + if ( chainName.isKMD() ) + timestamp = 0; // For KMD, we always use height + else if ( timestamp == 0 ) + timestamp = komodo_heightstamp(height); // derive the timestamp from the passed-in height - // If this chain is not a staked chain, use the normal Komodo logic to determine notaries. This allows KMD to still sync and use its proper pubkeys for dPoW. - if ( is_STAKED(ASSETCHAINS_SYMBOL) == 0 ) + // If this chain is not a staked chain, use the normal Komodo logic to determine notaries. + // This allows KMD to still sync and use its proper pubkeys for dPoW. + if ( is_STAKED(chainName.symbol()) == 0 ) { int32_t kmd_season = 0; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) + if ( chainName.isKMD() ) { // This is KMD, use block heights to determine the KMD notary season.. if ( height >= KOMODO_NOTARIES_HARDCODED ) @@ -108,17 +154,17 @@ int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestam } if ( kmd_season != 0 ) { - if ( didinit[kmd_season-1] == 0 ) + if ( !didinit_NOTARIES[kmd_season-1] ) { - for (i=0; i= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) - htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; - if ( Pubkeys == 0 ) + if ( Pubkeys == nullptr ) { komodo_init(height); - //printf("Pubkeys.%p htind.%d vs max.%d\n",Pubkeys,htind,KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP); } + int32_t htind = ht_index_from_height(height); + std::lock_guard lock(komodo_mutex); + int32_t n = Pubkeys[htind].numnotaries; + uint64_t mask = 0; + knotary_entry *kp; + knotary_entry *tmp; + HASH_ITER(hh,Pubkeys[htind].Notaries,kp,tmp) { - std::lock_guard lock(komodo_mutex); - n = Pubkeys[htind].numnotaries; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - fprintf(stderr,"%s height.%d t.%u genesis.%d\n",ASSETCHAINS_SYMBOL,height,timestamp,n); - HASH_ITER(hh,Pubkeys[htind].Notaries,kp,tmp) + if ( kp->notaryid < n ) { - if ( kp->notaryid < n ) - { - mask |= (1LL << kp->notaryid); - memcpy(pubkeys[kp->notaryid],kp->pubkey,33); - } else printf("illegal notaryid.%d vs n.%d\n",kp->notaryid,n); - } + mask |= (1LL << kp->notaryid); + memcpy(pubkeys[kp->notaryid],kp->pubkey,33); + } + else + printf("illegal notaryid.%d vs n.%d\n",kp->notaryid,n); } if ( (n < 64 && mask == ((1LL << n)-1)) || (n == 64 && mask == 0xffffffffffffffffLL) ) - return(n); + return n; printf("error retrieving notaries ht.%d got mask.%llx for n.%d\n",height,(long long)mask,n); - return(-1); + return -1; } int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp) @@ -178,53 +222,49 @@ int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t hei int32_t komodo_ratify_threshold(int32_t height,uint64_t signedmask) { - int32_t htind,numnotaries,i,wt = 0; - htind = height / KOMODO_ELECTION_GAP; - if ( htind >= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) - htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; + int32_t numnotaries, i, wt = 0; + int32_t htind = ht_index_from_height(height); numnotaries = Pubkeys[htind].numnotaries; for (i=0; i (numnotaries >> 1) || (wt > 7 && (signedmask & 1) != 0) ) - return(1); - else return(0); + return 1; + return 0; } +/***** + * Push keys into the notary collection + * @param origheight the height where these notaries begin + * @param pubkeys the notaries' public keys + * @param num the number of keys in pubkeys + */ void komodo_notarysinit(int32_t origheight,uint8_t pubkeys[64][33],int32_t num) { - static int32_t hwmheight; - int32_t k,i,htind,height; struct knotary_entry *kp; struct knotaries_entry N; if ( Pubkeys == 0 ) - Pubkeys = (struct knotaries_entry *)calloc(1 + (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP),sizeof(*Pubkeys)); + Pubkeys = (knotaries_entry *)calloc(1 + (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP),sizeof(*Pubkeys)); + knotaries_entry N; memset(&N,0,sizeof(N)); + // calculate the height + int32_t htind = 0; // height index (number of elections so far) if ( origheight > 0 ) { - height = (origheight + KOMODO_ELECTION_GAP/2); + int32_t height = (origheight + KOMODO_ELECTION_GAP/2); height /= KOMODO_ELECTION_GAP; height = ((height + 1) * KOMODO_ELECTION_GAP); - htind = (height / KOMODO_ELECTION_GAP); - if ( htind >= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) - htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; - //printf("htind.%d activation %d from %d vs %d | hwmheight.%d %s\n",htind,height,origheight,(((origheight+KOMODO_ELECTION_GAP/2)/KOMODO_ELECTION_GAP)+1)*KOMODO_ELECTION_GAP,hwmheight,ASSETCHAINS_SYMBOL); - } else htind = 0; + htind = ht_index_from_height(height); + } { std::lock_guard lock(komodo_mutex); - for (k=0; kpubkey,pubkeys[k],33); kp->notaryid = k; HASH_ADD_KEYPTR(hh,N.Notaries,kp->pubkey,33,kp); - if ( 0 && height > 10000 ) - { - for (i=0; i<33; i++) - printf("%02x",pubkeys[k][i]); - printf(" notarypubs.[%d] ht.%d active at %d\n",k,origheight,htind*KOMODO_ELECTION_GAP); - } } N.numnotaries = num; - for (i=htind; i= KOMODO_MAXBLOCKS ) { printf("komodo_chosennotary ht.%d illegal\n",height); return(-1); } - if ( height >= KOMODO_NOTARIES_HARDCODED || ASSETCHAINS_SYMBOL[0] != 0 ) + if ( height >= KOMODO_NOTARIES_HARDCODED || !chainName.isKMD() ) { if ( (*notaryidp= komodo_electednotary(&numnotaries,pubkey33,height,timestamp)) >= 0 && numnotaries != 0 ) { @@ -259,28 +302,25 @@ int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33, } if ( height >= 250000 ) return(-1); - if ( Pubkeys == 0 ) + if ( Pubkeys == nullptr ) komodo_init(0); - htind = height / KOMODO_ELECTION_GAP; - if ( htind >= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) - htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; + int32_t htind = ht_index_from_height(height); { std::lock_guard lock(komodo_mutex); HASH_FIND(hh,Pubkeys[htind].Notaries,pubkey33,33,kp); } - if ( kp != 0 ) + if ( kp != nullptr ) { if ( (numnotaries= Pubkeys[htind].numnotaries) > 0 ) { *notaryidp = kp->notaryid; modval = ((height % numnotaries) == kp->notaryid); - //printf("found notary.%d ht.%d modval.%d\n",kp->notaryid,height,modval); - } else printf("unexpected zero notaries at height.%d\n",height); - } //else printf("cant find kp at htind.%d ht.%d\n",htind,height); - //int32_t i; for (i=0; i<33; i++) - // printf("%02x",pubkey33[i]); - //printf(" ht.%d notary.%d special.%d htind.%d num.%d\n",height,*notaryidp,modval,htind,numnotaries); - return(modval); + } + else + printf("unexpected zero notaries at height.%d\n",height); + } + + return modval; } /****** @@ -441,28 +481,59 @@ void komodo_notarized_update(struct komodo_state *sp,int32_t nHeight,int32_t not sp->AddCheckpoint(new_cp); } +/**** + * @brief Initialize genesis notaries into memory + * @note After a successful run, subsequent calls do nothing + * @param height the current height (not used other than to stop initialization if less than zero) + */ void komodo_init(int32_t height) { - static int didinit; uint256 zero; - int32_t k,n; uint8_t pubkeys[64][33]; memset(&zero,0,sizeof(zero)); - if ( didinit == 0 ) + if ( !didinit ) { decode_hex(NOTARY_PUBKEY33,33,NOTARY_PUBKEY.c_str()); if ( height >= 0 ) { - n = (int32_t)(sizeof(Notaries_genesis)/sizeof(*Notaries_genesis)); - for (k=0; k= 32 ) - return(0); - if ( baseid < 10 ) - val *= 4; - mult = MINDENOMS[baseid] / MIND; - return(mult * val); -} - -uint64_t komodo_paxvol(uint64_t volume,uint64_t price) -{ - if ( volume < 10000000000 ) - return((volume * price) / 1000000000); - else if ( volume < (uint64_t)10 * 10000000000 ) - return((volume * (price / 10)) / 100000000); - else if ( volume < (uint64_t)100 * 10000000000 ) - return(((volume / 10) * (price / 10)) / 10000000); - else if ( volume < (uint64_t)1000 * 10000000000 ) - return(((volume / 10) * (price / 100)) / 1000000); - else if ( volume < (uint64_t)10000 * 10000000000 ) - return(((volume / 100) * (price / 100)) / 100000); - else if ( volume < (uint64_t)100000 * 10000000000 ) - return(((volume / 100) * (price / 1000)) / 10000); - else if ( volume < (uint64_t)1000000 * 10000000000 ) - return(((volume / 1000) * (price / 1000)) / 1000); - else if ( volume < (uint64_t)10000000 * 10000000000 ) - return(((volume / 1000) * (price / 10000)) / 100); - else return(((volume / 10000) * (price / 10000)) / 10); -} - -void pax_rank(uint64_t *ranked,uint32_t *pvals) -{ - int32_t i; uint64_t vals[32],sum = 0; - for (i=0; i<32; i++) - { - vals[i] = komodo_paxvol(M1SUPPLY[i] / MINDENOMS[i],pvals[i]); - sum += vals[i]; - } - for (i=0; i<32; i++) - { - ranked[i] = (vals[i] * 1000000000) / sum; - //printf("%.6f ",(double)ranked[i]/1000000000.); - } - //printf("sum %llu\n",(long long)sum); -}; - -#define BTCFACTOR_HEIGHT 466266 - -double PAX_BTCUSD(int32_t height,uint32_t btcusd) -{ - double btcfactor,BTCUSD; - if ( height >= BTCFACTOR_HEIGHT ) - btcfactor = 100000.; - else btcfactor = 1000.; - BTCUSD = ((double)btcusd / (1000000000. / btcfactor)); - if ( height >= BTCFACTOR_HEIGHT && height < 500000 && BTCUSD > 20000 && btcfactor == 100000. ) - BTCUSD /= 100; - return(BTCUSD); -} - -int32_t dpow_readprices(int32_t height,uint8_t *data,uint32_t *timestampp,double *KMDBTCp,double *BTCUSDp,double *CNYUSDp,uint32_t *pvals) -{ - uint32_t kmdbtc,btcusd,cnyusd; int32_t i,n,nonz,len = 0; - if ( data[0] == 'P' && data[5] == 35 ) - data++; - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)timestampp); - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&n); - if ( n != 35 ) - { - printf("dpow_readprices illegal n.%d\n",n); - return(-1); - } - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&kmdbtc); // /= 1000 - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&btcusd); // *= 1000 - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&cnyusd); - *KMDBTCp = ((double)kmdbtc / (1000000000. * 1000.)); - *BTCUSDp = PAX_BTCUSD(height,btcusd); - *CNYUSDp = ((double)cnyusd / 1000000000.); - for (i=nonz=0; i sizeof(crc32) ) - { - if ( (retval= (int32_t)fread(data,1,fsize,fp)) == fsize ) - { - len = iguana_rwnum(0,data,sizeof(crc32),(void *)&crc32); - check = calc_crc32(0,data+sizeof(crc32),(int32_t)(fsize-sizeof(crc32))); - if ( check == crc32 ) - { - double KMDBTC,BTCUSD,CNYUSD; uint32_t pvals[128]; - if ( dpow_readprices(height,&data[len],×tamp,&KMDBTC,&BTCUSD,&CNYUSD,pvals) > 0 ) - { - if ( 0 && lastcrc != crc32 ) - { - for (i=0; i<32; i++) - printf("%u ",pvals[i]); - printf("t%u n.%d KMD %f BTC %f CNY %f (%f)\n",timestamp,n,KMDBTC,BTCUSD,CNYUSD,CNYUSD!=0?1./CNYUSD:0); - } - if ( timestamp > time(NULL)-600 ) - { - n = komodo_opreturnscript(opret,'P',data+sizeof(crc32),(int32_t)(fsize-sizeof(crc32))); - if ( 0 && lastcrc != crc32 ) - { - for (i=0; i maxsize.%d or data[%d]\n",fsize,maxsize,(int32_t)sizeof(data)); - fclose(fp); - } //else printf("couldnt open %s\n",fname); - return(n); -} - -int32_t PAX_pubkey(int32_t rwflag,uint8_t *pubkey33,uint8_t *addrtypep,uint8_t rmd160[20],char fiat[4],uint8_t *shortflagp,int64_t *fiatoshisp) -{ - if ( rwflag != 0 ) - { - memset(pubkey33,0,33); - pubkey33[0] = 0x02 | (*shortflagp != 0); - memcpy(&pubkey33[1],fiat,3); - iguana_rwnum(rwflag,&pubkey33[4],sizeof(*fiatoshisp),(void *)fiatoshisp); - pubkey33[12] = *addrtypep; - memcpy(&pubkey33[13],rmd160,20); - } - else - { - *shortflagp = (pubkey33[0] == 0x03); - memcpy(fiat,&pubkey33[1],3); - fiat[3] = 0; - iguana_rwnum(rwflag,&pubkey33[4],sizeof(*fiatoshisp),(void *)fiatoshisp); - if ( *shortflagp != 0 ) - *fiatoshisp = -(*fiatoshisp); - *addrtypep = pubkey33[12]; - memcpy(rmd160,&pubkey33[13],20); - } - return(33); -} - -double PAX_val(uint32_t pval,int32_t baseid) -{ - //printf("PAX_val baseid.%d pval.%u\n",baseid,pval); - if ( baseid >= 0 && baseid < MAX_CURRENCIES ) - return(((double)pval / 1000000000.) / MINDENOMS[baseid]); - return(0.); -} - -void komodo_pvals(int32_t height,uint32_t *pvals,uint8_t numpvals) -{ - int32_t i,nonz; uint32_t kmdbtc,btcusd,cnyusd; double KMDBTC,BTCUSD,CNYUSD; - if ( numpvals >= 35 ) - { - for (nonz=i=0; i<32; i++) - { - if ( pvals[i] != 0 ) - nonz++; - //printf("%u ",pvals[i]); - } - if ( nonz == 32 ) - { - kmdbtc = pvals[i++]; - btcusd = pvals[i++]; - cnyusd = pvals[i++]; - KMDBTC = ((double)kmdbtc / (1000000000. * 1000.)); - BTCUSD = PAX_BTCUSD(height,btcusd); - CNYUSD = ((double)cnyusd / 1000000000.); - std::lock_guard lock(komodo_mutex); - PVALS = (uint32_t *)realloc(PVALS,(NUM_PRICES+1) * sizeof(*PVALS) * 36); - PVALS[36 * NUM_PRICES] = height; - memcpy(&PVALS[36 * NUM_PRICES + 1],pvals,sizeof(*pvals) * 35); - NUM_PRICES++; - } - } -} - -uint64_t komodo_paxcorrelation(uint64_t *votes,int32_t numvotes,uint64_t seed) -{ - int32_t i,j,k,ind,zeroes,wt,nonz; int64_t delta; uint64_t lastprice,tolerance,den,densum,sum=0; - for (sum=i=zeroes=nonz=0; i> 2) ) - return(0); - sum /= nonz; - lastprice = sum; - for (i=0; i (numvotes >> 1) ) - break; - } - } - } - } - if ( wt > (numvotes >> 1) ) - { - ind = i; - for (densum=sum=j=0; j KOMODO_PAXMAX ) - { - printf("paxcalc overflow %.8f\n",dstr(basevolume)); - return(0); - } - if ( (pvalb= pvals[baseid]) != 0 ) - { - if ( relid == MAX_CURRENCIES ) - { - if ( height < 236000 ) - { - if ( kmdbtc == 0 ) - kmdbtc = pvals[MAX_CURRENCIES]; - if ( btcusd == 0 ) - btcusd = pvals[MAX_CURRENCIES + 1]; - } - else - { - if ( (kmdbtc= pvals[MAX_CURRENCIES]) == 0 ) - kmdbtc = refkmdbtc; - if ( (btcusd= pvals[MAX_CURRENCIES + 1]) == 0 ) - btcusd = refbtcusd; - } - if ( kmdbtc < 25000000 ) - kmdbtc = 25000000; - if ( pvals[USD] != 0 && kmdbtc != 0 && btcusd != 0 ) - { - baseusd = (((uint64_t)pvalb * 1000000000) / pvals[USD]); - usdvol = komodo_paxvol(basevolume,baseusd); - usdkmd = ((uint64_t)kmdbtc * 1000000000) / btcusd; - if ( height >= 236000-10 ) - { - BTCUSD = PAX_BTCUSD(height,btcusd); - if ( height < BTCFACTOR_HEIGHT || (height < 500000 && BTCUSD > 20000) ) - usdkmd = ((uint64_t)kmdbtc * btcusd) / 1000000000; - else usdkmd = ((uint64_t)kmdbtc * btcusd) / 10000000; - ///if ( height >= BTCFACTOR_HEIGHT && BTCUSD >= 43 ) - // usdkmd = ((uint64_t)kmdbtc * btcusd) / 10000000; - //else usdkmd = ((uint64_t)kmdbtc * btcusd) / 1000000000; - price = ((uint64_t)10000000000 * MINDENOMS[USD] / MINDENOMS[baseid]) / komodo_paxvol(usdvol,usdkmd); - //fprintf(stderr,"ht.%d %.3f kmdbtc.%llu btcusd.%llu base -> USD %llu, usdkmd %llu usdvol %llu -> %llu\n",height,BTCUSD,(long long)kmdbtc,(long long)btcusd,(long long)baseusd,(long long)usdkmd,(long long)usdvol,(long long)(MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd) / (MINDENOMS[baseid]/100))); - //fprintf(stderr,"usdkmd.%llu basevolume.%llu baseusd.%llu paxvol.%llu usdvol.%llu -> %llu %llu\n",(long long)usdkmd,(long long)basevolume,(long long)baseusd,(long long)komodo_paxvol(basevolume,baseusd),(long long)usdvol,(long long)(MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd) / (MINDENOMS[baseid]/100)),(long long)price); - //fprintf(stderr,"usdkmd.%llu basevolume.%llu baseusd.%llu paxvol.%llu usdvol.%llu -> %llu\n",(long long)usdkmd,(long long)basevolume,(long long)baseusd,(long long)komodo_paxvol(basevolume,baseusd),(long long)usdvol,(long long)(MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd) / (MINDENOMS[baseid]/100))); - } else price = (MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd) / (MINDENOMS[baseid]/100)); - return(price); - } //else printf("zero val in KMD conv %llu %llu %llu\n",(long long)pvals[USD],(long long)kmdbtc,(long long)btcusd); - } - else if ( baseid == relid ) - { - if ( baseid != MAX_CURRENCIES ) - { - pax_rank(ranked,pvals); - //printf("%s M1 percentage %.8f\n",CURRENCIES[baseid],dstr(10 * ranked[baseid])); - return(10 * ranked[baseid]); // scaled percentage of M1 total - } else return(basevolume); - } - else if ( (pvalr= pvals[relid]) != 0 ) - { - baserel = ((uint64_t)pvalb * 1000000000) / pvalr; - //printf("baserel.%lld %lld %lld %.8f %.8f\n",(long long)baserel,(long long)MINDENOMS[baseid],(long long)MINDENOMS[relid],dstr(MINDENOMS[baseid]/MINDENOMS[relid]),dstr(MINDENOMS[relid]/MINDENOMS[baseid])); - if ( MINDENOMS[baseid] > MINDENOMS[relid] ) - basevolume /= (MINDENOMS[baseid] / MINDENOMS[relid]); - else if ( MINDENOMS[baseid] < MINDENOMS[relid] ) - basevolume *= (MINDENOMS[relid] / MINDENOMS[baseid]); - return(komodo_paxvol(basevolume,baserel)); - } - else printf("null pval for %s\n",CURRENCIES[relid]); - } else printf("null pval for %s\n",CURRENCIES[baseid]); - return(0); -} - -uint64_t _komodo_paxprice(uint64_t *kmdbtcp,uint64_t *btcusdp,int32_t height,char *base,char *rel,uint64_t basevolume,uint64_t kmdbtc,uint64_t btcusd) -{ - int32_t baseid=-1,relid=-1,i; uint32_t *ptr,*pvals; - if ( height > 10 ) - height -= 10; - if ( (baseid= komodo_baseid(base)) >= 0 && (relid= komodo_baseid(rel)) >= 0 ) - { - for (i=NUM_PRICES-1; i>=0; i--) - { - ptr = &PVALS[36 * i]; - if ( *ptr < height ) - { - pvals = &ptr[1]; - if ( kmdbtcp != 0 && btcusdp != 0 ) - { - *kmdbtcp = pvals[MAX_CURRENCIES] / 539; - *btcusdp = pvals[MAX_CURRENCIES + 1] / 539; - } - if ( kmdbtc != 0 && btcusd != 0 ) - return(komodo_paxcalc(height,pvals,baseid,relid,basevolume,kmdbtc,btcusd)); - else return(0); - } - } - } //else printf("paxprice invalid base.%s %d, rel.%s %d\n",base,baseid,rel,relid); - return(0); -} - -int32_t komodo_kmdbtcusd(int32_t rwflag,uint64_t *kmdbtcp,uint64_t *btcusdp,int32_t height) -{ - static uint64_t *KMDBTCS,*BTCUSDS; static int32_t maxheight = 0; int32_t incr = 10000; - if ( height >= maxheight ) - { - //printf("height.%d maxheight.%d incr.%d\n",height,maxheight,incr); - if ( height >= maxheight+incr ) - incr = (height - (maxheight+incr) + 1000); - KMDBTCS = (uint64_t *)realloc(KMDBTCS,((incr + maxheight) * sizeof(*KMDBTCS))); - memset(&KMDBTCS[maxheight],0,(incr * sizeof(*KMDBTCS))); - BTCUSDS = (uint64_t *)realloc(BTCUSDS,((incr + maxheight) * sizeof(*BTCUSDS))); - memset(&BTCUSDS[maxheight],0,(incr * sizeof(*BTCUSDS))); - maxheight += incr; - } - if ( rwflag == 0 ) - { - *kmdbtcp = KMDBTCS[height]; - *btcusdp = BTCUSDS[height]; - } - else - { - KMDBTCS[height] = *kmdbtcp; - BTCUSDS[height] = *btcusdp; - } - if ( *kmdbtcp != 0 && *btcusdp != 0 ) - return(0); - else return(-1); -} - -uint64_t _komodo_paxpriceB(uint64_t seed,int32_t height,char *base,char *rel,uint64_t basevolume) -{ - int32_t i,j,k,ind,zeroes,numvotes,wt,nonz; int64_t delta; uint64_t lastprice,tolerance,den,densum,sum=0,votes[sizeof(Peggy_inds)/sizeof(*Peggy_inds)],btcusds[sizeof(Peggy_inds)/sizeof(*Peggy_inds)],kmdbtcs[sizeof(Peggy_inds)/sizeof(*Peggy_inds)],kmdbtc,btcusd; - if ( basevolume > KOMODO_PAXMAX ) - { - printf("komodo_paxprice overflow %.8f\n",dstr(basevolume)); - return(0); - } - if ( strcmp(base,"KMD") == 0 || strcmp(base,"kmd") == 0 ) - { - printf("kmd cannot be base currency\n"); - return(0); - } - numvotes = (int32_t)(sizeof(Peggy_inds)/sizeof(*Peggy_inds)); - memset(votes,0,sizeof(votes)); - //if ( komodo_kmdbtcusd(0,&kmdbtc,&btcusd,height) < 0 ) crashes when via passthru GUI use - { - memset(btcusds,0,sizeof(btcusds)); - memset(kmdbtcs,0,sizeof(kmdbtcs)); - for (i=0; i> 1) ) - { - return(0); - } - return(komodo_paxcorrelation(votes,numvotes,seed) * basevolume / 100000); -} - -uint64_t komodo_paxpriceB(uint64_t seed,int32_t height,char *base,char *rel,uint64_t basevolume) -{ - uint64_t baseusd,basekmd,usdkmd; int32_t baseid = komodo_baseid(base); - if ( height >= 236000 && strcmp(rel,"kmd") == 0 ) - { - usdkmd = _komodo_paxpriceB(seed,height,(char *)"USD",(char *)"KMD",SATOSHIDEN); - if ( strcmp("usd",base) == 0 ) - return(komodo_paxvol(basevolume,usdkmd) * 10); - baseusd = _komodo_paxpriceB(seed,height,base,(char *)"USD",SATOSHIDEN); - basekmd = (komodo_paxvol(basevolume,baseusd) * usdkmd) / 10000000; - //if ( strcmp("KMD",base) == 0 ) - // printf("baseusd.%llu usdkmd.%llu %llu\n",(long long)baseusd,(long long)usdkmd,(long long)basekmd); - return(basekmd); - } else return(_komodo_paxpriceB(seed,height,base,rel,basevolume)); -} - -uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume) -{ - int32_t i,nonz=0; int64_t diff; uint64_t price,seed,sum = 0; - if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.LastTip() != 0 && height > chainActive.LastTip()->nHeight ) - { - if ( height < 100000000 ) - { - static uint32_t counter; - if ( counter++ < 3 ) - printf("komodo_paxprice height.%d vs tip.%d\n",height,chainActive.LastTip()->nHeight); - } - return(0); - } - *seedp = komodo_seed(height); - { - std::lock_guard lock(komodo_mutex); - for (i=0; i<17; i++) - { - if ( (price= komodo_paxpriceB(*seedp,height-i,base,rel,basevolume)) != 0 ) - { - sum += price; - nonz++; - if ( 0 && i == 1 && nonz == 2 ) - { - diff = (((int64_t)price - (sum >> 1)) * 10000); - if ( diff < 0 ) - diff = -diff; - diff /= price; - printf("(%llu %llu %lld).%lld ",(long long)price,(long long)(sum>>1),(long long)(((int64_t)price - (sum >> 1)) * 10000),(long long)diff); - if ( diff < 33 ) - break; - } - else if ( 0 && i == 3 && nonz == 4 ) - { - diff = (((int64_t)price - (sum >> 2)) * 10000); - if ( diff < 0 ) - diff = -diff; - diff /= price; - printf("(%llu %llu %lld).%lld ",(long long)price,(long long)(sum>>2),(long long) (((int64_t)price - (sum >> 2)) * 10000),(long long)diff); - if ( diff < 20 ) - break; - } - } - if ( height < 165000 || height > 236000 ) - break; - } - } - if ( nonz != 0 ) - sum /= nonz; - //printf("-> %lld %s/%s i.%d ht.%d\n",(long long)sum,base,rel,i,height); - return(sum); -} - -int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel) -{ - int32_t baseid=-1,relid=-1,i,num = 0; uint32_t *ptr; - if ( (baseid= komodo_baseid(base)) >= 0 && (relid= komodo_baseid(rel)) >= 0 ) - { - for (i=NUM_PRICES-1; i>=0; i--) - { - ptr = &PVALS[36 * i]; - heights[num] = *ptr; - prices[num] = komodo_paxcalc(*ptr,&ptr[1],baseid,relid,COIN,0,0); - num++; - if ( num >= max ) - return(num); - } - } - return(num); -} - -void komodo_paxpricefeed(int32_t height,uint8_t *pricefeed,int32_t opretlen) -{ - double KMDBTC,BTCUSD,CNYUSD; uint32_t numpvals,timestamp,pvals[128]; uint256 zero; - numpvals = dpow_readprices(height,pricefeed,×tamp,&KMDBTC,&BTCUSD,&CNYUSD,pvals); - memset(&zero,0,sizeof(zero)); - komodo_stateupdate(height,0,0,0,zero,0,0,pvals,numpvals,0,0,0,0,0,0,zero,0); - if ( 0 ) - { - int32_t i; - for (i=0; i KMD %.8f seed.%llx\n",height,base,(double)fiatoshis/COIN,(double)komodoshis/COIN,(long long)*seedp); - if ( bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr) == 20 ) - { - PAX_pubkey(1,pubkey33,&addrtype,rmd160,base,&shortflag,tokomodo != 0 ? &komodoshis : &fiatoshis); - bitcoin_address(destaddr,KOMODO_PUBTYPE,pubkey33,33); - } - return(komodoshis); -} diff --git a/src/komodo_pax.h b/src/komodo_pax.h deleted file mode 100644 index 830688d2932..00000000000 --- a/src/komodo_pax.h +++ /dev/null @@ -1,93 +0,0 @@ -/****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * - * * - * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * - * the top-level directory of this distribution for the individual copyright * - * holder information and the developer policies on copyright and licensing. * - * * - * Unless otherwise agreed in a custom licensing agreement, no part of the * - * SuperNET software, including this file may be copied, modified, propagated * - * or distributed except according to the terms contained in the LICENSE file * - * * - * Removal or modification of this copyright notice is prohibited. * - * * - ******************************************************************************/ -#pragma once -#include "komodo_defs.h" - -#define USD 0 -#define EUR 1 -#define JPY 2 -#define GBP 3 -#define AUD 4 -#define CAD 5 -#define CHF 6 -#define NZD 7 - -#define CNY 8 -#define RUB 9 -#define MXN 10 -#define BRL 11 -#define INR 12 -#define HKD 13 -#define TRY 14 -#define ZAR 15 - -#define PLN 16 -#define NOK 17 -#define SEK 18 -#define DKK 19 -#define CZK 20 -#define HUF 21 -#define ILS 22 -#define KRW 23 - -#define MYR 24 -#define PHP 25 -#define RON 26 -#define SGD 27 -#define THB 28 -#define BGN 29 -#define IDR 30 -#define HRK 31 - -#define MAX_CURRENCIES 32 -extern char CURRENCIES[][8]; - -uint64_t komodo_maxallowed(int32_t baseid); - -uint64_t komodo_paxvol(uint64_t volume,uint64_t price); - -void pax_rank(uint64_t *ranked,uint32_t *pvals); - -double PAX_BTCUSD(int32_t height,uint32_t btcusd); - -int32_t dpow_readprices(int32_t height,uint8_t *data,uint32_t *timestampp,double *KMDBTCp,double *BTCUSDp,double *CNYUSDp,uint32_t *pvals); - -int32_t komodo_pax_opreturn(int32_t height,uint8_t *opret,int32_t maxsize); - -int32_t PAX_pubkey(int32_t rwflag,uint8_t *pubkey33,uint8_t *addrtypep,uint8_t rmd160[20],char fiat[4],uint8_t *shortflagp,int64_t *fiatoshisp); - -double PAX_val(uint32_t pval,int32_t baseid); - -void komodo_pvals(int32_t height,uint32_t *pvals,uint8_t numpvals); - -uint64_t komodo_paxcorrelation(uint64_t *votes,int32_t numvotes,uint64_t seed); - -uint64_t komodo_paxcalc(int32_t height,uint32_t *pvals,int32_t baseid,int32_t relid,uint64_t basevolume,uint64_t refkmdbtc,uint64_t refbtcusd); - -uint64_t _komodo_paxprice(uint64_t *kmdbtcp,uint64_t *btcusdp,int32_t height,char *base,char *rel,uint64_t basevolume,uint64_t kmdbtc,uint64_t btcusd); - -int32_t komodo_kmdbtcusd(int32_t rwflag,uint64_t *kmdbtcp,uint64_t *btcusdp,int32_t height); - -uint64_t _komodo_paxpriceB(uint64_t seed,int32_t height,char *base,char *rel,uint64_t basevolume); - -uint64_t komodo_paxpriceB(uint64_t seed,int32_t height,char *base,char *rel,uint64_t basevolume); - -uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume); - -int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel); - -void komodo_paxpricefeed(int32_t height,uint8_t *pricefeed,int32_t opretlen); - -uint64_t PAX_fiatdest(uint64_t *seedp,int32_t tokomodo,char *destaddr,uint8_t pubkey33[33],char *coinaddr,int32_t height,char *origbase,int64_t fiatoshis); diff --git a/src/komodo_port.c b/src/komodo_port.c deleted file mode 100644 index f19018eebcc..00000000000 --- a/src/komodo_port.c +++ /dev/null @@ -1,898 +0,0 @@ -/****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * - * * - * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * - * the top-level directory of this distribution for the individual copyright * - * holder information and the developer policies on copyright and licensing. * - * * - * Unless otherwise agreed in a custom licensing agreement, no part of the * - * SuperNET software, including this file may be copied, modified, propagated * - * or distributed except according to the terms contained in the LICENSE file * - * * - * Removal or modification of this copyright notice is prohibited. * - * * - ******************************************************************************/ - -#include -#include -#include -#include -#include "bits256.h" - -uint64_t ASSETCHAINS_COMMISSION; -uint32_t ASSETCHAINS_MAGIC = 2387029918; -uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33]; - -struct sha256_vstate { uint64_t length; uint32_t state[8],curlen; uint8_t buf[64]; }; -struct rmd160_vstate { uint64_t length; uint8_t buf[64]; uint32_t curlen, state[5]; }; - -// following is ported from libtom - -#define STORE32L(x, y) \ -{ (y)[3] = (uint8_t)(((x)>>24)&255); (y)[2] = (uint8_t)(((x)>>16)&255); \ -(y)[1] = (uint8_t)(((x)>>8)&255); (y)[0] = (uint8_t)((x)&255); } - -#define LOAD32L(x, y) \ -{ x = (uint32_t)(((uint64_t)((y)[3] & 255)<<24) | \ -((uint32_t)((y)[2] & 255)<<16) | \ -((uint32_t)((y)[1] & 255)<<8) | \ -((uint32_t)((y)[0] & 255))); } - -#define STORE64L(x, y) \ -{ (y)[7] = (uint8_t)(((x)>>56)&255); (y)[6] = (uint8_t)(((x)>>48)&255); \ -(y)[5] = (uint8_t)(((x)>>40)&255); (y)[4] = (uint8_t)(((x)>>32)&255); \ -(y)[3] = (uint8_t)(((x)>>24)&255); (y)[2] = (uint8_t)(((x)>>16)&255); \ -(y)[1] = (uint8_t)(((x)>>8)&255); (y)[0] = (uint8_t)((x)&255); } - -#define LOAD64L(x, y) \ -{ x = (((uint64_t)((y)[7] & 255))<<56)|(((uint64_t)((y)[6] & 255))<<48)| \ -(((uint64_t)((y)[5] & 255))<<40)|(((uint64_t)((y)[4] & 255))<<32)| \ -(((uint64_t)((y)[3] & 255))<<24)|(((uint64_t)((y)[2] & 255))<<16)| \ -(((uint64_t)((y)[1] & 255))<<8)|(((uint64_t)((y)[0] & 255))); } - -#define STORE32H(x, y) \ -{ (y)[0] = (uint8_t)(((x)>>24)&255); (y)[1] = (uint8_t)(((x)>>16)&255); \ -(y)[2] = (uint8_t)(((x)>>8)&255); (y)[3] = (uint8_t)((x)&255); } - -#define LOAD32H(x, y) \ -{ x = (uint32_t)(((uint64_t)((y)[0] & 255)<<24) | \ -((uint32_t)((y)[1] & 255)<<16) | \ -((uint32_t)((y)[2] & 255)<<8) | \ -((uint32_t)((y)[3] & 255))); } - -#define STORE64H(x, y) \ -{ (y)[0] = (uint8_t)(((x)>>56)&255); (y)[1] = (uint8_t)(((x)>>48)&255); \ -(y)[2] = (uint8_t)(((x)>>40)&255); (y)[3] = (uint8_t)(((x)>>32)&255); \ -(y)[4] = (uint8_t)(((x)>>24)&255); (y)[5] = (uint8_t)(((x)>>16)&255); \ -(y)[6] = (uint8_t)(((x)>>8)&255); (y)[7] = (uint8_t)((x)&255); } - -#define LOAD64H(x, y) \ -{ x = (((uint64_t)((y)[0] & 255))<<56)|(((uint64_t)((y)[1] & 255))<<48) | \ -(((uint64_t)((y)[2] & 255))<<40)|(((uint64_t)((y)[3] & 255))<<32) | \ -(((uint64_t)((y)[4] & 255))<<24)|(((uint64_t)((y)[5] & 255))<<16) | \ -(((uint64_t)((y)[6] & 255))<<8)|(((uint64_t)((y)[7] & 255))); } - -// Various logical functions -#define RORc(x, y) ( ((((uint32_t)(x)&0xFFFFFFFFUL)>>(uint32_t)((y)&31)) | ((uint32_t)(x)<<(uint32_t)(32-((y)&31)))) & 0xFFFFFFFFUL) -#define Ch(x,y,z) (z ^ (x & (y ^ z))) -#define Maj(x,y,z) (((x | y) & z) | (x & y)) -#define S(x, n) RORc((x),(n)) -#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) -#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) -#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) -#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) -#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) -#define MIN(x, y) ( ((x)<(y))?(x):(y) ) - -static inline int32_t sha256_vcompress(struct sha256_vstate * md,uint8_t *buf) -{ - uint32_t S[8],W[64],t0,t1,i; - for (i=0; i<8; i++) // copy state into S - S[i] = md->state[i]; - for (i=0; i<16; i++) // copy the state into 512-bits into W[0..15] - LOAD32H(W[i],buf + (4*i)); - for (i=16; i<64; i++) // fill W[16..63] - W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; - -#define RND(a,b,c,d,e,f,g,h,i,ki) \ -t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \ -t1 = Sigma0(a) + Maj(a, b, c); \ -d += t0; \ -h = t0 + t1; - - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2); -#undef RND - for (i=0; i<8; i++) // feedback - md->state[i] = md->state[i] + S[i]; - return(0); -} - -#undef RORc -#undef Ch -#undef Maj -#undef S -#undef R -#undef Sigma0 -#undef Sigma1 -#undef Gamma0 -#undef Gamma1 - -static inline void sha256_vinit(struct sha256_vstate * md) -{ - md->curlen = 0; - md->length = 0; - md->state[0] = 0x6A09E667UL; - md->state[1] = 0xBB67AE85UL; - md->state[2] = 0x3C6EF372UL; - md->state[3] = 0xA54FF53AUL; - md->state[4] = 0x510E527FUL; - md->state[5] = 0x9B05688CUL; - md->state[6] = 0x1F83D9ABUL; - md->state[7] = 0x5BE0CD19UL; -} - -static inline int32_t sha256_vprocess(struct sha256_vstate *md,const uint8_t *in,uint64_t inlen) -{ - uint64_t n; int32_t err; - if ( md->curlen > sizeof(md->buf) ) - return(-1); - while ( inlen > 0 ) - { - if ( md->curlen == 0 && inlen >= 64 ) - { - if ( (err= sha256_vcompress(md,(uint8_t *)in)) != 0 ) - return(err); - md->length += 64 * 8, in += 64, inlen -= 64; - } - else - { - n = MIN(inlen,64 - md->curlen); - memcpy(md->buf + md->curlen,in,(size_t)n); - md->curlen += n, in += n, inlen -= n; - if ( md->curlen == 64 ) - { - if ( (err= sha256_vcompress(md,md->buf)) != 0 ) - return(err); - md->length += 8*64; - md->curlen = 0; - } - } - } - return(0); -} - -static inline int32_t sha256_vdone(struct sha256_vstate *md,uint8_t *out) -{ - int32_t i; - if ( md->curlen >= sizeof(md->buf) ) - return(-1); - md->length += md->curlen * 8; // increase the length of the message - md->buf[md->curlen++] = (uint8_t)0x80; // append the '1' bit - // if len > 56 bytes we append zeros then compress. Then we can fall back to padding zeros and length encoding like normal. - if ( md->curlen > 56 ) - { - while ( md->curlen < 64 ) - md->buf[md->curlen++] = (uint8_t)0; - sha256_vcompress(md,md->buf); - md->curlen = 0; - } - while ( md->curlen < 56 ) // pad upto 56 bytes of zeroes - md->buf[md->curlen++] = (uint8_t)0; - STORE64H(md->length,md->buf+56); // store length - sha256_vcompress(md,md->buf); - for (i=0; i<8; i++) // copy output - STORE32H(md->state[i],out+(4*i)); - return(0); -} - -void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len) -{ - struct sha256_vstate md; - sha256_vinit(&md); - sha256_vprocess(&md,src,len); - sha256_vdone(&md,hash); -} - -bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen) -{ - bits256 hash,hash2; int32_t i; - vcalc_sha256(0,hash.bytes,data,datalen); - vcalc_sha256(0,hash2.bytes,hash.bytes,sizeof(hash)); - for (i=0; i>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) - -/* the ten basic operations FF() through III() */ -#define FF(a, b, c, d, e, x, s) \ -(a) += F((b), (c), (d)) + (x);\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define GG(a, b, c, d, e, x, s) \ -(a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define HH(a, b, c, d, e, x, s) \ -(a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define II(a, b, c, d, e, x, s) \ -(a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define JJ(a, b, c, d, e, x, s) \ -(a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define FFF(a, b, c, d, e, x, s) \ -(a) += F((b), (c), (d)) + (x);\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define GGG(a, b, c, d, e, x, s) \ -(a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define HHH(a, b, c, d, e, x, s) \ -(a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define III(a, b, c, d, e, x, s) \ -(a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define JJJ(a, b, c, d, e, x, s) \ -(a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -static int32_t rmd160_vcompress(struct rmd160_vstate *md,uint8_t *buf) -{ - uint32_t aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,X[16]; - int i; - - /* load words X */ - for (i = 0; i < 16; i++){ - LOAD32L(X[i], buf + (4 * i)); - } - - /* load state */ - aa = aaa = md->state[0]; - bb = bbb = md->state[1]; - cc = ccc = md->state[2]; - dd = ddd = md->state[3]; - ee = eee = md->state[4]; - - /* round 1 */ - FF(aa, bb, cc, dd, ee, X[ 0], 11); - FF(ee, aa, bb, cc, dd, X[ 1], 14); - FF(dd, ee, aa, bb, cc, X[ 2], 15); - FF(cc, dd, ee, aa, bb, X[ 3], 12); - FF(bb, cc, dd, ee, aa, X[ 4], 5); - FF(aa, bb, cc, dd, ee, X[ 5], 8); - FF(ee, aa, bb, cc, dd, X[ 6], 7); - FF(dd, ee, aa, bb, cc, X[ 7], 9); - FF(cc, dd, ee, aa, bb, X[ 8], 11); - FF(bb, cc, dd, ee, aa, X[ 9], 13); - FF(aa, bb, cc, dd, ee, X[10], 14); - FF(ee, aa, bb, cc, dd, X[11], 15); - FF(dd, ee, aa, bb, cc, X[12], 6); - FF(cc, dd, ee, aa, bb, X[13], 7); - FF(bb, cc, dd, ee, aa, X[14], 9); - FF(aa, bb, cc, dd, ee, X[15], 8); - - /* round 2 */ - GG(ee, aa, bb, cc, dd, X[ 7], 7); - GG(dd, ee, aa, bb, cc, X[ 4], 6); - GG(cc, dd, ee, aa, bb, X[13], 8); - GG(bb, cc, dd, ee, aa, X[ 1], 13); - GG(aa, bb, cc, dd, ee, X[10], 11); - GG(ee, aa, bb, cc, dd, X[ 6], 9); - GG(dd, ee, aa, bb, cc, X[15], 7); - GG(cc, dd, ee, aa, bb, X[ 3], 15); - GG(bb, cc, dd, ee, aa, X[12], 7); - GG(aa, bb, cc, dd, ee, X[ 0], 12); - GG(ee, aa, bb, cc, dd, X[ 9], 15); - GG(dd, ee, aa, bb, cc, X[ 5], 9); - GG(cc, dd, ee, aa, bb, X[ 2], 11); - GG(bb, cc, dd, ee, aa, X[14], 7); - GG(aa, bb, cc, dd, ee, X[11], 13); - GG(ee, aa, bb, cc, dd, X[ 8], 12); - - /* round 3 */ - HH(dd, ee, aa, bb, cc, X[ 3], 11); - HH(cc, dd, ee, aa, bb, X[10], 13); - HH(bb, cc, dd, ee, aa, X[14], 6); - HH(aa, bb, cc, dd, ee, X[ 4], 7); - HH(ee, aa, bb, cc, dd, X[ 9], 14); - HH(dd, ee, aa, bb, cc, X[15], 9); - HH(cc, dd, ee, aa, bb, X[ 8], 13); - HH(bb, cc, dd, ee, aa, X[ 1], 15); - HH(aa, bb, cc, dd, ee, X[ 2], 14); - HH(ee, aa, bb, cc, dd, X[ 7], 8); - HH(dd, ee, aa, bb, cc, X[ 0], 13); - HH(cc, dd, ee, aa, bb, X[ 6], 6); - HH(bb, cc, dd, ee, aa, X[13], 5); - HH(aa, bb, cc, dd, ee, X[11], 12); - HH(ee, aa, bb, cc, dd, X[ 5], 7); - HH(dd, ee, aa, bb, cc, X[12], 5); - - /* round 4 */ - II(cc, dd, ee, aa, bb, X[ 1], 11); - II(bb, cc, dd, ee, aa, X[ 9], 12); - II(aa, bb, cc, dd, ee, X[11], 14); - II(ee, aa, bb, cc, dd, X[10], 15); - II(dd, ee, aa, bb, cc, X[ 0], 14); - II(cc, dd, ee, aa, bb, X[ 8], 15); - II(bb, cc, dd, ee, aa, X[12], 9); - II(aa, bb, cc, dd, ee, X[ 4], 8); - II(ee, aa, bb, cc, dd, X[13], 9); - II(dd, ee, aa, bb, cc, X[ 3], 14); - II(cc, dd, ee, aa, bb, X[ 7], 5); - II(bb, cc, dd, ee, aa, X[15], 6); - II(aa, bb, cc, dd, ee, X[14], 8); - II(ee, aa, bb, cc, dd, X[ 5], 6); - II(dd, ee, aa, bb, cc, X[ 6], 5); - II(cc, dd, ee, aa, bb, X[ 2], 12); - - /* round 5 */ - JJ(bb, cc, dd, ee, aa, X[ 4], 9); - JJ(aa, bb, cc, dd, ee, X[ 0], 15); - JJ(ee, aa, bb, cc, dd, X[ 5], 5); - JJ(dd, ee, aa, bb, cc, X[ 9], 11); - JJ(cc, dd, ee, aa, bb, X[ 7], 6); - JJ(bb, cc, dd, ee, aa, X[12], 8); - JJ(aa, bb, cc, dd, ee, X[ 2], 13); - JJ(ee, aa, bb, cc, dd, X[10], 12); - JJ(dd, ee, aa, bb, cc, X[14], 5); - JJ(cc, dd, ee, aa, bb, X[ 1], 12); - JJ(bb, cc, dd, ee, aa, X[ 3], 13); - JJ(aa, bb, cc, dd, ee, X[ 8], 14); - JJ(ee, aa, bb, cc, dd, X[11], 11); - JJ(dd, ee, aa, bb, cc, X[ 6], 8); - JJ(cc, dd, ee, aa, bb, X[15], 5); - JJ(bb, cc, dd, ee, aa, X[13], 6); - - /* parallel round 1 */ - JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); - JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); - JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); - JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); - JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); - JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); - JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); - JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); - JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); - JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); - - /* parallel round 2 */ - III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); - III(ddd, eee, aaa, bbb, ccc, X[11], 13); - III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); - III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); - III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); - III(eee, aaa, bbb, ccc, ddd, X[13], 8); - III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); - III(ccc, ddd, eee, aaa, bbb, X[10], 11); - III(bbb, ccc, ddd, eee, aaa, X[14], 7); - III(aaa, bbb, ccc, ddd, eee, X[15], 7); - III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); - III(ddd, eee, aaa, bbb, ccc, X[12], 7); - III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); - III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); - III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); - III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); - - /* parallel round 3 */ - HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); - HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); - HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); - HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); - HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); - HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); - HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); - HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); - HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); - HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); - HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); - HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); - HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); - HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); - HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); - HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); - - /* parallel round 4 */ - GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); - GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); - GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); - GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); - GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); - GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); - GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); - GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); - GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); - GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); - GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); - GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); - GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); - GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); - GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); - GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); - - /* parallel round 5 */ - FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); - FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); - FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); - FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); - FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); - FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); - FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); - FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); - FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); - FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); - FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); - FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); - FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); - FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); - FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); - FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); - - /* combine results */ - ddd += cc + md->state[1]; /* final result for md->state[0] */ - md->state[1] = md->state[2] + dd + eee; - md->state[2] = md->state[3] + ee + aaa; - md->state[3] = md->state[4] + aa + bbb; - md->state[4] = md->state[0] + bb + ccc; - md->state[0] = ddd; - - return 0; -} - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return 0 if successful - */ -int rmd160_vinit(struct rmd160_vstate * md) -{ - md->state[0] = 0x67452301UL; - md->state[1] = 0xefcdab89UL; - md->state[2] = 0x98badcfeUL; - md->state[3] = 0x10325476UL; - md->state[4] = 0xc3d2e1f0UL; - md->curlen = 0; - md->length = 0; - return 0; -} -#define HASH_PROCESS(func_name, compress_name, state_var, block_size) \ -int func_name (struct rmd160_vstate * md, const unsigned char *in, unsigned long inlen) \ -{ \ -unsigned long n; \ -int err; \ -if (md->curlen > sizeof(md->buf)) { \ -return -1; \ -} \ -while (inlen > 0) { \ -if (md->curlen == 0 && inlen >= block_size) { \ -if ((err = compress_name (md, (unsigned char *)in)) != 0) { \ -return err; \ -} \ -md->length += block_size * 8; \ -in += block_size; \ -inlen -= block_size; \ -} else { \ -n = MIN(inlen, (block_size - md->curlen)); \ -memcpy(md->buf + md->curlen, in, (size_t)n); \ -md->curlen += n; \ -in += n; \ -inlen -= n; \ -if (md->curlen == block_size) { \ -if ((err = compress_name (md, md->buf)) != 0) { \ -return err; \ -} \ -md->length += 8*block_size; \ -md->curlen = 0; \ -} \ -} \ -} \ -return 0; \ -} - -/** - Process a block of memory though the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return 0 if successful - */ -HASH_PROCESS(rmd160_vprocess, rmd160_vcompress, rmd160, 64) - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (20 bytes) - @return 0 if successful - */ -int rmd160_vdone(struct rmd160_vstate * md, unsigned char *out) -{ - int i; - if (md->curlen >= sizeof(md->buf)) { - return -1; - } - /* increase the length of the message */ - md->length += md->curlen * 8; - - /* append the '1' bit */ - md->buf[md->curlen++] = (unsigned char)0x80; - - /* if the length is currently above 56 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->curlen > 56) { - while (md->curlen < 64) { - md->buf[md->curlen++] = (unsigned char)0; - } - rmd160_vcompress(md, md->buf); - md->curlen = 0; - } - /* pad upto 56 bytes of zeroes */ - while (md->curlen < 56) { - md->buf[md->curlen++] = (unsigned char)0; - } - /* store length */ - STORE64L(md->length, md->buf+56); - rmd160_vcompress(md, md->buf); - /* copy output */ - for (i = 0; i < 5; i++) { - STORE32L(md->state[i], out+(4*i)); - } - return 0; -} - -void calc_rmd160(char deprecated[41],uint8_t buf[20],uint8_t *msg,int32_t len) -{ - struct rmd160_vstate md; - rmd160_vinit(&md); - rmd160_vprocess(&md,msg,len); - rmd160_vdone(&md, buf); -} -#undef F -#undef G -#undef H -#undef I -#undef J -#undef ROLc -#undef FF -#undef GG -#undef HH -#undef II -#undef JJ -#undef FFF -#undef GGG -#undef HHH -#undef III -#undef JJJ - -static const uint32_t crc32_tab[] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d -}; - -uint32_t calc_crc32(uint32_t crc,const void *buf,size_t size) -{ - const uint8_t *p; - - p = (const uint8_t *)buf; - crc = crc ^ ~0U; - - while (size--) - crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); - - return crc ^ ~0U; -} - -void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen) -{ - bits256 hash; - vcalc_sha256(0,hash.bytes,data,datalen); - calc_rmd160(0,rmd160,hash.bytes,sizeof(hash)); -} - -int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp) -{ - int32_t i; uint64_t x; - if ( rwflag == 0 ) - { - x = 0; - for (i=len-1; i>=0; i--) - { - x <<= 8; - x |= serialized[i]; - } - switch ( len ) - { - case 1: *(uint8_t *)endianedp = (uint8_t)x; break; - case 2: *(uint16_t *)endianedp = (uint16_t)x; break; - case 4: *(uint32_t *)endianedp = (uint32_t)x; break; - case 8: *(uint64_t *)endianedp = (uint64_t)x; break; - } - } - else - { - x = 0; - switch ( len ) - { - case 1: x = *(uint8_t *)endianedp; break; - case 2: x = *(uint16_t *)endianedp; break; - case 4: x = *(uint32_t *)endianedp; break; - case 8: x = *(uint64_t *)endianedp; break; - } - for (i=0; i>= 8) - serialized[i] = (uint8_t)(x & 0xff); - } - return(len); -} - -uint32_t komodo_assetmagic(char *symbol,uint64_t supply,uint8_t *extraptr,int32_t extralen) -{ - uint8_t buf[512]; uint32_t crc0=0; int32_t len = 0; bits256 hash; - if ( strcmp(symbol,"KMD") == 0 ) - return(0x8de4eef9); - len = iguana_rwnum(1,&buf[len],sizeof(supply),(void *)&supply); - strcpy((char *)&buf[len],symbol); - len += strlen(symbol); - if ( extraptr != 0 && extralen != 0 ) - { - vcalc_sha256(0,hash.bytes,extraptr,extralen); - crc0 = hash.uints[0]; - } - return(calc_crc32(crc0,buf,len)); -} - -uint16_t komodo_assetport(uint32_t magic,int32_t extralen) -{ - if ( magic == 0x8de4eef9 ) - return(7770); - else if ( extralen == 0 ) - return(8000 + (magic % 7777)); - else return(16000 + (magic % 49500)); -} - -uint16_t komodo_port(char *symbol,uint64_t supply,uint32_t *magicp,uint8_t *extraptr,int32_t extralen) -{ - if ( symbol == 0 || symbol[0] == 0 || strcmp("KMD",symbol) == 0 ) - { - *magicp = 0x8de4eef9; - return(7770); - } - *magicp = komodo_assetmagic(symbol,supply,extraptr,extralen); - return(komodo_assetport(*magicp,extralen)); -} - -uint16_t komodo_calcport(char *name,uint64_t supply,uint64_t endsubsidy,uint64_t reward,uint64_t halving,uint64_t decay,uint64_t commission,uint8_t staked,int32_t cc) -{ - uint8_t extrabuf[4096],*extraptr=0; int32_t extralen=0; uint64_t val; - if ( halving != 0 && halving < 1440 ) - { - halving = 1440; - printf("halving must be at least 1440 blocks\n"); - } - if ( decay == 100000000 && endsubsidy == 0 ) - { - decay = 0; - printf("decay of 100000000 means linear and that needs endsubsidy\n"); - } - else if ( decay > 100000000 ) - { - decay = 0; - printf("decay cant be more than 100000000\n"); - } - if ( endsubsidy != 0 || reward != 0 || halving != 0 || decay != 0 || commission != 0 || cc != 0 || staked != 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 ) - { - //printf("end.%llu reward.%llu halving.%llu decay.%llu perc.%llu\n",(long long)endsubsidy,(long long)reward,(long long)halving,(long long)decay,(long long)commission); - extraptr = extrabuf; - memcpy(extraptr,ASSETCHAINS_OVERRIDE_PUBKEY33,33), extralen = 33; - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(endsubsidy),(void *)&endsubsidy); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(reward),(void *)&reward); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(halving),(void *)&halving); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(decay),(void *)&decay); - val = commission | (((uint64_t)staked & 0xff) << 32) | (((uint64_t)cc & 0xffffff) << 40); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(val),(void *)&val); - } - return(komodo_port(name,supply,&ASSETCHAINS_MAGIC,extraptr,extralen)); -} - -int main(int argc, char * argv[]) -{ - uint16_t rpcport; int32_t i,j,offset=0,jsonflag=0,num = 1; uint64_t supply=10,commission=0,endsubsidy,reward,halving,decay; uint8_t *allocated=0,staked=0; uint32_t cc = 3; - endsubsidy = reward = halving = decay = 0; - if ( argc < 2 ) - { - // staked, commission and cc hardcoded - printf("%s name supply endsubsidy reward halving decay\n",argv[0]); - printf("%s -gen num name supply endsubsidy reward halving decay\n",argv[0]); - return(-1); - } - if ( strncmp(argv[1],"-gen",3) == 0 ) - { - num = atoi(argv[2]); - if ( strcmp(argv[1],"-genjson") == 0 ) - jsonflag = 1; - offset = 2; - allocated = calloc(1,1 << 16); - } - if ( argc > offset + 2 ) - supply = (long long)atof(argv[offset + 2]); - if ( argc > offset + 3 ) - endsubsidy = (long long)atof(argv[offset + 3]); - if ( argc > offset + 4 ) - reward = (long long)atof(argv[offset + 4]); - if ( argc > offset + 5 ) - halving = (long long)atof(argv[offset + 5]); - if ( argc > offset + 6 ) - decay = (long long)atof(argv[offset + 6]); - rpcport = 1 + komodo_calcport(argv[offset + 1],supply,endsubsidy,reward,halving,decay,commission,staked,cc); - printf("./komodod -ac_name=%s -ac_cc=%u -ac_supply=%llu -ac_end=%llu -ac_reward=%llu -ac_halving=%llu -ac_decay=%llu & # rpcport %u\n[",argv[offset + 1],cc,(long long)supply,(long long)endsubsidy,(long long)reward,(long long)halving,(long long)decay,rpcport); - if ( allocated != 0 ) - { - char name[64],newname[64]; - strcpy(name,argv[offset + 1]); - allocated[rpcport] = 1; - allocated[rpcport-1] = 1; - for (i=0; i - -extern std::mutex komodo_mutex; - -/*** - * komodo_state - */ - -bool komodo_state::add_event(const std::string& symbol, const uint32_t height, std::shared_ptr in) -{ - if (ASSETCHAINS_SYMBOL[0] != 0) - { - std::lock_guard lock(komodo_mutex); - events.push_back( in ); - return true; - } - return false; -} namespace komodo { @@ -96,11 +80,11 @@ std::ostream& operator<<(std::ostream& os, const event& in) break; case(EVENT_NOTARIZED): { - event_notarized* tmp = dynamic_cast(const_cast(&in)); - if (tmp->MoMdepth == 0) - os << "N"; - else + const event_notarized& tmp = static_cast(in); + if (tmp.MoMdepth != 0 && !tmp.MoM.IsNull()) os << "M"; + else + os << "N"; break; } case(EVENT_U): @@ -108,8 +92,8 @@ std::ostream& operator<<(std::ostream& os, const event& in) break; case(EVENT_KMDHEIGHT): { - event_kmdheight* tmp = dynamic_cast(const_cast(&in)); - if (tmp->timestamp == 0) + const event_kmdheight& tmp = static_cast(in); + if (tmp.timestamp == 0) os << "K"; else os << "T"; @@ -135,7 +119,7 @@ std::ostream& operator<<(std::ostream& os, const event& in) * @param pos the starting position (will advance) * @param data_len full length of data */ -event_pubkeys::event_pubkeys(uint8_t* data, long& pos, long data_len, int32_t height) : event(EVENT_PUBKEYS, height) +event_pubkeys::event_pubkeys(uint8_t* data, long& pos, long data_len, int32_t height) : event_pubkeys(height) { num = data[pos++]; if (num > 64) @@ -143,7 +127,7 @@ event_pubkeys::event_pubkeys(uint8_t* data, long& pos, long data_len, int32_t he mem_nread(pubkeys, num, data, pos, data_len); } -event_pubkeys::event_pubkeys(FILE* fp, int32_t height) : event(EVENT_PUBKEYS, height) +event_pubkeys::event_pubkeys(FILE* fp, int32_t height) : event_pubkeys(height) { num = fgetc(fp); if ( fread(pubkeys,33,num,fp) != num ) @@ -152,30 +136,34 @@ event_pubkeys::event_pubkeys(FILE* fp, int32_t height) : event(EVENT_PUBKEYS, he std::ostream& operator<<(std::ostream& os, const event_pubkeys& in) { - const event& e = dynamic_cast(in); + const event& e = static_cast(in); os << e; os << in.num; - for(uint8_t i = 0; i < in.num-1; ++i) - os << in.pubkeys[i]; + for(uint8_t i = 0; i < in.num; ++i) + for(uint8_t j = 0; j < 33; ++j) + os << in.pubkeys[i][j]; return os; } -event_rewind::event_rewind(uint8_t *data, long &pos, long data_len, int32_t height) : event(EVENT_REWIND, height) +event_rewind::event_rewind(uint8_t *data, long &pos, long data_len, int32_t height) : event_rewind(height) { // nothing to do } std::ostream& operator<<(std::ostream& os, const event_rewind& in) { - const event& e = dynamic_cast(in); + const event& e = static_cast(in); os << e; return os; } -event_notarized::event_notarized(uint8_t *data, long &pos, long data_len, int32_t height, const char* _dest, bool includeMoM) - : event(EVENT_NOTARIZED, height), MoMdepth(0) +event_notarized::event_notarized(uint8_t *data, long &pos, long data_len, int32_t height, + const char* _dest, bool includeMoM) + : event_notarized(height, _dest) { - strncpy(this->dest, _dest, sizeof(this->dest)-1); - this->dest[sizeof(this->dest)-1] = 0; + // init via event_notarized(height, dest) + //if (_dest != nullptr) + // strncpy(this->dest, _dest, sizeof(this->dest)-1); + //this->dest[sizeof(this->dest)-1] = 0; MoM.SetNull(); mem_read(this->notarizedheight, data, pos, data_len); mem_read(this->blockhash, data, pos, data_len); @@ -188,10 +176,12 @@ event_notarized::event_notarized(uint8_t *data, long &pos, long data_len, int32_ } event_notarized::event_notarized(FILE* fp, int32_t height, const char* _dest, bool includeMoM) - : event(EVENT_NOTARIZED, height), MoMdepth(0) + : event_notarized(height, _dest) { - strncpy(this->dest, _dest, sizeof(this->dest)-1); - this->dest[sizeof(this->dest)-1] = 0; + // init via event_notarized(height, dest) + //if (_dest != nullptr) + // strncpy(this->dest, _dest, sizeof(this->dest)-1); + //this->dest[sizeof(this->dest)-1] = 0; MoM.SetNull(); if ( fread(¬arizedheight,1,sizeof(notarizedheight),fp) != sizeof(notarizedheight) ) throw parse_error("Invalid notarization height"); @@ -210,12 +200,12 @@ event_notarized::event_notarized(FILE* fp, int32_t height, const char* _dest, bo std::ostream& operator<<(std::ostream& os, const event_notarized& in) { - const event& e = dynamic_cast(in); + const event& e = static_cast(in); os << e; os << serializable(in.notarizedheight); os << serializable(in.blockhash); os << serializable(in.desttxid); - if (in.MoMdepth > 0) + if (in.MoMdepth != 0 && !in.MoM.IsNull()) { os << serializable(in.MoM); os << serializable(in.MoMdepth); @@ -223,7 +213,7 @@ std::ostream& operator<<(std::ostream& os, const event_notarized& in) return os; } -event_u::event_u(uint8_t *data, long &pos, long data_len, int32_t height) : event(EVENT_U, height) +event_u::event_u(uint8_t *data, long &pos, long data_len, int32_t height) : event_u(height) { mem_read(this->n, data, pos, data_len); mem_read(this->nid, data, pos, data_len); @@ -231,7 +221,7 @@ event_u::event_u(uint8_t *data, long &pos, long data_len, int32_t height) : even mem_read(this->hash, data, pos, data_len); } -event_u::event_u(FILE *fp, int32_t height) : event(EVENT_U, height) +event_u::event_u(FILE *fp, int32_t height) : event_u(height) { if (fread(&n, 1, sizeof(n), fp) != sizeof(n)) throw parse_error("Unable to read n of event U from file"); @@ -245,7 +235,7 @@ event_u::event_u(FILE *fp, int32_t height) : event(EVENT_U, height) std::ostream& operator<<(std::ostream& os, const event_u& in) { - const event& e = dynamic_cast(in); + const event& e = static_cast(in); os << e; os << in.n << in.nid; os.write((const char*)in.mask, 8); @@ -253,14 +243,16 @@ std::ostream& operator<<(std::ostream& os, const event_u& in) return os; } -event_kmdheight::event_kmdheight(uint8_t* data, long &pos, long data_len, int32_t height, bool includeTimestamp) : event(EVENT_KMDHEIGHT, height) +event_kmdheight::event_kmdheight(uint8_t* data, long &pos, long data_len, int32_t height, + bool includeTimestamp) : event_kmdheight(height) { mem_read(this->kheight, data, pos, data_len); if (includeTimestamp) mem_read(this->timestamp, data, pos, data_len); } -event_kmdheight::event_kmdheight(FILE *fp, int32_t height, bool includeTimestamp) : event(EVENT_KMDHEIGHT, height) +event_kmdheight::event_kmdheight(FILE *fp, int32_t height, bool includeTimestamp) + : event_kmdheight(height) { if ( fread(&kheight,1,sizeof(kheight),fp) != sizeof(kheight) ) throw parse_error("Unable to parse KMD height"); @@ -273,14 +265,15 @@ event_kmdheight::event_kmdheight(FILE *fp, int32_t height, bool includeTimestamp std::ostream& operator<<(std::ostream& os, const event_kmdheight& in) { - const event& e = dynamic_cast(in); + const event& e = static_cast(in); os << e << serializable(in.kheight); if (in.timestamp > 0) os << serializable(in.timestamp); return os; } -event_opreturn::event_opreturn(uint8_t *data, long &pos, long data_len, int32_t height) : event(EVENT_OPRETURN, height) +event_opreturn::event_opreturn(uint8_t *data, long &pos, long data_len, int32_t height) + : event_opreturn(height) { mem_read(this->txid, data, pos, data_len); mem_read(this->vout, data, pos, data_len); @@ -294,7 +287,7 @@ event_opreturn::event_opreturn(uint8_t *data, long &pos, long data_len, int32_t } } -event_opreturn::event_opreturn(FILE* fp, int32_t height) : event(EVENT_OPRETURN, height) +event_opreturn::event_opreturn(FILE* fp, int32_t height) : event_opreturn(height) { if ( fread(&txid,1,sizeof(txid),fp) != sizeof(txid) ) throw parse_error("Unable to parse txid of opreturn record"); @@ -312,7 +305,7 @@ event_opreturn::event_opreturn(FILE* fp, int32_t height) : event(EVENT_OPRETURN, std::ostream& operator<<(std::ostream& os, const event_opreturn& in) { - const event& e = dynamic_cast(in); + const event& e = static_cast(in); os << e << serializable(in.txid) << serializable(in.vout) @@ -322,7 +315,8 @@ std::ostream& operator<<(std::ostream& os, const event_opreturn& in) return os; } -event_pricefeed::event_pricefeed(uint8_t *data, long &pos, long data_len, int32_t height) : event(EVENT_PRICEFEED, height) +event_pricefeed::event_pricefeed(uint8_t *data, long &pos, long data_len, int32_t height) + : event_pricefeed(height) { mem_read(this->num, data, pos, data_len); // we're only interested if there are 35 prices. @@ -333,7 +327,8 @@ event_pricefeed::event_pricefeed(uint8_t *data, long &pos, long data_len, int32_ pos += num * sizeof(uint32_t); } -event_pricefeed::event_pricefeed(FILE* fp, int32_t height) : event(EVENT_PRICEFEED, height) +event_pricefeed::event_pricefeed(FILE* fp, int32_t height) + : event_pricefeed(height) { num = fgetc(fp); if ( num * sizeof(uint32_t) <= sizeof(prices) && fread(prices,sizeof(uint32_t),num,fp) != num ) @@ -342,7 +337,7 @@ event_pricefeed::event_pricefeed(FILE* fp, int32_t height) : event(EVENT_PRICEFE std::ostream& operator<<(std::ostream& os, const event_pricefeed& in) { - const event& e = dynamic_cast(in); + const event& e = static_cast(in); os << e << (uint8_t)in.num; os.write((const char*)in.prices, in.num * sizeof(uint32_t)); return os; diff --git a/src/komodo_structs.h b/src/komodo_structs.h index 6f4f0135186..152a51de915 100644 --- a/src/komodo_structs.h +++ b/src/komodo_structs.h @@ -19,40 +19,22 @@ #include #include "komodo_defs.h" +#include "komodo_extern_globals.h" #include "uthash.h" #include "utlist.h" #define GENESIS_NBITS 0x1f00ffff #define KOMODO_MINRATIFY ((height < 90000) ? 7 : 11) -#define KOMODO_NOTARIES_HARDCODED 180000 // DONT CHANGE +#define KOMODO_NOTARIES_HARDCODED 180000 // DONT CHANGE Below this height notaries were hardcoded #define KOMODO_MAXBLOCKS 250000 // DONT CHANGE -#define KOMODO_EVENT_RATIFY 'P' -#define KOMODO_EVENT_NOTARIZED 'N' -#define KOMODO_EVENT_KMDHEIGHT 'K' -#define KOMODO_EVENT_REWIND 'B' -#define KOMODO_EVENT_PRICEFEED 'V' -#define KOMODO_EVENT_OPRETURN 'R' -#define KOMODO_OPRETURN_DEPOSIT 'D' -#define KOMODO_OPRETURN_ISSUED 'I' // assetchain -#define KOMODO_OPRETURN_WITHDRAW 'W' // assetchain -#define KOMODO_OPRETURN_REDEEMED 'X' - -#define KOMODO_KVPROTECTED 1 -#define KOMODO_KVBINARY 2 -#define KOMODO_KVDURATION 1440 #define KOMODO_ASSETCHAIN_MAXLEN 65 #include "bits256.h" +#include -// structs prior to refactor -struct komodo_kv { UT_hash_handle hh; bits256 pubkey; uint8_t *key,*value; int32_t height; uint32_t flags; uint16_t keylen,valuesize; }; - -struct komodo_event_notarized { uint256 blockhash,desttxid,MoM; int32_t notarizedheight,MoMdepth; char dest[16]; }; -struct komodo_event_pubkeys { uint8_t num; uint8_t pubkeys[64][33]; }; -struct komodo_event_opreturn { uint256 txid; uint64_t value; uint16_t vout,oplen; uint8_t opret[]; }; -struct komodo_event_pricefeed { uint8_t num; uint32_t prices[35]; }; +//extern std::mutex komodo_mutex; //todo remove struct komodo_event { @@ -64,6 +46,21 @@ struct komodo_event uint8_t space[]; }; +/*** + * @brief persist event to file stream + * @param evt the event + * @param fp the file + * @returns the number of bytes written + */ +template +size_t write_event(T& evt, FILE *fp) +{ + std::stringstream ss; + ss << evt; + std::string buf = ss.str(); + return fwrite(buf.c_str(), buf.size(), 1, fp); +} + namespace komodo { enum komodo_event_type @@ -112,7 +109,7 @@ struct event_notarized : public event event_notarized() : event(komodo_event_type::EVENT_NOTARIZED, 0), notarizedheight(0), MoMdepth(0) { memset(this->dest, 0, sizeof(this->dest)); } - event_notarized(int32_t ht, const char* _dest) : event(EVENT_NOTARIZED, ht), notarizedheight(0), MoMdepth(0) { + event_notarized(int32_t ht, const char* _dest) : event(komodo_event_type::EVENT_NOTARIZED, ht), notarizedheight(0), MoMdepth(0) { strncpy(this->dest, _dest, sizeof(this->dest)-1); this->dest[sizeof(this->dest)-1] = 0; } event_notarized(uint8_t* data, long &pos, long data_len, int32_t height, const char* _dest, bool includeMoM = false); @@ -222,19 +219,13 @@ std::ostream& operator<<(std::ostream& os, const event_pricefeed& in); } // namespace komodo -struct pax_transaction -{ - UT_hash_handle hh; - uint256 txid; - uint64_t komodoshis,fiatoshis,validated; - int32_t marked,height,otherheight,approved,didstats,ready; - uint16_t vout; - char symbol[KOMODO_ASSETCHAIN_MAXLEN],source[KOMODO_ASSETCHAIN_MAXLEN],coinaddr[64]; uint8_t rmd160[20],type,buf[35]; -}; - struct knotary_entry { UT_hash_handle hh; uint8_t pubkey[33],notaryid; }; -struct knotaries_entry { int32_t height,numnotaries; struct knotary_entry *Notaries; }; - +struct knotaries_entry +{ + int32_t height; + int32_t numnotaries; // The number of notaries stored in Notaries + knotary_entry *Notaries; // A hashtable of notary ID/public key +}; struct notarized_checkpoint { uint256 notarized_hash; @@ -280,6 +271,7 @@ struct komodo_ccdata class komodo_state { public: + std::string symbol; int32_t SAVEDHEIGHT; int32_t CURRENT_HEIGHT; uint32_t SAVEDTIMESTAMP; @@ -291,7 +283,19 @@ class komodo_state uint64_t shorted; std::list> events; uint32_t RTbufs[64][3]; uint64_t RTmask; - bool add_event(const std::string& symbol, const uint32_t height, std::shared_ptr in); + template + bool add_event(const std::string& symbol, const uint32_t height, T& in) + { + if (!chainName.isKMD()) + { + std::shared_ptr ptr = std::make_shared( in ); + std::lock_guard lock(komodo_mutex); + events.push_back( ptr ); + return true; + } + return false; + } + protected: /*** * @brief clear the checkpoints collection diff --git a/src/komodo_utils.cpp b/src/komodo_utils.cpp index 8c70a7f7bf9..d3d8fe3ea70 100644 --- a/src/komodo_utils.cpp +++ b/src/komodo_utils.cpp @@ -12,16 +12,19 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ +#include "komodo_defs.h" +#include "komodo.h" #include "komodo_utils.h" -#include "komodo_extern_globals.h" +#include "komodo_globals.h" #include "komodo_notary.h" +#include "komodo_gateway.h" +#include "notaries_staked.h" + +#include "cc/CCinclude.h" void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len) { - struct sha256_vstate md; - sha256_vinit(&md); - sha256_vprocess(&md,src,len); - sha256_vdone(&md,hash); + CSHA256().Write((const unsigned char *)src, len).Finalize(hash); } bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen) @@ -34,397 +37,6 @@ bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen) return(hash); } -// rmd160: the five basic functions F(), G() and H() -#define F(x, y, z) ((x) ^ (y) ^ (z)) -#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define H(x, y, z) (((x) | ~(y)) ^ (z)) -#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define J(x, y, z) ((x) ^ ((y) | ~(z))) -#define ROLc(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) - -/* the ten basic operations FF() through III() */ -#define FF(a, b, c, d, e, x, s) \ -(a) += F((b), (c), (d)) + (x);\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define GG(a, b, c, d, e, x, s) \ -(a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define HH(a, b, c, d, e, x, s) \ -(a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define II(a, b, c, d, e, x, s) \ -(a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define JJ(a, b, c, d, e, x, s) \ -(a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define FFF(a, b, c, d, e, x, s) \ -(a) += F((b), (c), (d)) + (x);\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define GGG(a, b, c, d, e, x, s) \ -(a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define HHH(a, b, c, d, e, x, s) \ -(a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define III(a, b, c, d, e, x, s) \ -(a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define JJJ(a, b, c, d, e, x, s) \ -(a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -static int32_t rmd160_vcompress(struct rmd160_vstate *md,uint8_t *buf) -{ - uint32_t aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,X[16]; - int i; - - /* load words X */ - for (i = 0; i < 16; i++){ - LOAD32L(X[i], buf + (4 * i)); - } - - /* load state */ - aa = aaa = md->state[0]; - bb = bbb = md->state[1]; - cc = ccc = md->state[2]; - dd = ddd = md->state[3]; - ee = eee = md->state[4]; - - /* round 1 */ - FF(aa, bb, cc, dd, ee, X[ 0], 11); - FF(ee, aa, bb, cc, dd, X[ 1], 14); - FF(dd, ee, aa, bb, cc, X[ 2], 15); - FF(cc, dd, ee, aa, bb, X[ 3], 12); - FF(bb, cc, dd, ee, aa, X[ 4], 5); - FF(aa, bb, cc, dd, ee, X[ 5], 8); - FF(ee, aa, bb, cc, dd, X[ 6], 7); - FF(dd, ee, aa, bb, cc, X[ 7], 9); - FF(cc, dd, ee, aa, bb, X[ 8], 11); - FF(bb, cc, dd, ee, aa, X[ 9], 13); - FF(aa, bb, cc, dd, ee, X[10], 14); - FF(ee, aa, bb, cc, dd, X[11], 15); - FF(dd, ee, aa, bb, cc, X[12], 6); - FF(cc, dd, ee, aa, bb, X[13], 7); - FF(bb, cc, dd, ee, aa, X[14], 9); - FF(aa, bb, cc, dd, ee, X[15], 8); - - /* round 2 */ - GG(ee, aa, bb, cc, dd, X[ 7], 7); - GG(dd, ee, aa, bb, cc, X[ 4], 6); - GG(cc, dd, ee, aa, bb, X[13], 8); - GG(bb, cc, dd, ee, aa, X[ 1], 13); - GG(aa, bb, cc, dd, ee, X[10], 11); - GG(ee, aa, bb, cc, dd, X[ 6], 9); - GG(dd, ee, aa, bb, cc, X[15], 7); - GG(cc, dd, ee, aa, bb, X[ 3], 15); - GG(bb, cc, dd, ee, aa, X[12], 7); - GG(aa, bb, cc, dd, ee, X[ 0], 12); - GG(ee, aa, bb, cc, dd, X[ 9], 15); - GG(dd, ee, aa, bb, cc, X[ 5], 9); - GG(cc, dd, ee, aa, bb, X[ 2], 11); - GG(bb, cc, dd, ee, aa, X[14], 7); - GG(aa, bb, cc, dd, ee, X[11], 13); - GG(ee, aa, bb, cc, dd, X[ 8], 12); - - /* round 3 */ - HH(dd, ee, aa, bb, cc, X[ 3], 11); - HH(cc, dd, ee, aa, bb, X[10], 13); - HH(bb, cc, dd, ee, aa, X[14], 6); - HH(aa, bb, cc, dd, ee, X[ 4], 7); - HH(ee, aa, bb, cc, dd, X[ 9], 14); - HH(dd, ee, aa, bb, cc, X[15], 9); - HH(cc, dd, ee, aa, bb, X[ 8], 13); - HH(bb, cc, dd, ee, aa, X[ 1], 15); - HH(aa, bb, cc, dd, ee, X[ 2], 14); - HH(ee, aa, bb, cc, dd, X[ 7], 8); - HH(dd, ee, aa, bb, cc, X[ 0], 13); - HH(cc, dd, ee, aa, bb, X[ 6], 6); - HH(bb, cc, dd, ee, aa, X[13], 5); - HH(aa, bb, cc, dd, ee, X[11], 12); - HH(ee, aa, bb, cc, dd, X[ 5], 7); - HH(dd, ee, aa, bb, cc, X[12], 5); - - /* round 4 */ - II(cc, dd, ee, aa, bb, X[ 1], 11); - II(bb, cc, dd, ee, aa, X[ 9], 12); - II(aa, bb, cc, dd, ee, X[11], 14); - II(ee, aa, bb, cc, dd, X[10], 15); - II(dd, ee, aa, bb, cc, X[ 0], 14); - II(cc, dd, ee, aa, bb, X[ 8], 15); - II(bb, cc, dd, ee, aa, X[12], 9); - II(aa, bb, cc, dd, ee, X[ 4], 8); - II(ee, aa, bb, cc, dd, X[13], 9); - II(dd, ee, aa, bb, cc, X[ 3], 14); - II(cc, dd, ee, aa, bb, X[ 7], 5); - II(bb, cc, dd, ee, aa, X[15], 6); - II(aa, bb, cc, dd, ee, X[14], 8); - II(ee, aa, bb, cc, dd, X[ 5], 6); - II(dd, ee, aa, bb, cc, X[ 6], 5); - II(cc, dd, ee, aa, bb, X[ 2], 12); - - /* round 5 */ - JJ(bb, cc, dd, ee, aa, X[ 4], 9); - JJ(aa, bb, cc, dd, ee, X[ 0], 15); - JJ(ee, aa, bb, cc, dd, X[ 5], 5); - JJ(dd, ee, aa, bb, cc, X[ 9], 11); - JJ(cc, dd, ee, aa, bb, X[ 7], 6); - JJ(bb, cc, dd, ee, aa, X[12], 8); - JJ(aa, bb, cc, dd, ee, X[ 2], 13); - JJ(ee, aa, bb, cc, dd, X[10], 12); - JJ(dd, ee, aa, bb, cc, X[14], 5); - JJ(cc, dd, ee, aa, bb, X[ 1], 12); - JJ(bb, cc, dd, ee, aa, X[ 3], 13); - JJ(aa, bb, cc, dd, ee, X[ 8], 14); - JJ(ee, aa, bb, cc, dd, X[11], 11); - JJ(dd, ee, aa, bb, cc, X[ 6], 8); - JJ(cc, dd, ee, aa, bb, X[15], 5); - JJ(bb, cc, dd, ee, aa, X[13], 6); - - /* parallel round 1 */ - JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); - JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); - JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); - JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); - JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); - JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); - JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); - JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); - JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); - JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); - - /* parallel round 2 */ - III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); - III(ddd, eee, aaa, bbb, ccc, X[11], 13); - III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); - III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); - III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); - III(eee, aaa, bbb, ccc, ddd, X[13], 8); - III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); - III(ccc, ddd, eee, aaa, bbb, X[10], 11); - III(bbb, ccc, ddd, eee, aaa, X[14], 7); - III(aaa, bbb, ccc, ddd, eee, X[15], 7); - III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); - III(ddd, eee, aaa, bbb, ccc, X[12], 7); - III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); - III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); - III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); - III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); - - /* parallel round 3 */ - HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); - HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); - HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); - HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); - HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); - HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); - HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); - HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); - HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); - HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); - HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); - HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); - HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); - HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); - HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); - HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); - - /* parallel round 4 */ - GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); - GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); - GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); - GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); - GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); - GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); - GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); - GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); - GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); - GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); - GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); - GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); - GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); - GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); - GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); - GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); - - /* parallel round 5 */ - FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); - FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); - FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); - FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); - FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); - FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); - FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); - FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); - FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); - FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); - FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); - FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); - FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); - FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); - FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); - FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); - - /* combine results */ - ddd += cc + md->state[1]; /* final result for md->state[0] */ - md->state[1] = md->state[2] + dd + eee; - md->state[2] = md->state[3] + ee + aaa; - md->state[3] = md->state[4] + aa + bbb; - md->state[4] = md->state[0] + bb + ccc; - md->state[0] = ddd; - - return 0; -} - -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return 0 if successful - */ -int rmd160_vinit(struct rmd160_vstate * md) -{ - md->state[0] = 0x67452301UL; - md->state[1] = 0xefcdab89UL; - md->state[2] = 0x98badcfeUL; - md->state[3] = 0x10325476UL; - md->state[4] = 0xc3d2e1f0UL; - md->curlen = 0; - md->length = 0; - return 0; -} - -/** - Process a block of memory though the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return 0 if successful - */ -int rmd160_vprocess (struct rmd160_vstate * md, const unsigned char *in, unsigned long inlen) -{ - unsigned long n; - int err; - if (md->curlen > sizeof(md->buf)) { - return -1; - } - while (inlen > 0) { - if (md->curlen == 0 && inlen >= 64) { - if ((err = rmd160_vcompress (md, (unsigned char *)in)) != 0) { - return err; - } - md->length += 64 * 8; - in += 64; - inlen -= 64; - } else { - n = MIN(inlen, (64 - md->curlen)); - memcpy(md->buf + md->curlen, in, (size_t)n); - md->curlen += n; - in += n; - inlen -= n; - if (md->curlen == 64) { - if ((err = rmd160_vcompress (md, md->buf)) != 0) { - return err; - } - md->length += 8*64; - md->curlen = 0; - } - } - } - return 0; -} - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (20 bytes) - @return 0 if successful - */ -int rmd160_vdone(struct rmd160_vstate * md, unsigned char *out) -{ - int i; - if (md->curlen >= sizeof(md->buf)) { - return -1; - } - /* increase the length of the message */ - md->length += md->curlen * 8; - - /* append the '1' bit */ - md->buf[md->curlen++] = (unsigned char)0x80; - - /* if the length is currently above 56 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->curlen > 56) { - while (md->curlen < 64) { - md->buf[md->curlen++] = (unsigned char)0; - } - rmd160_vcompress(md, md->buf); - md->curlen = 0; - } - /* pad upto 56 bytes of zeroes */ - while (md->curlen < 56) { - md->buf[md->curlen++] = (unsigned char)0; - } - /* store length */ - STORE64L(md->length, md->buf+56); - rmd160_vcompress(md, md->buf); - /* copy output */ - for (i = 0; i < 5; i++) { - STORE32L(md->state[i], out+(4*i)); - } - return 0; -} - -void calc_rmd160(char deprecated[41],uint8_t buf[20],uint8_t *msg,int32_t len) -{ - struct rmd160_vstate md; - rmd160_vinit(&md); - rmd160_vprocess(&md,msg,len); - rmd160_vdone(&md, buf); -} -#undef F -#undef G -#undef H -#undef I -#undef J -#undef ROLc -#undef FF -#undef GG -#undef HH -#undef II -#undef JJ -#undef FFF -#undef GGG -#undef HHH -#undef III -#undef JJJ - static const uint32_t crc32_tab[] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, @@ -486,12 +98,10 @@ uint32_t calc_crc32(uint32_t crc,const void *buf,size_t size) void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen) { - bits256 hash; - vcalc_sha256(0,hash.bytes,data,datalen); - calc_rmd160(0,rmd160,hash.bytes,sizeof(hash)); + CHash160().Write((const unsigned char *)data, datalen).Finalize(rmd160); // SHA-256 + RIPEMD-160 } -int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr) +int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],const char *coinaddr) { bits256 hash; uint8_t *buf,_buf[25]; int32_t len; memset(rmd160,0,20); @@ -525,31 +135,32 @@ int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len) { - int32_t i; uint8_t data[25]; bits256 hash;// char checkaddr[65]; + int32_t i; + uint8_t data[25]; + bits256 hash; if ( len != 20 ) calc_rmd160_sha256(data+1,pubkey_or_rmd160,len); - else memcpy(data+1,pubkey_or_rmd160,20); - //btc_convrmd160(checkaddr,addrtype,data+1); + else + memcpy(data+1,pubkey_or_rmd160,20); data[0] = addrtype; hash = bits256_doublesha256(0,data,21); for (i=0; i<4; i++) data[21+i] = hash.bytes[31-i]; - if ( (coinaddr= bitcoin_base58encode(coinaddr,data,25)) != 0 ) - { - //uint8_t checktype,rmd160[20]; - //bitcoin_addr2rmd160(&checktype,rmd160,coinaddr); - //if ( strcmp(checkaddr,coinaddr) != 0 ) - // printf("checkaddr.(%s) vs coinaddr.(%s) %02x vs [%02x] memcmp.%d\n",checkaddr,coinaddr,addrtype,checktype,memcmp(rmd160,data+1,20)); - } - return(coinaddr); + return bitcoin_base58encode(coinaddr,data,25); } -int32_t komodo_is_issuer() + +/*int32_t komodo_baseid(const char *origbase) { - if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) >= 0 ) - return(1); - else return(0); -} + int32_t i; char base[64]; + for (i=0; origbase[i]!=0&&i= 0x4c ) - { - if ( opretlen == 0x4c ) - opretlen = script[len++]; - else if ( opretlen == 0x4d ) - { - opretlen = script[len] + (script[len+1] << 8); - len += 2; - //opretlen = script[len++]; - //opretlen = (opretlen << 8) | script[len++]; - } - } - *opretlenp = opretlen; - return(len); -} - int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen) { int32_t offset = 0; @@ -749,171 +341,67 @@ void OS_randombytes(unsigned char *x,long xlen) } #endif -void lock_queue(queue_t *queue) -{ - if ( queue->initflag == 0 ) - { - portable_mutex_init(&queue->mutex); - queue->initflag = 1; - } - portable_mutex_lock(&queue->mutex); -} - -void queue_enqueue(char *name,queue_t *queue,struct queueitem *item) -{ - if ( queue->name[0] == 0 && name != 0 && name[0] != 0 ) - strcpy(queue->name,name); - if ( item == 0 ) - { - printf("FATAL type error: queueing empty value\n"); - return; - } - lock_queue(queue); - DL_APPEND(queue->list,item); - portable_mutex_unlock(&queue->mutex); -} - -struct queueitem *queue_dequeue(queue_t *queue) -{ - struct queueitem *item = 0; - lock_queue(queue); - if ( queue->list != 0 ) - { - item = queue->list; - DL_DELETE(queue->list,item); - } - portable_mutex_unlock(&queue->mutex); - return(item); -} - -void *queue_delete(queue_t *queue,struct queueitem *copy,int32_t copysize) -{ - struct queueitem *item = 0; - lock_queue(queue); - if ( queue->list != 0 ) - { - DL_FOREACH(queue->list,item) - { - #ifdef _WIN32 - if ( item == copy || (item->allocsize == copysize && memcmp((void *)((intptr_t)item + sizeof(struct queueitem)),(void *)((intptr_t)copy + sizeof(struct queueitem)),copysize) == 0) ) - #else - if ( item == copy || (item->allocsize == copysize && memcmp((void *)((long)item + sizeof(struct queueitem)),(void *)((long)copy + sizeof(struct queueitem)),copysize) == 0) ) - #endif - { - DL_DELETE(queue->list,item); - portable_mutex_unlock(&queue->mutex); - printf("name.(%s) deleted item.%p list.%p\n",queue->name,item,queue->list); - return(item); - } - } - } - portable_mutex_unlock(&queue->mutex); - return(0); -} - -void *queue_free(queue_t *queue) -{ - struct queueitem *item = 0; - lock_queue(queue); - if ( queue->list != 0 ) - { - DL_FOREACH(queue->list,item) - { - DL_DELETE(queue->list,item); - free(item); - } - //printf("name.(%s) dequeue.%p list.%p\n",queue->name,item,queue->list); - } - portable_mutex_unlock(&queue->mutex); - return(0); -} - -void *queue_clone(queue_t *clone,queue_t *queue,int32_t size) -{ - struct queueitem *ptr,*item = 0; - lock_queue(queue); - if ( queue->list != 0 ) - { - DL_FOREACH(queue->list,item) - { - ptr = (struct queueitem *)calloc(1,sizeof(*ptr)); - memcpy(ptr,item,size); - queue_enqueue(queue->name,clone,ptr); - } - //printf("name.(%s) dequeue.%p list.%p\n",queue->name,item,queue->list); - } - portable_mutex_unlock(&queue->mutex); - return(0); -} - -int32_t queue_size(queue_t *queue) +/** + * @brief Get the username, password, and port from a file + * @param[out] username the username found in the config file + * @param[out] password the password found in the config file + * @param[in] fp the file to be read + * @return the RPC port + */ +uint16_t _komodo_userpass(char *username,char *password,FILE *fp) { - int32_t count = 0; - struct queueitem *tmp; - lock_queue(queue); - DL_COUNT(queue->list,tmp,count); - portable_mutex_unlock(&queue->mutex); - return count; -} + uint16_t port = 0; + char *rpcuser = nullptr; + char *rpcpassword = nullptr; + char line[8192]; -void iguana_initQ(queue_t *Q,char *name) -{ - struct queueitem *item,*I; - memset(Q,0,sizeof(*Q)); - I = (struct queueitem *)calloc(1,sizeof(*I)); - strcpy(Q->name,name); - queue_enqueue(name,Q,I); - if ( (item= queue_dequeue(Q)) != 0 ) - free(item); -} + username[0] = 0; + password[0] = 0; -uint16_t _komodo_userpass(char *username,char *password,FILE *fp) -{ - char *rpcuser,*rpcpassword,*str,line[8192]; uint16_t port = 0; - rpcuser = rpcpassword = 0; - username[0] = password[0] = 0; while ( fgets(line,sizeof(line),fp) != 0 ) { + char *str = nullptr; if ( line[0] == '#' ) continue; - //printf("line.(%s) %p %p\n",line,strstr(line,(char *)"rpcuser"),strstr(line,(char *)"rpcpassword")); - if ( (str= strstr(line,(char *)"rpcuser")) != 0 ) + if ( (str= strstr(line,(char *)"rpcuser")) != nullptr ) + { rpcuser = parse_conf_line(str,(char *)"rpcuser"); - else if ( (str= strstr(line,(char *)"rpcpassword")) != 0 ) + } + else if ( (str= strstr(line,(char *)"rpcpassword")) != nullptr ) + { rpcpassword = parse_conf_line(str,(char *)"rpcpassword"); - else if ( (str= strstr(line,(char *)"rpcport")) != 0 ) + } + else if ( (str= strstr(line,(char *)"rpcport")) != nullptr ) { port = atoi(parse_conf_line(str,(char *)"rpcport")); - //fprintf(stderr,"rpcport.%u in file\n",port); } } - if ( rpcuser != 0 && rpcpassword != 0 ) + if ( rpcuser != nullptr && rpcpassword != nullptr ) { strcpy(username,rpcuser); strcpy(password,rpcpassword); } - //printf("rpcuser.(%s) rpcpassword.(%s) KMDUSERPASS.(%s) %u\n",rpcuser,rpcpassword,KMDUSERPASS,port); - if ( rpcuser != 0 ) + if ( rpcuser != nullptr ) free(rpcuser); - if ( rpcpassword != 0 ) + if ( rpcpassword != nullptr ) free(rpcpassword); - return(port); + return port; } -void komodo_statefname(char *fname,char *symbol,char *str) +void komodo_statefname(char *fname, const char *symbol, const char *str) { int32_t n,len; - sprintf(fname,"%s",GetDataDir(false).string().c_str()); - if ( (n= (int32_t)strlen(ASSETCHAINS_SYMBOL)) != 0 ) + snprintf(fname, MAX_STATEFNAME, "%s",GetDataDir(false).string().c_str()); + if ( (n= (int32_t)chainName.symbol().size()) != 0 ) { len = (int32_t)strlen(fname); - if ( !mapArgs.count("-datadir") && strcmp(ASSETCHAINS_SYMBOL,&fname[len - n]) == 0 ) + if ( !mapArgs.count("-datadir") && strcmp(chainName.symbol().c_str(),&fname[len - n]) == 0 ) fname[len - n] = 0; else if(mapArgs.count("-datadir")) printf("DEBUG - komodo_utils:1363: custom datadir\n"); else { if ( strcmp(symbol,"REGTEST") != 0 ) - printf("unexpected fname.(%s) vs %s [%s] n.%d len.%d (%s)\n",fname,symbol,ASSETCHAINS_SYMBOL,n,len,&fname[len - n]); + printf("unexpected fname.(%s) vs %s [%s] n.%d len.%d (%s)\n",fname,symbol,chainName.symbol().c_str(),n,len,&fname[len - n]); return; } } @@ -928,7 +416,6 @@ void komodo_statefname(char *fname,char *symbol,char *str) if ( symbol != 0 && symbol[0] != 0 && strcmp("KMD",symbol) != 0 ) { if(!mapArgs.count("-datadir")) strcat(fname,symbol); - //printf("statefname.(%s) -> (%s)\n",symbol,fname); #ifdef _WIN32 strcat(fname,"\\"); #else @@ -936,10 +423,9 @@ void komodo_statefname(char *fname,char *symbol,char *str) #endif } strcat(fname,str); - //printf("test.(%s) -> [%s] statename.(%s) %s\n",test,ASSETCHAINS_SYMBOL,symbol,fname); } -void komodo_configfile(char *symbol,uint16_t rpcport) +void komodo_configfile(const char *symbol,uint16_t rpcport) { static char myusername[512],mypassword[8192]; FILE *fp; uint16_t kmdport; uint8_t buf2[33]; char fname[512],buf[128],username[512],password[8192]; uint32_t crc,r,r2,i; @@ -1007,11 +493,10 @@ void komodo_configfile(char *symbol,uint16_t rpcport) KMD_PORT = kmdport; sprintf(KMDUSERPASS,"%s:%s",username,password); fclose(fp); -//printf("KOMODO.(%s) -> userpass.(%s)\n",fname,KMDUSERPASS); - } //else printf("couldnt open.(%s)\n",fname); + } } -uint16_t komodo_userpass(char *userpass,char *symbol) +uint16_t komodo_userpass(char *userpass,const char *symbol) { FILE *fp; uint16_t port = 0; char fname[512],username[512],password[512],confname[KOMODO_ASSETCHAIN_MAXLEN]; userpass[0] = 0; @@ -1032,66 +517,85 @@ uint16_t komodo_userpass(char *userpass,char *symbol) { port = _komodo_userpass(username,password,fp); sprintf(userpass,"%s:%s",username,password); - if ( strcmp(symbol,ASSETCHAINS_SYMBOL) == 0 ) + if ( chainName.isSymbol(symbol) ) strcpy(ASSETCHAINS_USERPASS,userpass); fclose(fp); } return(port); } -uint32_t komodo_assetmagic(char *symbol,uint64_t supply,uint8_t *extraptr,int32_t extralen) +/** + * @brief Compute the magic number + * + * @param symbol the chain symbol + * @param supply max supply + * @param extraptr details of chain parameters + * @param extralen length of extraptr + * @return the magic number + */ +uint32_t komodo_assetmagic(const char *symbol,uint64_t supply,uint8_t *extraptr,int32_t extralen) { - uint8_t buf[512]; uint32_t crc0=0; int32_t len = 0; bits256 hash; + uint8_t buf[512]; + uint32_t crc0=0; + int32_t len = 0; + bits256 hash; if ( strcmp(symbol,"KMD") == 0 ) - return(0x8de4eef9); + return 0x8de4eef9; + len = iguana_rwnum(1,&buf[len],sizeof(supply),(void *)&supply); strcpy((char *)&buf[len],symbol); len += strlen(symbol); + if ( extraptr != 0 && extralen != 0 ) { + bits256 hash; vcalc_sha256(0,hash.bytes,extraptr,extralen); crc0 = hash.uints[0]; - int32_t i; for (i=0; i 0 ) + { + uint64_t lastEnd = j == 0 ? 0 : ASSETCHAINS_ENDSUBSIDY[j - 1]; + uint64_t curEnd = ASSETCHAINS_ENDSUBSIDY[j] == 0 ? nHeight : nHeight > ASSETCHAINS_ENDSUBSIDY[j] ? ASSETCHAINS_ENDSUBSIDY[j] : nHeight; + uint64_t period = ASSETCHAINS_HALVING[j]; + if ( period == 0 ) + period = 210000; + uint32_t nSteps = (curEnd - lastEnd) / period; + uint32_t modulo = (curEnd - lastEnd) % period; + uint64_t decay = ASSETCHAINS_DECAY[j]; + + //fprintf(stderr,"period.%llu cur_money %.8f += %.8f * %d\n",(long long)period,(double)cur_money/COIN,(double)reward/COIN,nHeight); + if ( ASSETCHAINS_HALVING[j] == 0 ) + { + // no halving, straight multiply + cur_money += reward * (nHeight - 1); + //fprintf(stderr,"cur_money %.8f\n",(double)cur_money/COIN); + } + // if exactly SATOSHIDEN, linear decay to zero or to next era, same as: + // (next_era_reward + (starting reward - next_era_reward) / 2) * num_blocks + else if ( decay == SATOSHIDEN ) + { + int64_t lowestSubsidy, subsidyDifference, stepDifference, stepTriangle; + int64_t denominator, modulo=1; + int32_t sign = 1; + + if ( j == ASSETCHAINS_LASTERA ) + { + subsidyDifference = reward; + lowestSubsidy = 0; + } + else + { + // Ex: -ac_eras=3 -ac_reward=0,384,24 -ac_end=1440,260640,0 -ac_halving=1,1440,2103840 -ac_decay 100000000,97750000,0 + subsidyDifference = reward - ASSETCHAINS_REWARD[j + 1]; + if (subsidyDifference < 0) + { + sign = -1; + subsidyDifference *= sign; + lowestSubsidy = reward; + } + else + { + lowestSubsidy = ASSETCHAINS_REWARD[j + 1]; + } + } + + // if we have not finished the current era, we need to caluclate a total as if we are at the end, with the current + // subsidy. we will calculate the total of a linear era as follows. Each item represents an area calculation: + // a) the rectangle from 0 to the lowest reward in the era * the number of blocks + // b) the rectangle of the remainder of blocks from the lowest point of the era to the highest point of the era if any remainder + // c) the minor triangle from the start of transition from the lowest point to the start of transition to the highest point + // d) one halving triangle (half area of one full step) + // + // we also need: + // e) number of steps = (n - erastart) / halving interval + // + // the total supply from era start up to height is: + // a + b + c + (d * e) + + // calculate amount in one step's triangular protrusion over minor triangle's hypotenuse + denominator = nSteps * period; + if ( denominator == 0 ) + denominator = 1; + // difference of one step vs. total + stepDifference = (period * subsidyDifference) / denominator; + + // area == coin holding of one step triangle, protruding from minor triangle's hypotenuse + stepTriangle = (period * stepDifference) >> 1; + + // sign is negative if slope is positive (start is less than end) + if (sign < 0) + { + // use steps minus one for our calculations, and add the potentially partial rectangle + // at the end + cur_money += stepTriangle * (nSteps - 1); + cur_money += stepTriangle * (nSteps - 1) * (nSteps - 1); + + // difference times number of steps is height of rectangle above lowest subsidy + cur_money += modulo * stepDifference * nSteps; + } + else + { + // if negative slope, the minor triangle is the full number of steps, as the highest + // level step is full. lowest subsidy is just the lowest so far + lowestSubsidy = reward - (stepDifference * nSteps); + + // add the step triangles, one per step + cur_money += stepTriangle * nSteps; + + // add the minor triangle + cur_money += stepTriangle * nSteps * nSteps; + } + + // add more for the base rectangle if lowest subsidy is not 0 + cur_money += lowestSubsidy * (curEnd - lastEnd); + } + else + { + for ( int k = lastEnd; k < curEnd; k += period ) + { + cur_money += period * reward; + // if zero, we do straight halving + reward = decay ? (reward * decay) / SATOSHIDEN : reward >> 1; + } + cur_money += modulo * reward; + } + } + } + } + } + if ( KOMODO_BIT63SET(cur_money) != 0 ) + return(KOMODO_MAXNVALUE); + if ( ASSETCHAINS_COMMISSION != 0 ) + { + uint64_t newval = (cur_money + (cur_money/COIN * ASSETCHAINS_COMMISSION)); + if ( KOMODO_BIT63SET(newval) != 0 ) + return(KOMODO_MAXNVALUE); + else if ( newval < cur_money ) // check for underflow + return(KOMODO_MAXNVALUE); + return(newval); + } + //fprintf(stderr,"cur_money %.8f\n",(double)cur_money/COIN); + return(cur_money); +} + uint64_t komodo_max_money() { return komodo_current_supply(10000000); @@ -1207,15 +867,13 @@ uint64_t komodo_ac_block_subsidy(int nHeight) else subsidy += ASSETCHAINS_SUPPLY * SATOSHIDEN + magicExtra; } - else if ( is_STAKED(ASSETCHAINS_SYMBOL) == 2 ) + else if ( is_STAKED(chainName.symbol()) == 2 ) return(0); // LABS fungible chains, cannot have any block reward! return(subsidy); } -extern int64_t MAX_MONEY; -void komodo_cbopretupdate(int32_t forceflag); -void SplitStr(const std::string& strVal, std::vector &outVals); +//void SplitStr(const std::string& strVal, std::vector &outVals); int8_t equihash_params_possible(uint64_t n, uint64_t k) { @@ -1239,21 +897,80 @@ int8_t equihash_params_possible(uint64_t n, uint64_t k) return(-1); } +/*** + * @brief get username, password, and port from a config file + * @param[in] path the path to the data directory + * @param[in] filename the filename of the config file (without directory) + * @param[out] userpass the username and password from the config file (colon separated) + * @param[out] port the RPC port found in the config file + */ +void get_userpass_and_port(const boost::filesystem::path& path, const std::string& filename, + std::string& userpass, uint16_t& port) +{ + userpass = ""; + port = 0; + boost::filesystem::path datadir_path = path; + datadir_path /= filename; + FILE* fp = fopen(datadir_path.string().c_str(), "rb"); + if ( fp != nullptr ) + { + char username[512]; + char password[4096]; + port = _komodo_userpass(username,password,fp); + if ( username[0] != 0 && password[0] != 0 ) + userpass = std::string(username) + ":" + std::string(password); + fclose(fp); + } + else + printf("couldnt open.(%s) will not validate dest notarizations\n", datadir_path.string().c_str()); +} + +/**** + * @brief set ports and usernames/passwords from command line and/or config files + * @note modifies ASSETCHAINS_P2PPORT, ASSETCHAINS_RPCPORT, KMDUSERPASS, BTCUSERPASS, DESTPORT + * @note IS_KOMODO_NOTARY should already be set + * @param ltc_config_filename configuration file for ltc (via -notary command line parameter) + */ +void set_kmd_user_password_port(const std::string& ltc_config_filename) +{ + ASSETCHAINS_P2PPORT = 7770; // default port for P2P + ASSETCHAINS_RPCPORT = 7771; // default port for RPC +#ifdef __APPLE__ + std::string filename = "Komodo.conf"; +#else + std::string filename = "komodo.conf"; +#endif + + auto datadir_path = GetDataDir(); + uint16_t ignore; + std::string userpass; + get_userpass_and_port(datadir_path, filename, userpass, ignore); + if (!userpass.empty()) + strncpy(KMDUSERPASS, userpass.c_str(), 8705); + if (IS_KOMODO_NOTARY) + { + auto approot_path = GetAppDir(); // go to app root dir + get_userpass_and_port(approot_path, ltc_config_filename, userpass, DEST_PORT); + if (!userpass.empty()) + strncpy(BTCUSERPASS, userpass.c_str(), 8192); + } +} + void komodo_args(char *argv0) { - std::string name,addn,hexstr,symbol; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[32756],disablebits[32],*extraptr=0; - FILE *fp; uint64_t val; uint16_t port, dest_rpc_port; int32_t i,nonz=0,baseid,len,n,extralen = 0; uint64_t ccenables[256], ccEnablesHeight[512] = {0}; CTransaction earlytx; uint256 hashBlock; + uint8_t disablebits[32]; + uint8_t *extraptr=nullptr; + FILE *fp; + uint16_t nonz=0; // keep track of # CCs enabled + int32_t extralen = 0; - std::string ntz_dest_path; - ntz_dest_path = GetArg("-notary", ""); + const std::string ntz_dest_path = GetArg("-notary", ""); IS_KOMODO_NOTARY = ntz_dest_path == "" ? 0 : 1; STAKED_NOTARY_ID = GetArg("-stakednotary", -1); KOMODO_NSPV = GetArg("-nSPV",0); - memset(ccenables,0,sizeof(ccenables)); - memset(disablebits,0,sizeof(disablebits)); - memset(ccEnablesHeight,0,sizeof(ccEnablesHeight)); + memset(disablebits,0,sizeof(disablebits)); // everything enabled if ( GetBoolArg("-gen", false) != 0 ) { KOMODO_MININGTHREADS = GetArg("-genproclimit",-1); @@ -1273,7 +990,7 @@ void komodo_args(char *argv0) // We dont have any chain data yet, so use system clock to guess. // I think on season change should reccomend notaries to use -notary to avoid needing this. int32_t kmd_season = getacseason(time(NULL)); - for (i=0; i<64; i++) + for (uint16_t i=0; i<64; i++) { if ( strcmp(NOTARY_PUBKEY.c_str(),notaries_elected[kmd_season-1][i][1]) == 0 ) { @@ -1291,13 +1008,13 @@ void komodo_args(char *argv0) fprintf(stderr, "Cannot be STAKED and KMD notary at the same time!\n"); StartShutdown(); } - name = GetArg("-ac_name",""); + std::string name = GetArg("-ac_name",""); if ( argv0 != 0 ) { - len = (int32_t)strlen(argv0); - for (i=0; i matches suffix (%s) -> ac_name.(%s)\n",argv0,argv0suffix[i],argv0names[i]); @@ -1306,6 +1023,7 @@ void komodo_args(char *argv0) } } } + chainName = assetchain(name); KOMODO_STOPAT = GetArg("-stopat",0); MAX_REORG_LENGTH = GetArg("-maxreorg",MAX_REORG_LENGTH); WITNESS_CACHE_SIZE = MAX_REORG_LENGTH+10; @@ -1318,6 +1036,8 @@ void komodo_args(char *argv0) Split(GetArg("-ac_nk",""), sizeof(ASSETCHAINS_NK)/sizeof(*ASSETCHAINS_NK), ASSETCHAINS_NK, 0); // -ac_ccactivateht=evalcode,height,evalcode,height,evalcode,height.... + uint64_t ccEnablesHeight[512]; + memset(ccEnablesHeight, 0, sizeof(ccEnablesHeight)); Split(GetArg("-ac_ccactivateht",""), sizeof(ccEnablesHeight)/sizeof(*ccEnablesHeight), ccEnablesHeight, 0); // fill map with all eval codes and activation height of 0. for ( int i = 0; i < 256; i++ ) @@ -1345,11 +1065,13 @@ void komodo_args(char *argv0) } KOMODO_EARLYTXID = Parseuint256(GetArg("-earlytxid","0").c_str()); ASSETCHAINS_EARLYTXIDCONTRACT = GetArg("-ac_earlytxidcontract",0); - if ( name.c_str()[0] != 0 ) + + if ( !chainName.isKMD() ) { std::string selectedAlgo = GetArg("-ac_algo", std::string(ASSETCHAINS_ALGORITHMS[0])); - for ( int i = 0; i < ASSETCHAINS_NUMALGOS; i++ ) + uint32_t i; + for ( i = 0; i < ASSETCHAINS_NUMALGOS; i++ ) { if (std::string(ASSETCHAINS_ALGORITHMS[i]) == selectedAlgo) { @@ -1400,7 +1122,7 @@ void komodo_args(char *argv0) for ( int i = 0; i < ASSETCHAINS_MAX_ERAS; i++ ) { - if ( ASSETCHAINS_DECAY[i] == 100000000 && ASSETCHAINS_ENDSUBSIDY == 0 ) + if ( ASSETCHAINS_DECAY[i] == 100000000 && ASSETCHAINS_ENDSUBSIDY[i] == 0 ) { ASSETCHAINS_DECAY[i] = 0; printf("ERA%u: ASSETCHAINS_DECAY of 100000000 means linear and that needs ASSETCHAINS_ENDSUBSIDY\n", i); @@ -1429,31 +1151,15 @@ void komodo_args(char *argv0) ASSETCHAINS_SCRIPTPUB = GetArg("-ac_script",""); ASSETCHAINS_BEAMPORT = GetArg("-ac_beam",0); ASSETCHAINS_CODAPORT = GetArg("-ac_coda",0); - ASSETCHAINS_CBOPRET = GetArg("-ac_cbopret",0); ASSETCHAINS_CBMATURITY = GetArg("-ac_cbmaturity",0); ASSETCHAINS_ADAPTIVEPOW = GetArg("-ac_adaptivepow",0); - //fprintf(stderr,"ASSETCHAINS_CBOPRET.%llx\n",(long long)ASSETCHAINS_CBOPRET); - if ( ASSETCHAINS_CBOPRET != 0 ) - { - SplitStr(GetArg("-ac_prices",""), ASSETCHAINS_PRICES); - if ( ASSETCHAINS_PRICES.size() > 0 ) - ASSETCHAINS_CBOPRET |= 4; - SplitStr(GetArg("-ac_stocks",""), ASSETCHAINS_STOCKS); - if ( ASSETCHAINS_STOCKS.size() > 0 ) - ASSETCHAINS_CBOPRET |= 8; - for (i=0; i Mineropret; if ( hexstr.size() != 0 ) { Mineropret.resize(hexstr.size()/2); decode_hex(Mineropret.data(),hexstr.size()/2,(char *)hexstr.c_str()); - for (i=0; i 0 ) { - for (i=0; i<256; i++) + // disable all CCs + for (uint16_t i=0; i<256; i++) { ASSETCHAINS_CCDISABLES[i] = 1; SETBIT(disablebits,i); } - for (i=0; i 0 ) - { - for (i=first; i<=last; i++) - { - CLEARBIT(disablebits,i); - ASSETCHAINS_CCDISABLES[i] = 0; - } - }*/ } if ( ASSETCHAINS_BEAMPORT != 0 ) { @@ -1530,15 +1232,6 @@ void komodo_args(char *argv0) StartShutdown(); } } - else if ( ASSETCHAINS_SELFIMPORT == "PEGSCC") - { - Split(GetArg("-ac_pegsccparams",""), sizeof(ASSETCHAINS_PEGSCCPARAMS)/sizeof(*ASSETCHAINS_PEGSCCPARAMS), ASSETCHAINS_PEGSCCPARAMS, 0); - if (ASSETCHAINS_ENDSUBSIDY[0]!=1 || ASSETCHAINS_COMMISSION!=0) - { - fprintf(stderr,"when using import for pegsCC these must be set: -ac_end=1 -ac_perc=0\n"); - StartShutdown(); - } - } // else it can be gateway coin else if (!ASSETCHAINS_SELFIMPORT.empty() && (ASSETCHAINS_ENDSUBSIDY[0]!=1 || ASSETCHAINS_SUPPLY>0 || ASSETCHAINS_COMMISSION!=0)) { @@ -1607,8 +1300,36 @@ void komodo_args(char *argv0) printf("ASSETCHAINS_FOUNDERS needs an ASSETCHAINS_OVERRIDE_PUBKEY or ASSETCHAINS_SCRIPTPUB\n"); } } - if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1 || ASSETCHAINS_SELFIMPORT.size() > 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF|| ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LASTERA > 0 || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 || nonz > 0 || ASSETCHAINS_CCLIB.size() > 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 || ASSETCHAINS_NOTARY_PAY[0] != 0 || ASSETCHAINS_BLOCKTIME != 60 || ASSETCHAINS_CBOPRET != 0 || Mineropret.size() != 0 || (ASSETCHAINS_NK[0] != 0 && ASSETCHAINS_NK[1] != 0) || KOMODO_SNAPSHOT_INTERVAL != 0 || ASSETCHAINS_EARLYTXIDCONTRACT != 0 || ASSETCHAINS_CBMATURITY != 0 || ASSETCHAINS_ADAPTIVEPOW != 0 ) - { + if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 + || ASSETCHAINS_REWARD[0] != 0 + || ASSETCHAINS_HALVING[0] != 0 + || ASSETCHAINS_DECAY[0] != 0 + || ASSETCHAINS_COMMISSION != 0 + || ASSETCHAINS_PUBLIC != 0 + || ASSETCHAINS_PRIVATE != 0 + || ASSETCHAINS_TXPOW != 0 + || ASSETCHAINS_FOUNDERS != 0 + || ASSETCHAINS_SCRIPTPUB.size() > 1 + || ASSETCHAINS_SELFIMPORT.size() > 0 + || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 + || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF + || ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH + || ASSETCHAINS_LASTERA > 0 + || ASSETCHAINS_BEAMPORT != 0 + || ASSETCHAINS_CODAPORT != 0 + || nonz > 0 + || ASSETCHAINS_CCLIB.size() > 0 + || ASSETCHAINS_FOUNDERS_REWARD != 0 + || ASSETCHAINS_NOTARY_PAY[0] != 0 + || ASSETCHAINS_BLOCKTIME != 60 + || Mineropret.size() != 0 + || (ASSETCHAINS_NK[0] != 0 && ASSETCHAINS_NK[1] != 0) + || KOMODO_SNAPSHOT_INTERVAL != 0 + || ASSETCHAINS_EARLYTXIDCONTRACT != 0 + || ASSETCHAINS_CBMATURITY != 0 + || ASSETCHAINS_ADAPTIVEPOW != 0 ) + { + uint8_t extrabuf[32756]; fprintf(stderr,"perc %.4f%% ac_pub=[%02x%02x%02x...] acsize.%d\n",dstr(ASSETCHAINS_COMMISSION)*100,ASSETCHAINS_OVERRIDE_PUBKEY33[0],ASSETCHAINS_OVERRIDE_PUBKEY33[1],ASSETCHAINS_OVERRIDE_PUBKEY33[2],(int32_t)ASSETCHAINS_SCRIPTPUB.size()); extraptr = extrabuf; memcpy(extraptr,ASSETCHAINS_OVERRIDE_PUBKEY33,33), extralen = 33; @@ -1651,7 +1372,7 @@ void komodo_args(char *argv0) extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_ALGO),(void *)&ASSETCHAINS_ALGO); } - val = ASSETCHAINS_COMMISSION | (((int64_t)ASSETCHAINS_STAKED & 0xff) << 32) | (((uint64_t)ASSETCHAINS_CC & 0xffff) << 40) | ((ASSETCHAINS_PUBLIC != 0) << 7) | ((ASSETCHAINS_PRIVATE != 0) << 6) | ASSETCHAINS_TXPOW; + uint64_t val = ASSETCHAINS_COMMISSION | (((int64_t)ASSETCHAINS_STAKED & 0xff) << 32) | (((uint64_t)ASSETCHAINS_CC & 0xffff) << 40) | ((ASSETCHAINS_PUBLIC != 0) << 7) | ((ASSETCHAINS_PRIVATE != 0) << 6) | ASSETCHAINS_TXPOW; extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(val),(void *)&val); if ( ASSETCHAINS_FOUNDERS != 0 ) @@ -1670,13 +1391,12 @@ void komodo_args(char *argv0) { decode_hex(&extraptr[extralen],ASSETCHAINS_SCRIPTPUB.size()/2,(char *)ASSETCHAINS_SCRIPTPUB.c_str()); extralen += ASSETCHAINS_SCRIPTPUB.size()/2; - //extralen += iguana_rwnum(1,&extraptr[extralen],(int32_t)ASSETCHAINS_SCRIPTPUB.size(),(void *)ASSETCHAINS_SCRIPTPUB.c_str()); fprintf(stderr,"append ac_script %s\n",ASSETCHAINS_SCRIPTPUB.c_str()); } if ( ASSETCHAINS_SELFIMPORT.size() > 0 ) { memcpy(&extraptr[extralen],(char *)ASSETCHAINS_SELFIMPORT.c_str(),ASSETCHAINS_SELFIMPORT.size()); - for (i=0; i 1 ) { - for (i=0; i 0 ) - ASSETCHAINS_SEED = 1; - - strncpy(ASSETCHAINS_SYMBOL,name.c_str(),sizeof(ASSETCHAINS_SYMBOL)-1); - - /* VRSC chain is incompatible with Komodo daemon */ - assert(strcmp(ASSETCHAINS_SYMBOL, "VRSC") != 0); + //addn = GetArg("-seednode",""); + //if ( strlen(addn.c_str()) > 0 ) + // ASSETCHAINS_SEED = 1; MAX_MONEY = komodo_max_money(); - - if ( (baseid = komodo_baseid(ASSETCHAINS_SYMBOL)) >= 0 && baseid < 32 ) + int32_t baseid; + if ( (baseid = komodo_baseid(chainName.symbol().c_str())) >= 0 && baseid < 32 ) { - //komodo_maxallowed(baseid); - printf("baseid.%d MAX_MONEY.%s %.8f\n",baseid,ASSETCHAINS_SYMBOL,(double)MAX_MONEY/SATOSHIDEN); + printf("baseid.%d MAX_MONEY.%s %.8f\n",baseid,chainName.symbol().c_str(),(double)MAX_MONEY/SATOSHIDEN); } if ( ASSETCHAINS_CC >= KOMODO_FIRSTFUNGIBLEID && MAX_MONEY < 1000000LL*SATOSHIDEN ) @@ -1775,14 +1464,16 @@ void komodo_args(char *argv0) if ( KOMODO_BIT63SET(MAX_MONEY) != 0 ) MAX_MONEY = KOMODO_MAXNVALUE; fprintf(stderr,"MAX_MONEY %llu %.8f\n",(long long)MAX_MONEY,(double)MAX_MONEY/SATOSHIDEN); - //printf("baseid.%d MAX_MONEY.%s %.8f\n",baseid,ASSETCHAINS_SYMBOL,(double)MAX_MONEY/SATOSHIDEN); - uint16_t tmpport = komodo_port(ASSETCHAINS_SYMBOL,ASSETCHAINS_SUPPLY,&ASSETCHAINS_MAGIC,extraptr,extralen); + uint16_t tmpport = komodo_port(chainName.symbol().c_str(),ASSETCHAINS_SUPPLY,&ASSETCHAINS_MAGIC,extraptr,extralen); if ( GetArg("-port",0) != 0 ) { ASSETCHAINS_P2PPORT = GetArg("-port",0); fprintf(stderr,"set p2pport.%u\n",ASSETCHAINS_P2PPORT); - } else ASSETCHAINS_P2PPORT = tmpport; + } + else + ASSETCHAINS_P2PPORT = tmpport; + char* dirname = nullptr; while ( (dirname= (char *)GetDataDir(false).string().c_str()) == 0 || dirname[0] == 0 ) { fprintf(stderr,"waiting for datadir (%s)\n",dirname); @@ -1792,49 +1483,47 @@ void komodo_args(char *argv0) boost::this_thread::sleep(boost::posix_time::milliseconds(3000)); #endif } - //fprintf(stderr,"Got datadir.(%s)\n",dirname); - if ( ASSETCHAINS_SYMBOL[0] != 0 ) + if ( !chainName.isKMD() ) { - int32_t komodo_baseid(char *origbase); - extern int COINBASE_MATURITY; - if ( strcmp(ASSETCHAINS_SYMBOL,"KMD") == 0 ) + if ( chainName.isSymbol("KMD") ) { - fprintf(stderr,"cant have assetchain named KMD\n"); + fprintf(stderr,"can't have assetchain named KMD\n"); StartShutdown(); } - if ( (port= komodo_userpass(ASSETCHAINS_USERPASS,ASSETCHAINS_SYMBOL)) != 0 ) + uint16_t port; + if ( (port= komodo_userpass(ASSETCHAINS_USERPASS,chainName.symbol().c_str())) != 0 ) ASSETCHAINS_RPCPORT = port; - else komodo_configfile(ASSETCHAINS_SYMBOL,ASSETCHAINS_P2PPORT + 1); + else komodo_configfile(chainName.symbol().c_str(),ASSETCHAINS_P2PPORT + 1); if (ASSETCHAINS_CBMATURITY != 0) - COINBASE_MATURITY = ASSETCHAINS_CBMATURITY; - else if (ASSETCHAINS_LASTERA == 0 || is_STAKED(ASSETCHAINS_SYMBOL) != 0) - COINBASE_MATURITY = 1; - if (COINBASE_MATURITY < 1) + Params().SetCoinbaseMaturity(ASSETCHAINS_CBMATURITY); + else if (ASSETCHAINS_LASTERA == 0 || is_STAKED(chainName.symbol()) != 0) + Params().SetCoinbaseMaturity(1); + if (Params().CoinbaseMaturity() < 1) { fprintf(stderr,"ac_cbmaturity must be >0, shutting down\n"); StartShutdown(); } - //fprintf(stderr,"ASSETCHAINS_RPCPORT (%s) %u\n",ASSETCHAINS_SYMBOL,ASSETCHAINS_RPCPORT); } if ( ASSETCHAINS_RPCPORT == 0 ) ASSETCHAINS_RPCPORT = ASSETCHAINS_P2PPORT + 1; - //ASSETCHAINS_NOTARIES = GetArg("-ac_notaries",""); - //komodo_assetchain_pubkeys((char *)ASSETCHAINS_NOTARIES.c_str()); + uint8_t magic[4]; iguana_rwnum(1,magic,sizeof(ASSETCHAINS_MAGIC),(void *)&ASSETCHAINS_MAGIC); + char magicstr[9]; for (i=0; i<4; i++) sprintf(&magicstr[i<<1],"%02x",magic[i]); magicstr[8] = 0; #ifndef FROM_CLI - sprintf(fname,"%s_7776",ASSETCHAINS_SYMBOL); + char fname[512]; + sprintf(fname,"%s_7776",chainName.symbol().c_str()); if ( (fp= fopen(fname,"wb")) != 0 ) { int8_t notarypay = 0; if ( ASSETCHAINS_NOTARY_PAY[0] != 0 ) notarypay = 1; + char *iguanafmtstr = (char *)"curl --url \"http://127.0.0.1:7776\" --data \"{\\\"conf\\\":\\\"%s.conf\\\",\\\"path\\\":\\\"${HOME#\"/\"}/.komodo/%s\\\",\\\"unitval\\\":\\\"20\\\",\\\"zcash\\\":1,\\\"RELAY\\\":-1,\\\"VALIDATE\\\":0,\\\"prefetchlag\\\":-1,\\\"poll\\\":100,\\\"active\\\":1,\\\"agent\\\":\\\"iguana\\\",\\\"method\\\":\\\"addcoin\\\",\\\"startpend\\\":4,\\\"endpend\\\":4,\\\"services\\\":129,\\\"maxpeers\\\":8,\\\"newcoin\\\":\\\"%s\\\",\\\"name\\\":\\\"%s\\\",\\\"hasheaders\\\":1,\\\"useaddmultisig\\\":0,\\\"netmagic\\\":\\\"%s\\\",\\\"p2p\\\":%u,\\\"rpc\\\":%u,\\\"pubval\\\":60,\\\"p2shval\\\":85,\\\"wifval\\\":188,\\\"txfee_satoshis\\\":\\\"10000\\\",\\\"isPoS\\\":0,\\\"minoutput\\\":10000,\\\"minconfirms\\\":2,\\\"genesishash\\\":\\\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\\\",\\\"protover\\\":170002,\\\"genesisblock\\\":\\\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\\\",\\\"debug\\\":0,\\\"seedipaddr\\\":\\\"%s\\\",\\\"sapling\\\":1,\\\"notarypay\\\":%i}\""; fprintf(fp,iguanafmtstr,name.c_str(),name.c_str(),name.c_str(),name.c_str(),magicstr,ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,"78.47.196.146",notarypay); fclose(fp); - //printf("created (%s)\n",fname); } else printf("error creating (%s)\n",fname); #endif if ( ASSETCHAINS_CC < 2 ) @@ -1853,48 +1542,15 @@ void komodo_args(char *argv0) } else { - char fname[512],username[512],password[4096]; int32_t iter; FILE *fp; - ASSETCHAINS_P2PPORT = 7770; - ASSETCHAINS_RPCPORT = 7771; - for (iter=0; iter<2; iter++) - { - strcpy(fname,GetDataDir().string().c_str()); -#ifdef _WIN32 - while ( fname[strlen(fname)-1] != '\\' ) - fname[strlen(fname)-1] = 0; - if ( iter == 0 ) - strcat(fname,"Komodo\\komodo.conf"); - else strcat(fname,ntz_dest_path.c_str()); -#else - while ( fname[strlen(fname)-1] != '/' ) - fname[strlen(fname)-1] = 0; -#ifdef __APPLE__ - if ( iter == 0 ) - strcat(fname,"Komodo/Komodo.conf"); - else strcat(fname,ntz_dest_path.c_str()); -#else - if ( iter == 0 ) - strcat(fname,".komodo/komodo.conf"); - else strcat(fname,ntz_dest_path.c_str()); -#endif -#endif - if ( (fp= fopen(fname,"rb")) != 0 ) - { - dest_rpc_port = _komodo_userpass(username,password,fp); - DEST_PORT = iter == 1 ? dest_rpc_port : 0; - sprintf(iter == 0 ? KMDUSERPASS : BTCUSERPASS,"%s:%s",username,password); - fclose(fp); - } else printf("couldnt open.(%s) will not validate dest notarizations\n",fname); - if ( !IS_KOMODO_NOTARY ) - break; - } + // -ac_name not passed, we are on the KMD chain + set_kmd_user_password_port(ntz_dest_path); } int32_t dpowconfs = KOMODO_DPOWCONFS; - if ( ASSETCHAINS_SYMBOL[0] != 0 ) + if ( !chainName.isKMD() ) { BITCOIND_RPCPORT = GetArg("-rpcport", ASSETCHAINS_RPCPORT); - //fprintf(stderr,"(%s) port.%u chain params initialized\n",ASSETCHAINS_SYMBOL,BITCOIND_RPCPORT); - if ( strcmp("PIRATE",ASSETCHAINS_SYMBOL) == 0 && ASSETCHAINS_HALVING[0] == 77777 ) + //fprintf(stderr,"(%s) port.%u chain params initialized\n",chainName.symbol().c_str(),BITCOIND_RPCPORT); + if ( chainName.isSymbol("PIRATE") && ASSETCHAINS_HALVING[0] == 77777 ) { ASSETCHAINS_HALVING[0] *= 5; fprintf(stderr,"PIRATE halving changed to %d %.1f days ASSETCHAINS_LASTERA.%llu\n",(int32_t)ASSETCHAINS_HALVING[0],(double)ASSETCHAINS_HALVING[0]/1440,(long long)ASSETCHAINS_LASTERA); @@ -1905,19 +1561,19 @@ void komodo_args(char *argv0) StartShutdown(); } // Set cc enables for all existing ac_cc chains here. - if ( strcmp("AXO",ASSETCHAINS_SYMBOL) == 0 ) + if ( chainName.isSymbol("AXO") ) { // No CCs used on this chain yet. CCDISABLEALL; } - if ( strcmp("CCL",ASSETCHAINS_SYMBOL) == 0 ) + if ( chainName.isSymbol("CCL") ) { // No CCs used on this chain yet. CCDISABLEALL; CCENABLE(EVAL_TOKENS); CCENABLE(EVAL_HEIR); } - if ( strcmp("COQUI",ASSETCHAINS_SYMBOL) == 0 ) + if ( chainName.isSymbol("COQUI") ) { CCDISABLEALL; CCENABLE(EVAL_DICE); @@ -1926,101 +1582,132 @@ void komodo_args(char *argv0) CCENABLE(EVAL_ASSETS); CCENABLE(EVAL_TOKENS); } - if ( strcmp("DION",ASSETCHAINS_SYMBOL) == 0 ) + if ( chainName.isSymbol("DION") ) { // No CCs used on this chain yet. CCDISABLEALL; } - if ( strcmp("EQL",ASSETCHAINS_SYMBOL) == 0 ) + if ( chainName.isSymbol("EQL") ) { // No CCs used on this chain yet. CCDISABLEALL; } - if ( strcmp("ILN",ASSETCHAINS_SYMBOL) == 0 ) + if ( chainName.isSymbol("ILN") ) { // No CCs used on this chain yet. CCDISABLEALL; } - if ( strcmp("OUR",ASSETCHAINS_SYMBOL) == 0 ) + if ( chainName.isSymbol("OUR") ) { // No CCs used on this chain yet. CCDISABLEALL; } - if ( strcmp("ZEXO",ASSETCHAINS_SYMBOL) == 0 ) + if ( chainName.isSymbol("ZEXO") ) { // No CCs used on this chain yet. CCDISABLEALL; } - if ( strcmp("SEC",ASSETCHAINS_SYMBOL) == 0 ) + if ( chainName.isSymbol("SEC") ) { CCDISABLEALL; CCENABLE(EVAL_ASSETS); CCENABLE(EVAL_TOKENS); CCENABLE(EVAL_ORACLES); } - if ( strcmp("KMDICE",ASSETCHAINS_SYMBOL) == 0 ) + if ( chainName.isSymbol("KMDICE") ) { CCDISABLEALL; CCENABLE(EVAL_FAUCET); CCENABLE(EVAL_DICE); CCENABLE(EVAL_ORACLES); } - } else BITCOIND_RPCPORT = GetArg("-rpcport", BaseParams().RPCPort()); + } + else + BITCOIND_RPCPORT = GetArg("-rpcport", BaseParams().RPCPort()); KOMODO_DPOWCONFS = GetArg("-dpowconfs",dpowconfs); - if ( ASSETCHAINS_SYMBOL[0] == 0 || strcmp(ASSETCHAINS_SYMBOL,"SUPERNET") == 0 || strcmp(ASSETCHAINS_SYMBOL,"DEX") == 0 || strcmp(ASSETCHAINS_SYMBOL,"COQUI") == 0 || strcmp(ASSETCHAINS_SYMBOL,"PIRATE") == 0 || strcmp(ASSETCHAINS_SYMBOL,"KMDICE") == 0 ) + if ( chainName.isKMD() + || chainName.isSymbol("SUPERNET") + || chainName.isSymbol("DEX") + || chainName.isSymbol("COQUI") + || chainName.isSymbol("PIRATE") + || chainName.isSymbol("KMDICE") ) KOMODO_EXTRASATOSHI = 1; } -void komodo_nameset(char *symbol,char *dest,char *source) +/*** + * @brief sets 'symbol' to the current chain name, 'dest' to either KMD or BTC + * according to the 'source' which must be either the current asset chain name or empty (if KMD). + * @param[out] symbol set to the current asset chain name or "KMD" + * @param[out] dest set to the notarisation chain name (KMD or BTC) + * @param[in] source current asset chain name or empty string for KMD + * This function should be deprecated IMO + */ +void komodo_nameset(char *symbol,char *dest,const char *source) { - if ( source[0] == 0 ) + if ( source[0] == 0 ) // if not an asset chain { - strcpy(symbol,(char *)"KMD"); - strcpy(dest,(char *)"BTC"); + strcpy(symbol,(char *)"KMD"); // this chain is KMD + strcpy(dest,(char *)"BTC"); // dest is BTC } else { - strcpy(symbol,source); - strcpy(dest,(char *)"KMD"); + strcpy(symbol,source); // this chain an asset chain + strcpy(dest,(char *)"KMD"); // dest is KMD } } -struct komodo_state *komodo_stateptrget(char *base) +/**** + * @brief get the right komodo_state + * @param[in] base what to search for (nullptr == "KMD") + * @returns the correct komodo_state object + */ +komodo_state *komodo_stateptrget(char *base) { - int32_t baseid; + // "KMD" case if ( base == 0 || base[0] == 0 || strcmp(base,(char *)"KMD") == 0 ) - return(&KOMODO_STATES[33]); - else if ( (baseid= komodo_baseid(base)) >= 0 ) - return(&KOMODO_STATES[baseid+1]); - else return(&KOMODO_STATES[0]); + return &KOMODO_STATES[1]; + + // evidently this asset chain + return &KOMODO_STATES[0]; } -struct komodo_state *komodo_stateptr(char *symbol,char *dest) +/**** + * @brief get the symbol and dest based on this chain's ASSETCHAINS_SYMBOL + * @param[out] symbol this chain ("KMD" if ASSETCHAINS_SYMBOL is nullptr) + * @param[out] dest the destination chain ("BTC" in the case of KMD, otherwise "KMD") + * @returns the komodo_state object for symbol + */ +komodo_state *komodo_stateptr(char *symbol,char *dest) { int32_t baseid; - komodo_nameset(symbol,dest,ASSETCHAINS_SYMBOL); + komodo_nameset(symbol,dest,chainName.symbol().c_str()); return(komodo_stateptrget(symbol)); } +/*** + * @brief prefetch file contents, leave next read position where it started + * @param fp the file to read + */ void komodo_prefetch(FILE *fp) { - long fsize,fpos; int32_t incr = 16*1024*1024; - fpos = ftell(fp); + // I am not sure why we do this, perhaps looking for disk errors or + // disk caching? - JMJ + int32_t incr = 16*1024*1024; + long fpos = ftell(fp); // store the current position fseek(fp,0,SEEK_END); - fsize = ftell(fp); - if ( fsize > incr ) + if ( ftell(fp) > incr ) // if the file is greater than 16MB { char *ignore = (char *)malloc(incr); if ( ignore != 0 ) { - rewind(fp); - while ( fread(ignore,1,incr,fp) == incr ) // prefetch + rewind(fp); // go back to the beginning + while ( fread(ignore,1,incr,fp) == incr ) // prefetch in 16MB blocks fprintf(stderr,"."); free(ignore); } } - fseek(fp,fpos,SEEK_SET); + fseek(fp,fpos,SEEK_SET); // go to where we were when this function was called } // check if block timestamp is more than S5 activation time diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 6ebae40852e..e4005be0fcf 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -14,6 +14,7 @@ ******************************************************************************/ #pragma once #include "komodo_defs.h" +#include "komodo_structs.h" #include "hex.h" #include "key_io.h" #include "cc/CCinclude.h" @@ -25,23 +26,13 @@ #include #endif -#define SATOSHIDEN ((uint64_t)100000000L) -#define dstr(x) ((double)(x) / SATOSHIDEN) +//#define SATOSHIDEN ((uint64_t)100000000L) +//#define dstr(x) ((double)(x) / SATOSHIDEN) #define portable_mutex_t pthread_mutex_t #define portable_mutex_init(ptr) pthread_mutex_init(ptr,NULL) #define portable_mutex_lock pthread_mutex_lock #define portable_mutex_unlock pthread_mutex_unlock -struct allocitem { uint32_t allocsize,type; }; -struct queueitem { struct queueitem *next,*prev; uint32_t allocsize,type; }; - -typedef struct queue -{ - struct queueitem *list; - pthread_mutex_t mutex; - char name[64],initflag; -} queue_t; - #include "mini-gmp.h" #define CRYPTO777_PUBSECPSTR "020e46e79a2a8d12b9b5d12c7a91adb4e454edfae43c0a0cb805427d2ac7613fd9" @@ -50,242 +41,12 @@ typedef struct queue #define KOMODO_PUBTYPE 60 -struct sha256_vstate { uint64_t length; uint32_t state[8],curlen; uint8_t buf[64]; }; struct rmd160_vstate { uint64_t length; uint8_t buf[64]; uint32_t curlen, state[5]; }; -// following is ported from libtom - -#define STORE32L(x, y) \ -{ (y)[3] = (uint8_t)(((x)>>24)&255); (y)[2] = (uint8_t)(((x)>>16)&255); \ -(y)[1] = (uint8_t)(((x)>>8)&255); (y)[0] = (uint8_t)((x)&255); } - -#define LOAD32L(x, y) \ -{ x = (uint32_t)(((uint64_t)((y)[3] & 255)<<24) | \ -((uint32_t)((y)[2] & 255)<<16) | \ -((uint32_t)((y)[1] & 255)<<8) | \ -((uint32_t)((y)[0] & 255))); } - -#define STORE64L(x, y) \ -{ (y)[7] = (uint8_t)(((x)>>56)&255); (y)[6] = (uint8_t)(((x)>>48)&255); \ -(y)[5] = (uint8_t)(((x)>>40)&255); (y)[4] = (uint8_t)(((x)>>32)&255); \ -(y)[3] = (uint8_t)(((x)>>24)&255); (y)[2] = (uint8_t)(((x)>>16)&255); \ -(y)[1] = (uint8_t)(((x)>>8)&255); (y)[0] = (uint8_t)((x)&255); } - -#define LOAD64L(x, y) \ -{ x = (((uint64_t)((y)[7] & 255))<<56)|(((uint64_t)((y)[6] & 255))<<48)| \ -(((uint64_t)((y)[5] & 255))<<40)|(((uint64_t)((y)[4] & 255))<<32)| \ -(((uint64_t)((y)[3] & 255))<<24)|(((uint64_t)((y)[2] & 255))<<16)| \ -(((uint64_t)((y)[1] & 255))<<8)|(((uint64_t)((y)[0] & 255))); } - -#define STORE32H(x, y) \ -{ (y)[0] = (uint8_t)(((x)>>24)&255); (y)[1] = (uint8_t)(((x)>>16)&255); \ -(y)[2] = (uint8_t)(((x)>>8)&255); (y)[3] = (uint8_t)((x)&255); } - -#define LOAD32H(x, y) \ -{ x = (uint32_t)(((uint64_t)((y)[0] & 255)<<24) | \ -((uint32_t)((y)[1] & 255)<<16) | \ -((uint32_t)((y)[2] & 255)<<8) | \ -((uint32_t)((y)[3] & 255))); } - -#define STORE64H(x, y) \ -{ (y)[0] = (uint8_t)(((x)>>56)&255); (y)[1] = (uint8_t)(((x)>>48)&255); \ -(y)[2] = (uint8_t)(((x)>>40)&255); (y)[3] = (uint8_t)(((x)>>32)&255); \ -(y)[4] = (uint8_t)(((x)>>24)&255); (y)[5] = (uint8_t)(((x)>>16)&255); \ -(y)[6] = (uint8_t)(((x)>>8)&255); (y)[7] = (uint8_t)((x)&255); } - -#define LOAD64H(x, y) \ -{ x = (((uint64_t)((y)[0] & 255))<<56)|(((uint64_t)((y)[1] & 255))<<48) | \ -(((uint64_t)((y)[2] & 255))<<40)|(((uint64_t)((y)[3] & 255))<<32) | \ -(((uint64_t)((y)[4] & 255))<<24)|(((uint64_t)((y)[5] & 255))<<16) | \ -(((uint64_t)((y)[6] & 255))<<8)|(((uint64_t)((y)[7] & 255))); } - -// Various logical functions -#define RORc(x, y) ( ((((uint32_t)(x)&0xFFFFFFFFUL)>>(uint32_t)((y)&31)) | ((uint32_t)(x)<<(uint32_t)(32-((y)&31)))) & 0xFFFFFFFFUL) -#define Ch(x,y,z) (z ^ (x & (y ^ z))) -#define Maj(x,y,z) (((x | y) & z) | (x & y)) -#define S(x, n) RORc((x),(n)) -#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) -#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) -#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) -#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) -#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) -#define MIN(x, y) ( ((x)<(y))?(x):(y) ) - -static inline int32_t sha256_vcompress(struct sha256_vstate * md,uint8_t *buf) -{ - uint32_t S[8],W[64],t0,t1,i; - for (i=0; i<8; i++) // copy state into S - S[i] = md->state[i]; - for (i=0; i<16; i++) // copy the state into 512-bits into W[0..15] - LOAD32H(W[i],buf + (4*i)); - for (i=16; i<64; i++) // fill W[16..63] - W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; - -#define RND(a,b,c,d,e,f,g,h,i,ki) \ -t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \ -t1 = Sigma0(a) + Maj(a, b, c); \ -d += t0; \ -h = t0 + t1; - - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2); -#undef RND - for (i=0; i<8; i++) // feedback - md->state[i] = md->state[i] + S[i]; - return(0); -} - -#undef RORc -#undef Ch -#undef Maj -#undef S -#undef R -#undef Sigma0 -#undef Sigma1 -#undef Gamma0 -#undef Gamma1 - -static inline void sha256_vinit(struct sha256_vstate * md) -{ - md->curlen = 0; - md->length = 0; - md->state[0] = 0x6A09E667UL; - md->state[1] = 0xBB67AE85UL; - md->state[2] = 0x3C6EF372UL; - md->state[3] = 0xA54FF53AUL; - md->state[4] = 0x510E527FUL; - md->state[5] = 0x9B05688CUL; - md->state[6] = 0x1F83D9ABUL; - md->state[7] = 0x5BE0CD19UL; -} - -static inline int32_t sha256_vprocess(struct sha256_vstate *md,const uint8_t *in,uint64_t inlen) -{ - uint64_t n; int32_t err; - if ( md->curlen > sizeof(md->buf) ) - return(-1); - while ( inlen > 0 ) - { - if ( md->curlen == 0 && inlen >= 64 ) - { - if ( (err= sha256_vcompress(md,(uint8_t *)in)) != 0 ) - return(err); - md->length += 64 * 8, in += 64, inlen -= 64; - } - else - { - n = MIN(inlen,64 - md->curlen); - memcpy(md->buf + md->curlen,in,(size_t)n); - md->curlen += n, in += n, inlen -= n; - if ( md->curlen == 64 ) - { - if ( (err= sha256_vcompress(md,md->buf)) != 0 ) - return(err); - md->length += 8*64; - md->curlen = 0; - } - } - } - return(0); -} - -static inline int32_t sha256_vdone(struct sha256_vstate *md,uint8_t *out) -{ - int32_t i; - if ( md->curlen >= sizeof(md->buf) ) - return(-1); - md->length += md->curlen * 8; // increase the length of the message - md->buf[md->curlen++] = (uint8_t)0x80; // append the '1' bit - // if len > 56 bytes we append zeros then compress. Then we can fall back to padding zeros and length encoding like normal. - if ( md->curlen > 56 ) - { - while ( md->curlen < 64 ) - md->buf[md->curlen++] = (uint8_t)0; - sha256_vcompress(md,md->buf); - md->curlen = 0; - } - while ( md->curlen < 56 ) // pad upto 56 bytes of zeroes - md->buf[md->curlen++] = (uint8_t)0; - STORE64H(md->length,md->buf+56); // store length - sha256_vcompress(md,md->buf); - for (i=0; i<8; i++) // copy output - STORE32H(md->state[i],out+(4*i)); - return(0); -} - void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len); bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen); -/** - Initialize the hash state - @param md The hash state you wish to initialize - @return 0 if successful - */ -int rmd160_vinit(struct rmd160_vstate * md); - /** Process a block of memory though the hash @param md The hash state @@ -295,26 +56,14 @@ int rmd160_vinit(struct rmd160_vstate * md); */ int rmd160_vprocess (struct rmd160_vstate * md, const unsigned char *in, unsigned long inlen); -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (20 bytes) - @return 0 if successful - */ -int rmd160_vdone(struct rmd160_vstate * md, unsigned char *out); - -void calc_rmd160(char deprecated[41],uint8_t buf[20],uint8_t *msg,int32_t len); - uint32_t calc_crc32(uint32_t crc,const void *buf,size_t size); void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen); -int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr); +int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],const char *coinaddr); char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len); -int32_t komodo_is_issuer(); - int32_t bitweight(uint64_t x); char *bits256_str(char hexstr[65],bits256 x); @@ -323,8 +72,6 @@ int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endian int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp); -int32_t komodo_scriptitemlen(int32_t *opretlenp,uint8_t *script); - int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen); // get a pseudo random number that is the same for each block individually at all times and different @@ -340,54 +87,37 @@ char *parse_conf_line(char *line,char *field); double OS_milliseconds(); -void lock_queue(queue_t *queue); - -void queue_enqueue(char *name,queue_t *queue,struct queueitem *item); - -struct queueitem *queue_dequeue(queue_t *queue); - -void *queue_delete(queue_t *queue,struct queueitem *copy,int32_t copysize); - -void *queue_free(queue_t *queue); - -void *queue_clone(queue_t *clone,queue_t *queue,int32_t size); - -int32_t queue_size(queue_t *queue); - -void iguana_initQ(queue_t *Q,char *name); - -uint16_t _komodo_userpass(char *username,char *password,FILE *fp); - -void komodo_statefname(char *fname,char *symbol,char *str); - -void komodo_configfile(char *symbol,uint16_t rpcport); - -uint16_t komodo_userpass(char *userpass,char *symbol); - -uint32_t komodo_assetmagic(char *symbol,uint64_t supply,uint8_t *extraptr,int32_t extralen); - -uint16_t komodo_assetport(uint32_t magic,int32_t extralen); - -uint16_t komodo_port(char *symbol,uint64_t supply,uint32_t *magicp,uint8_t *extraptr,int32_t extralen); +#define MAX_STATEFNAME 512 +void komodo_statefname(char *fname, const char *symbol, const char *str); int32_t komodo_whoami(char *pubkeystr,int32_t height,uint32_t timestamp); -uint64_t komodo_max_money(); - uint64_t komodo_ac_block_subsidy(int nHeight); -int8_t equihash_params_possible(uint64_t n, uint64_t k); - void komodo_args(char *argv0); -void komodo_nameset(char *symbol,char *dest,char *source); +/*** + * @brief given a source, calculate the symbol and dest + * @note if source == nullptr, the results will be KMD/BTC, otherwise source/KMD + * @param[out] symbol the symbol (i.e. "KMD") + * @param[out] dest the destination (i.e. "BTC") + * @param[in] source the source (i.e. "KMD") + */ +void komodo_nameset(char *symbol,char *dest,const char *source); -struct komodo_state *komodo_stateptrget(char *base); +/**** + * @brief get the right komodo_state + * @param[in] base what to search for (nullptr == "KMD") + * @returns the correct komodo_state object + */ +komodo_state *komodo_stateptrget(char *base); -struct komodo_state *komodo_stateptr(char *symbol,char *dest); +komodo_state *komodo_stateptr(char *symbol,char *dest); void komodo_prefetch(FILE *fp); // check if block timestamp is more than S5 activation time // this function is to activate the ExtractDestination fix bool komodo_is_vSolutionsFixActive(); + +void set_kmd_user_password_port(const std::string& ltc_config_filename); diff --git a/src/leveldb/Makefile b/src/leveldb/Makefile index 2bd2cadcdde..486802d5424 100644 --- a/src/leveldb/Makefile +++ b/src/leveldb/Makefile @@ -107,8 +107,8 @@ clean: -rm -rf ios-x86/* ios-arm/* $(LIBRARY): $(LIBOBJECTS) - rm -f $@ - $(AR) -rs $@ $(LIBOBJECTS) + @rm -f $@ + @$(AR) -rs $@ $(LIBOBJECTS) db_bench: db/db_bench.o $(LIBOBJECTS) $(TESTUTIL) $(CXX) $(LDFLAGS) db/db_bench.o $(LIBOBJECTS) $(TESTUTIL) -o $@ $(LIBS) @@ -189,8 +189,8 @@ write_batch_test: db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS) $(CXX) $(LDFLAGS) db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) $(MEMENVLIBRARY) : $(MEMENVOBJECTS) - rm -f $@ - $(AR) -rs $@ $(MEMENVOBJECTS) + @rm -f $@ + @$(AR) -rs $@ $(MEMENVOBJECTS) memenv_test : helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) $(CXX) $(LDFLAGS) helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) -o $@ $(LIBS) @@ -220,8 +220,8 @@ IOSARCH=-arch armv6 -arch armv7 -arch armv7s -arch arm64 else .cc.o: - $(CXX) $(CXXFLAGS) -c $< -o $@ + @$(CXX) $(CXXFLAGS) -c $< -o $@ .c.o: - $(CC) $(CFLAGS) -c $< -o $@ + @$(CC) $(CFLAGS) -c $< -o $@ endif diff --git a/src/main.cpp b/src/main.cpp index 59e5dc9f070..a3468c3d636 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers -// Copyright (c) 2015-2020 The Zcash developers -// Copyright (c) 2015-2020 The Komodo Platform developers +// Copyright (c) 2015-2022 The Zcash developers +// Copyright (c) 2015-2023 The Komodo Platform developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -51,6 +51,15 @@ #include "wallet/asyncrpcoperation_shieldcoinbase.h" #include "notaries_staked.h" #include "komodo_extern_globals.h" +#include "komodo_gateway.h" +#include "komodo.h" +#include "komodo_notary.h" +#include "key_io.h" +#include "komodo_utils.h" +#include "komodo_bitcoind.h" +#include "komodo_interest.h" +#include "rpc/net.h" +#include "cc/CCinclude.h" #include #include @@ -81,14 +90,7 @@ using namespace std; #define TMPFILE_START 100000000 CCriticalSection cs_main; -extern uint8_t NOTARY_PUBKEY33[33]; -extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN,KOMODO_INSYNC,KOMODO_CONNECTING,KOMODO_EXTRASATOSHI; int32_t KOMODO_NEWBLOCKS; -int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); -//void komodo_broadcast(CBlock *pblock,int32_t limit); -bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); -void komodo_setactivation(int32_t height); -void komodo_pricesupdate(int32_t height,CBlock *pblock); BlockMap mapBlockIndex; CChain chainActive; @@ -131,7 +133,7 @@ struct COrphanTx { }; map mapOrphanTransactions GUARDED_BY(cs_main);; map > mapOrphanTransactionsByPrev GUARDED_BY(cs_main);; -void EraseOrphansFor(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main); +void EraseOrphansFor(NodeId peer) REQUIRES(cs_main); /** * Returns true if there are nRequired or more blocks of minVersion or above @@ -235,7 +237,7 @@ namespace { * * Memory used: 1.7MB */ - boost::scoped_ptr recentRejects; + std::unique_ptr recentRejects; uint256 hashRecentRejectsChainTip; /** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */ @@ -337,11 +339,14 @@ namespace { int GetHeight() { - CBlockIndex *pindex; - if ( (pindex= chainActive.LastTip()) != 0 ) + CBlockIndex *pindex = nullptr; + { + LOCK(cs_main); + pindex = chainActive.Tip(); + } + if ( pindex != nullptr ) return pindex->nHeight; - else return(0); - /*return chainActive.Height();*/ + return 0; } void UpdatePreferredDownload(CNode* node, CNodeState* state) @@ -521,8 +526,6 @@ namespace { // Never fetch further than the best block we know the peer has, or more than BLOCK_DOWNLOAD_WINDOW + 1 beyond the last // linked block we have in common with this peer. The +1 is so we can detect stalling, namely if we would be able to // download that next block if the window were 1 larger. - if ( ASSETCHAINS_CBOPRET != 0 && IsInitialBlockDownload() == 0 ) - BLOCK_DOWNLOAD_WINDOW = 1; int nWindowEnd = state->pindexLastCommonBlock->nHeight + BLOCK_DOWNLOAD_WINDOW; int nMaxHeight = std::min(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1); NodeId waitingfor = -1; @@ -625,8 +628,8 @@ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& loc return chain.Genesis(); } -CCoinsViewCache *pcoinsTip = NULL; -CBlockTreeDB *pblocktree = NULL; +CCoinsViewCache *pcoinsTip = nullptr; +CBlockTreeDB *pblocktree = nullptr; // Komodo globals @@ -639,7 +642,7 @@ UniValue komodo_snapshot(int top) UniValue result(UniValue::VOBJ); if (fAddressIndex) { - if ( pblocktree != 0 ) { + if ( pblocktree != nullptr ) { result = pblocktree->Snapshot(top); } else { fprintf(stderr,"null pblocktree start with -addressindex=1\n"); @@ -652,7 +655,7 @@ UniValue komodo_snapshot(int top) bool komodo_snapshot2(std::map &addressAmounts) { - if ( fAddressIndex && pblocktree != 0 ) + if ( fAddressIndex && pblocktree != nullptr ) { return pblocktree->Snapshot2(addressAmounts, 0); } @@ -668,18 +671,18 @@ bool komodo_dailysnapshot(int32_t height) uint256 notarized_hash,notarized_desttxid; int32_t prevMoMheight,notarized_height,undo_height,extraoffset; // NOTE: To make this 100% safe under all sync conditions, it should be using a notarized notarization, from the DB. // Under heavy reorg attack, its possible `komodo_notarized_height` can return a height that can't be found on chain sync. - // However, the DB can reorg the last notarization. By using 2 deep, we know 100% that the previous notarization cannot be reorged by online nodes, - // and as such will always be notarizing the same height. May need to check heights on scan back to make sure they are confirmed in correct order. + // However, the DB can reorg the last notarization. By using 2 deep, we know 100% that the previous notarization cannot be + // reorged by online nodes, and as such will always be notarizing the same height. May need to check heights on scan back + // to make sure they are confirmed in correct order. if ( (extraoffset= height % KOMODO_SNAPSHOT_INTERVAL) != 0 ) { // we are on chain init, and need to scan all the way back to the correct height, other wise our node will have a diffrent snapshot to online nodes. // use the notarizationsDB to scan back from the consesnus height to get the offset we need. - std::string symbol; Notarisation nota; - symbol.assign(ASSETCHAINS_SYMBOL); - if ( ScanNotarisationsDB(height-extraoffset, symbol, 100, nota) == 0 ) + Notarisation nota; + if ( ScanNotarisationsDB(height-extraoffset, chainName.symbol(), 100, nota) == 0 ) undo_height = height-extraoffset-reorglimit; - else undo_height = nota.second.height; - //fprintf(stderr, "height.%i-extraoffset.%i = startscanfrom.%i to get undo_height.%i\n", height, extraoffset, height-extraoffset, undo_height); + else + undo_height = nota.second.height; } else { @@ -698,7 +701,6 @@ bool komodo_dailysnapshot(int32_t height) // undo blocks in reverse order for (int32_t n = height; n > undo_height; n--) { - //fprintf(stderr, "undoing block.%i\n",n); CBlockIndex *pindex; CBlock block; if ( (pindex= komodo_chainactive(n)) == 0 || komodo_blockload(block, pindex) != 0 ) return false; @@ -716,20 +718,17 @@ bool komodo_dailysnapshot(int32_t height) addressAmounts[CBitcoinAddress(vDest).ToString()] -= out.nValue; if ( addressAmounts[CBitcoinAddress(vDest).ToString()] < 1 ) addressAmounts.erase(CBitcoinAddress(vDest).ToString()); - //fprintf(stderr, "VOUT: address.%s remove_coins.%li\n",CBitcoinAddress(vDest).ToString().c_str(), out.nValue); } } // loop vins in reverse order, get prevout and return the sent balance. for (unsigned int j = tx.vin.size(); j-- > 0;) { uint256 blockhash; CTransaction txin; - if (tx.IsPegsImport() && j==0) continue; if ( !tx.IsCoinImport() && !tx.IsCoinBase() && myGetTransaction(tx.vin[j].prevout.hash,txin,blockhash) ) { int vout = tx.vin[j].prevout.n; if ( ExtractDestination(txin.vout[vout].scriptPubKey, vDest) ) { - //fprintf(stderr, "VIN: address.%s add_coins.%li\n",CBitcoinAddress(vDest).ToString().c_str(), txin.vout[vout].nValue); addressAmounts[CBitcoinAddress(vDest).ToString()] += txin.vout[vout].nValue; } } @@ -742,8 +741,6 @@ bool komodo_dailysnapshot(int32_t height) vAddressSnapshot.push_back(make_pair(element.second, DecodeDestination(element.first))); // sort the vector by amount, highest at top. std::sort(vAddressSnapshot.rbegin(), vAddressSnapshot.rend()); - //for (int j = 0; j < 50; j++) - // fprintf(stderr, "j.%i address.%s nValue.%li\n",j, CBitcoinAddress(vAddressSnapshot[j].second).ToString().c_str(), vAddressSnapshot[j].first ); // include only top 3999 address. if ( vAddressSnapshot.size() > 3999 ) vAddressSnapshot.resize(3999); lastSnapShotHeight = undo_height; @@ -756,7 +753,7 @@ bool komodo_dailysnapshot(int32_t height) // mapOrphanTransactions // -bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main) +bool AddOrphanTx(const CTransaction& tx, NodeId peer) REQUIRES(cs_main) { uint256 hash = tx.GetHash(); if (mapOrphanTransactions.count(hash)) @@ -786,7 +783,7 @@ bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(c return true; } -void static EraseOrphanTx(uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) +void static EraseOrphanTx(uint256 hash) REQUIRES(cs_main) { map::iterator it = mapOrphanTransactions.find(hash); if (it == mapOrphanTransactions.end()) @@ -820,7 +817,7 @@ void EraseOrphansFor(NodeId peer) } -unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) EXCLUSIVE_LOCKS_REQUIRED(cs_main) +unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) REQUIRES(cs_main) { unsigned int nEvicted = 0; while (mapOrphanTransactions.size() > nMaxOrphans) @@ -957,6 +954,13 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime) return true; } +/** + * Check if transaction is expired and can be included in a block with the + * specified height. Consensus critical. + * @param tx the transaction + * @param nBlockHeight the current block height + * @returns true if transaction is expired (mainly tx.expiryHeight > nBlockHeight) + */ bool IsExpiredTx(const CTransaction &tx, int nBlockHeight) { if (tx.nExpiryHeight == 0 || tx.IsCoinBase()) { @@ -1015,7 +1019,6 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs, for (unsigned int i = 0; i < tx.vin.size(); i++) { - if (tx.IsPegsImport() && i==0) continue; const CTxOut& prev = mapInputs.GetOutputFor(tx.vin[i]); vector > vSolutions; @@ -1093,7 +1096,6 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in unsigned int nSigOps = 0; for (unsigned int i = 0; i < tx.vin.size(); i++) { - if (tx.IsPegsImport() && i==0) continue; const CTxOut &prevout = inputs.GetOutputFor(tx.vin[i]); if (prevout.scriptPubKey.IsPayToScriptHash()) nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig); @@ -1141,11 +1143,6 @@ bool ContextualCheckCoinbaseTransaction(int32_t slowflag,const CBlock *block,CBl } return(false); } - else if ( slowflag != 0 && ASSETCHAINS_CBOPRET != 0 && validateprices != 0 && nHeight > 0 && tx.vout.size() > 0 ) - { - if ( komodo_opretvalidate(block,previndex,nHeight,tx.vout[tx.vout.size()-1].scriptPubKey) < 0 ) - return(false); - } return(true); } @@ -1256,7 +1253,6 @@ bool ContextualCheckTransaction(int32_t slowflag,const CBlock *block, CBlockInde // Rules that apply before Sapling: if (!saplingActive) { // Size limits - //BOOST_STATIC_ASSERT(MAX_BLOCK_SIZE(chainActive.LastTip()->nHeight+1) > MAX_TX_SIZE_BEFORE_SAPLING); // sanity if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_TX_SIZE_BEFORE_SAPLING) return state.DoS(100, error("ContextualCheckTransaction(): size limits failed"), REJECT_INVALID, "bad-txns-oversize"); @@ -1362,28 +1358,32 @@ bool ContextualCheckTransaction(int32_t slowflag,const CBlock *block, CBlockInde bool CheckTransaction(uint32_t tiptime,const CTransaction& tx, CValidationState &state, libzcash::ProofVerifier& verifier,int32_t txIndex, int32_t numTxs) { - static uint256 array[64]; static int32_t numbanned,indallvouts; int32_t j,k,n; uint256 merkleroot; - if ( *(int32_t *)&array[0] == 0 ) - numbanned = komodo_bannedset(&indallvouts,array,(int32_t)(sizeof(array)/sizeof(*array))); - n = tx.vin.size(); - if ( ASSETCHAINS_SYMBOL[0] == 0 ) + if (chainName.isKMD()) { - for (j=0; j= indallvouts) ) + if ( tx.vin[j].prevout.hash == array[k] && komodo_checkvout(tx.vin[j].prevout.n,k,indallvouts) ) { + // hash matches and the vout.n matches static uint32_t counter; if ( counter++ < 100 ) - printf("MEMPOOL: banned tx.%d being used at ht.%d vout.%d\n",k,(int32_t)chainActive.Tip()->nHeight,j); - return(false); + printf("MEMPOOL: banned tx.%d being used at ht.%d vout.%ld\n",k,(int32_t)chainActive.Tip()->nHeight,j); + return false; } } } } - + uint256 merkleroot; if ( ASSETCHAINS_STAKED != 0 && komodo_newStakerActive(0, tiptime) != 0 && tx.vout.size() == 2 && DecodeStakingOpRet(tx.vout[1].scriptPubKey, merkleroot) != 0 ) { if ( numTxs == 0 || txIndex != numTxs-1 ) @@ -1412,28 +1412,6 @@ bool CheckTransaction(uint32_t tiptime,const CTransaction& tx, CValidationState } } -// ARRR notary exception -int32_t komodo_isnotaryvout(char *coinaddr,uint32_t tiptime) // from ac_private chains only -{ - int32_t season = getacseason(tiptime); - if ( NOTARY_ADDRESSES[season-1][0][0] == 0 ) - { - uint8_t pubkeys[64][33]; - komodo_notaries(pubkeys,0,tiptime); - } - if ( strcmp(coinaddr,CRYPTO777_KMDADDR) == 0 ) - return(1); - for (int32_t i = 0; i < NUM_KMD_NOTARIES; i++) - { - if ( strcmp(coinaddr,NOTARY_ADDRESSES[season-1][i]) == 0 ) - { - //fprintf(stderr, "coinaddr.%s notaryaddress[%i].%s\n",coinaddr,i,NOTARY_ADDRESSES[season-1][i]); - return(1); - } - } - return(0); -} - int32_t komodo_acpublic(uint32_t tiptime); bool CheckTransactionWithoutProofVerification(uint32_t tiptime,const CTransaction& tx, CValidationState &state) @@ -1495,7 +1473,6 @@ bool CheckTransactionWithoutProofVerification(uint32_t tiptime,const CTransactio REJECT_INVALID, "bad-txns-vout-empty"); // Size limits - //BOOST_STATIC_ASSERT(MAX_BLOCK_SIZE(chainActive.LastTip()->nHeight+1) >= MAX_TX_SIZE_AFTER_SAPLING); // sanity BOOST_STATIC_ASSERT(MAX_TX_SIZE_AFTER_SAPLING > MAX_TX_SIZE_BEFORE_SAPLING); // sanity if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_TX_SIZE_AFTER_SAPLING) return state.DoS(100, error("CheckTransaction(): size limits failed"), @@ -1780,18 +1757,29 @@ CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowF return nMinFee; } - +/***** + * @brief Try to add transaction to memory pool + * @param pool + * @param state + * @param tx + * @param fLimitFree + * @param pfMissingInputs + * @param fRejectAbsurdFee + * @param dosLevel + * @returns true on success + */ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,bool* pfMissingInputs, bool fRejectAbsurdFee, int dosLevel) { AssertLockHeld(cs_main); - if (pfMissingInputs) + if (pfMissingInputs != nullptr) *pfMissingInputs = false; uint32_t tiptime; - int flag=0,nextBlockHeight = chainActive.Height() + 1; + int nextBlockHeight = chainActive.Height() + 1; auto consensusBranchId = CurrentEpochBranchId(nextBlockHeight, Params().GetConsensus()); - if ( nextBlockHeight <= 1 || chainActive.LastTip() == 0 ) + if ( nextBlockHeight <= 1 || chainActive.Tip() == 0 ) tiptime = (uint32_t)time(NULL); - else tiptime = (uint32_t)chainActive.LastTip()->nTime; + else + tiptime = (uint32_t)chainActive.Tip()->nTime; //fprintf(stderr,"addmempool 0\n"); // Node operator can choose to reject tx by number of transparent inputs static_assert(std::numeric_limits::max() >= std::numeric_limits::max(), "size_t too small"); @@ -1806,11 +1794,11 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa return false; } } -//fprintf(stderr,"addmempool 1\n"); auto verifier = libzcash::ProofVerifier::Strict(); - if ( ASSETCHAINS_SYMBOL[0] == 0 && komodo_validate_interest(tx,chainActive.LastTip()->nHeight+1,chainActive.LastTip()->GetMedianTimePast() + 777,0) < 0 ) + if (chainName.isKMD() && chainActive.Tip() != nullptr + && !komodo_validate_interest(tx, chainActive.Tip()->nHeight + 1, chainActive.Tip()->GetMedianTimePast() + 777)) { - return error("%s: komodo_validate_interest failed txid.%s", __func__, tx.GetHash().ToString()); + return state.DoS(0, error("%s: komodo_validate_interest failed txid.%s", __func__, tx.GetHash().ToString()), REJECT_INVALID, "komodo-interest-invalid"); } if (!CheckTransaction(tiptime,tx, state, verifier, 0, 0)) @@ -1824,8 +1812,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa { return error("AcceptToMemoryPool: ContextualCheckTransaction failed"); } -//fprintf(stderr,"addmempool 2\n"); - // Coinbase is only valid in a block, not as a loose transaction + // Coinbase is only valid in a block, not as a loose transaction if (tx.IsCoinBase()) { fprintf(stderr,"AcceptToMemoryPool coinbase as individual tx\n"); @@ -1836,8 +1823,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa string reason; if (Params().RequireStandard() && !IsStandardTx(tx, reason, nextBlockHeight)) { - // - //fprintf(stderr,"AcceptToMemoryPool reject nonstandard transaction: %s\nscriptPubKey: %s\n",reason.c_str(),tx.vout[0].scriptPubKey.ToString().c_str()); return state.DoS(0,error("AcceptToMemoryPool: nonstandard transaction: %s", reason),REJECT_NONSTANDARD, reason); } @@ -1846,15 +1831,12 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // be mined yet. if (!CheckFinalTx(tx, STANDARD_LOCKTIME_VERIFY_FLAGS)) { - //fprintf(stderr,"AcceptToMemoryPool reject non-final\n"); return state.DoS(0, false, REJECT_NONSTANDARD, "non-final"); } -//fprintf(stderr,"addmempool 3\n"); // is it already in the memory pool? uint256 hash = tx.GetHash(); if (pool.exists(hash)) { - //fprintf(stderr,"already in mempool\n"); return state.Invalid(false, REJECT_DUPLICATE, "already in mempool"); } @@ -1867,7 +1849,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (pool.mapNextTx.count(outpoint)) { // Disable replacement feature for now - return false; + return state.Invalid(false, REJECT_INVALID, "mempool conflict"); } } BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { @@ -1884,7 +1866,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } } } -//fprintf(stderr,"addmempool 4\n"); { CCoinsView dummy; CCoinsViewCache view(&dummy); @@ -1898,11 +1879,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // do we already have it? if (view.HaveCoins(hash)) { - //fprintf(stderr,"view.HaveCoins(hash) error\n"); return state.Invalid(false, REJECT_DUPLICATE, "already have coins"); } - if (tx.IsCoinImport() || tx.IsPegsImport()) + if (tx.IsCoinImport()) { // Inverse of normal case; if input exists, it's been spent if (ExistsImportTombstone(tx, view)) @@ -1919,7 +1899,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa { if (pfMissingInputs) *pfMissingInputs = true; - //fprintf(stderr,"missing inputs\n"); return false; /* https://github.com/zcash/zcash/blob/master/src/main.cpp#L1490 @@ -1930,7 +1909,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // are the actual inputs available? if (!view.HaveInputs(tx)) { - //fprintf(stderr,"accept failure.1\n"); return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),REJECT_DUPLICATE, "bad-txns-inputs-spent"); } } @@ -1938,16 +1916,13 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // are the joinsplit's requirements met? if (!view.HaveJoinSplitRequirements(tx)) { - //fprintf(stderr,"accept failure.2\n"); return state.Invalid(error("AcceptToMemoryPool: joinsplit requirements not met"),REJECT_DUPLICATE, "bad-txns-joinsplit-requirements-not-met"); } // Bring the best block into scope view.GetBestBlock(); - nValueIn = view.GetValueIn(chainActive.LastTip()->nHeight,&interest,tx,chainActive.LastTip()->nTime); - if ( 0 && interest != 0 ) - fprintf(stderr,"add interest %.8f\n",(double)interest/COIN); + nValueIn = view.GetValueIn(GetHeight(),interest,tx); // we have all inputs cached now, so switch back to dummy, so we don't need to keep lock on mempool view.SetBackend(dummy); } @@ -1977,7 +1952,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Keep track of transactions that spend a coinbase, which we re-scan // during reorgs to ensure COINBASE_MATURITY is still met. bool fSpendsCoinbase = false; - if (!tx.IsCoinImport() && !tx.IsPegsImport()) { + if (!tx.IsCoinImport()) { BOOST_FOREACH(const CTxIn &txin, tx.vin) { const CCoins *coins = view.AccessCoins(txin.prevout.hash); if (coins->IsCoinBase()) { @@ -1986,7 +1961,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } } } -//fprintf(stderr,"addmempool 5\n"); // Grab the branch ID we expect this transaction to commit to. We don't // yet know if it does, but if the entry gets added to the mempool, then // it has passed ContextualCheckInputs and therefore this is correct. @@ -2017,7 +1991,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Continuously rate-limit free (really, very-low-fee) transactions // This mitigates 'penny-flooding' -- sending thousands of free transactions just to // be annoying or make others' transactions take longer to confirm. - if (fLimitFree && nFees < ::minRelayTxFee.GetFee(nSize) && !tx.IsCoinImport() && !tx.IsPegsImport()) + if (fLimitFree && nFees < ::minRelayTxFee.GetFee(nSize) && !tx.IsCoinImport()) { static CCriticalSection csFreeLimiter; static double dFreeCount; @@ -2040,7 +2014,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa dFreeCount += nSize; } - if (!tx.IsCoinImport() && !tx.IsPegsImport() && fRejectAbsurdFee && nFees > ::minRelayTxFee.GetFee(nSize) * 10000 && nFees > nValueOut/19) + if (!tx.IsCoinImport() && fRejectAbsurdFee && nFees > ::minRelayTxFee.GetFee(nSize) * 10000 && nFees > nValueOut/19) { string errmsg = strprintf("absurdly high fees %s, %d > %d", hash.ToString(), @@ -2048,7 +2022,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa LogPrint("mempool", errmsg.c_str()); return state.Error("AcceptToMemoryPool: " + errmsg); } -//fprintf(stderr,"addmempool 6\n"); // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. @@ -2069,20 +2042,21 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // invalid blocks, however allowing such transactions into the mempool // can be exploited as a DoS attack. // XXX: is this neccesary for CryptoConditions? - if ( KOMODO_CONNECTING <= 0 && chainActive.LastTip() != 0 ) + bool komodoConnectingSet = false; + if ( KOMODO_CONNECTING <= 0 && chainActive.Tip() != 0 ) { - flag = 1; - KOMODO_CONNECTING = (1<<30) + (int32_t)chainActive.LastTip()->nHeight + 1; + // set KOMODO_CONNECTING so that ContextualCheckInputs works, (don't forget to reset) + komodoConnectingSet = true; + KOMODO_CONNECTING = (1<<30) + (int32_t)chainActive.Tip()->nHeight + 1; } -//fprintf(stderr,"addmempool 7\n"); if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId)) { - if ( flag != 0 ) + if ( komodoConnectingSet ) // undo what we did KOMODO_CONNECTING = -1; return error("AcceptToMemoryPool: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s", hash.ToString()); } - if ( flag != 0 ) + if ( komodoConnectingSet ) KOMODO_CONNECTING = -1; { @@ -2103,17 +2077,21 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } } } - // This should be here still? - //SyncWithWallets(tx, NULL); return true; } +/**** + * @brief Add a transaction to the memory pool without the checks of AcceptToMemoryPool + * @param pool the memory pool to add the transaction to + * @param tx the transaction + * @returns true + */ bool CCTxFixAcceptToMemPoolUnchecked(CTxMemPool& pool, const CTransaction &tx) { // called from CheckBlock which is in cs_main and mempool.cs locks already. auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); - CTxMemPoolEntry entry(tx, 0, GetTime(), 0, chainActive.Height(), mempool.HasNoInputsOf(tx), false, consensusBranchId); - //fprintf(stderr, "adding %s to mempool from block %d\n",tx.GetHash().ToString().c_str(),chainActive.nHeight); + CTxMemPoolEntry entry(tx, 0, GetTime(), 0, chainActive.Height(), + mempool.HasNoInputsOf(tx), false, consensusBranchId); pool.addUnchecked(tx.GetHash(), entry, false); return true; } @@ -2181,41 +2159,49 @@ struct CompareBlocksByHeightMain } }; -/*uint64_t myGettxout(uint256 hash,int32_t n) -{ - CCoins coins; - LOCK2(cs_main,mempool.cs); - CCoinsViewMemPool view(pcoinsTip, mempool); - if (!view.GetCoins(hash, coins)) - return(0); - if ( n < 0 || (unsigned int)n >= coins.vout.size() || coins.vout[n].IsNull() ) - return(0); - else return(coins.vout[n].nValue); -}*/ - -bool myAddtomempool(CTransaction &tx, CValidationState *pstate, bool fSkipExpiry) +/**** + * @brief add a transaction to the mempool + * @param[in] tx the transaction + * @param pstate where to store any error (can be nullptr) + * @param fSkipExpiry set to false to add to pool without many checks + * @returns true on success + */ +bool myAddtomempool(const CTransaction &tx, CValidationState *pstate, bool fSkipExpiry) { CValidationState state; - if (!pstate) + if (pstate == nullptr) pstate = &state; - CTransaction Ltx; bool fMissingInputs,fOverrideFees = false; - if ( mempool.lookup(tx.GetHash(),Ltx) == 0 ) + + CTransaction Ltx; + if ( mempool.lookup(tx.GetHash(),Ltx) == false ) // does not already exist { if ( !fSkipExpiry ) + { + bool fMissingInputs; + bool fOverrideFees = false; return(AcceptToMemoryPool(mempool, *pstate, tx, false, &fMissingInputs, !fOverrideFees, -1)); + } else return(CCTxFixAcceptToMemPoolUnchecked(mempool,tx)); } - else return(true); + return true; } +/***** + * @brief get a transaction by its hash (without locks) + * @param[in] hash what to look for + * @param[out] txOut the found transaction + * @param[out] hashBlock the hash of the block (all zeros if still in mempool) + * @returns true if found + */ bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) { memset(&hashBlock,0,sizeof(hashBlock)); if ( KOMODO_NSPV_SUPERLITE ) { - int64_t rewardsum = 0; int32_t i,retval,txheight,currentheight,height=0,vout = 0; - for (i=0; iReadTxIndex(hash, postx)) { - //fprintf(stderr,"OpenBlockFile\n"); + if (pblocktree->ReadTxIndex(hash, postx)) + { + // Found the transaction in the index. Load the block to get the block hash CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION); if (file.IsNull()) return error("%s: OpenBlockFile failed", __func__); CBlockHeader header; - //fprintf(stderr,"seek and read\n"); try { file >> header; fseek(file.Get(), postx.nTxOffset, SEEK_CUR); @@ -2255,11 +2239,9 @@ bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlo hashBlock = header.GetHash(); if (txOut.GetHash() != hash) return error("%s: txid mismatch", __func__); - //fprintf(stderr,"found on disk %s\n",hash.GetHex().c_str()); return true; } } - //fprintf(stderr,"not found on disk %s\n",hash.GetHex().c_str()); return false; } @@ -2281,10 +2263,16 @@ bool NSPV_myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &ha return false; } -/** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */ +/** + * @brief Find a transaction (uses locks) + * @param[in] hash the transaction to look for + * @param[out] txOut the transaction found + * @param[out] hashBlock the block where the transaction was found (all zeros if found in mempool) + * @param[in] fAllowSlow true to continue searching even if there are no transaction indexes + * @returns true if found + */ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow) { - CBlockIndex *pindexSlow = NULL; memset(&hashBlock,0,sizeof(hashBlock)); LOCK(cs_main); @@ -2315,26 +2303,33 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock } } + CBlockIndex *pindexSlow = nullptr; if (fAllowSlow) { // use coin database to locate block that contains transaction, and scan it int nHeight = -1; { - CCoinsViewCache &view = *pcoinsTip; - const CCoins* coins = view.AccessCoins(hash); - if (coins) + const CCoins* coins = pcoinsTip->AccessCoins(hash); + if (coins != nullptr) + { nHeight = coins->nHeight; - } - if (nHeight > 0) - pindexSlow = chainActive[nHeight]; - } - - if (pindexSlow) { - CBlock block; - if (ReadBlockFromDisk(block, pindexSlow,1)) { - BOOST_FOREACH(const CTransaction &tx, block.vtx) { - if (tx.GetHash() == hash) { - txOut = tx; - hashBlock = pindexSlow->GetBlockHash(); - return true; + if (nHeight > 0) + { + CBlockIndex *pindexSlow = chainActive[nHeight]; + if (pindexSlow != nullptr) + { + CBlock block; + if (ReadBlockFromDisk(block, pindexSlow,1)) + { + for(const CTransaction &tx : block.vtx) + { + if (tx.GetHash() == hash) + { + txOut = tx; + hashBlock = pindexSlow->GetBlockHash(); + return true; + } + } + } + } } } } @@ -2343,21 +2338,6 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock return false; } -/*char *komodo_getspendscript(uint256 hash,int32_t n) - { - CTransaction tx; uint256 hashBlock; - if ( !GetTransaction(hash,tx,hashBlock,true) ) - { - printf("null GetTransaction\n"); - return(0); - } - if ( n >= 0 && n < tx.vout.size() ) - return((char *)tx.vout[n].scriptPubKey.ToString().c_str()); - else printf("getspendscript illegal n.%d\n",n); - return(0); - }*/ - - ////////////////////////////////////////////////////////////////////////////// // // CBlock and CBlockIndex @@ -2433,18 +2413,10 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex,bool checkPOW) return true; } -//uint64_t komodo_moneysupply(int32_t height); -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -extern uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS+1]; -extern uint32_t ASSETCHAINS_MAGIC; -extern uint64_t ASSETCHAINS_LINEAR,ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY; -extern uint8_t ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE; -extern int32_t ASSETCHAINS_STAKED; - CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) { int32_t numhalvings,i; uint64_t numerator; CAmount nSubsidy = 3 * COIN; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) + if ( chainName.isKMD() ) { if ( nHeight == 1 ) return(100000000 * COIN); // ICO allocation @@ -2509,22 +2481,12 @@ bool IsInitialBlockDownload() return true; } - bool state; - arith_uint256 bigZero = arith_uint256(); - arith_uint256 minWork = UintToArith256(chainParams.GetConsensus().nMinimumChainWork); CBlockIndex *ptr = chainActive.Tip(); - if (ptr == NULL) { - //fprintf(stderr,"nullptr in IsInitialDownload\n"); - return true; - } - if (0 && ptr->nChainWork < UintToArith256(chainParams.GetConsensus().nMinimumChainWork)) - { - fprintf(stderr,"nChainWork insufficient in IsInitialDownload\n"); return true; } - state = ((chainActive.Height() < ptr->nHeight - 24*60) || + bool state = ((chainActive.Height() < ptr->nHeight - 24*60) || ptr->GetBlockTime() < (GetTime() - nMaxTipAge)); if ( KOMODO_INSYNC != 0 ) state = false; @@ -2588,7 +2550,8 @@ void CheckForkWarningConditions() if (pindexBestForkTip && chainActive.Height() - pindexBestForkTip->nHeight >= 288) pindexBestForkTip = NULL; - if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > (chainActive.LastTip()->nChainWork + (GetBlockProof(*chainActive.LastTip()) * 6)))) + if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > + (chainActive.Tip()->nChainWork + (GetBlockProof(*chainActive.Tip()) * 6)))) { if (!fLargeWorkForkFound && pindexBestForkBase) { @@ -2623,7 +2586,7 @@ void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip) AssertLockHeld(cs_main); // If we are on a fork that is sufficiently large, set a warning flag CBlockIndex* pfork = pindexNewForkTip; - CBlockIndex* plonger = chainActive.LastTip(); + CBlockIndex* plonger = chainActive.Tip(); while (pfork && pfork != plonger) { while (plonger && plonger->nHeight > pfork->nHeight) @@ -2680,7 +2643,7 @@ void static InvalidChainFound(CBlockIndex* pindexNew) pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, log(pindexNew->nChainWork.getdouble())/log(2.0), DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexNew->GetBlockTime())); - CBlockIndex *tip = chainActive.LastTip(); + CBlockIndex *tip = chainActive.Tip(); assert (tip); LogPrintf("%s: current best=%s height=%d log2_work=%.8g date=%s\n", __func__, tip->GetBlockHash().ToString(), chainActive.Height(), @@ -2714,7 +2677,6 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txund { txundo.vprevout.reserve(tx.vin.size()); BOOST_FOREACH(const CTxIn &txin, tx.vin) { - if (tx.IsPegsImport() && txin.prevout.n==10e8) continue; CCoinsModifier coins = inputs.ModifyCoins(txin.prevout.hash); unsigned nPos = txin.prevout.n; @@ -2738,7 +2700,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txund inputs.ModifyCoins(tx.GetHash())->FromTx(tx, nHeight); // add outputs // Unorthodox state - if (tx.IsCoinImport() || tx.IsPegsImport()) { + if (tx.IsCoinImport()) { // add a tombstone for the burnTx AddImportTombstone(tx, inputs, nHeight); } @@ -2782,11 +2744,6 @@ namespace Consensus { CAmount nFees = 0; for (unsigned int i = 0; i < tx.vin.size(); i++) { - if (tx.IsPegsImport() && i==0) - { - nValueIn=GetCoinImportValue(tx); - continue; - } const COutPoint &prevout = tx.vin[i].prevout; const CCoins *coins = inputs.AccessCoins(prevout.hash); assert(coins); @@ -2804,9 +2761,9 @@ namespace Consensus { } // Ensure that coinbases are matured, no DoS as retry may work later - if (nSpendHeight - coins->nHeight < COINBASE_MATURITY) { + if (nSpendHeight - coins->nHeight < ::Params().CoinbaseMaturity()) { return state.Invalid( - error("CheckInputs(): tried to spend coinbase at depth %d/%d", nSpendHeight - coins->nHeight, (int32_t)COINBASE_MATURITY), + error("CheckInputs(): tried to spend coinbase at depth %d/%d", nSpendHeight - coins->nHeight, (int32_t)::Params().CoinbaseMaturity()), REJECT_INVALID, "bad-txns-premature-spend-of-coinbase"); } @@ -2824,14 +2781,13 @@ namespace Consensus { // Check for negative or overflow input values nValueIn += coins->vout[prevout.n].nValue; #ifdef KOMODO_ENABLE_INTEREST - if ( ASSETCHAINS_SYMBOL[0] == 0 && nSpendHeight > 60000 )//chainActive.LastTip() != 0 && chainActive.LastTip()->nHeight >= 60000 ) + if ( chainName.isKMD() && nSpendHeight > 60000 )//chainActive.Tip() != 0 && chainActive.Tip()->nHeight >= 60000 ) { if ( coins->vout[prevout.n].nValue >= 10*COIN ) { int64_t interest; int32_t txheight; uint32_t locktime; if ( (interest= komodo_accrued_interest(&txheight,&locktime,prevout.hash,prevout.n,0,coins->vout[prevout.n].nValue,(int32_t)nSpendHeight-1)) != 0 ) { - //fprintf(stderr,"checkResult %.8f += val %.8f interest %.8f ht.%d lock.%u tip.%u\n",(double)nValueIn/COIN,(double)coins->vout[prevout.n].nValue/COIN,(double)interest/COIN,txheight,locktime,chainActive.LastTip()->nTime); nValueIn += interest; } } @@ -2897,7 +2853,6 @@ bool ContextualCheckInputs( // still computed and checked, and any change will be caught at the next checkpoint. if (fScriptChecks) { for (unsigned int i = 0; i < tx.vin.size(); i++) { - if (tx.IsPegsImport() && i==0) continue; const COutPoint &prevout = tx.vin[i].prevout; const CCoins* coins = inputs.AccessCoins(prevout.hash); assert(coins); @@ -2933,7 +2888,7 @@ bool ContextualCheckInputs( } } - if (tx.IsCoinImport() || tx.IsPegsImport()) + if (tx.IsCoinImport()) { LOCK(cs_main); ServerTransactionSignatureChecker checker(&tx, 0, 0, false, txdata); @@ -2943,45 +2898,6 @@ bool ContextualCheckInputs( return true; } - -/*bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, const Consensus::Params& consensusParams, std::vector *pvChecks) - { - if (!NonContextualCheckInputs(tx, state, inputs, fScriptChecks, flags, cacheStore, consensusParams, pvChecks)) { - fprintf(stderr,"ContextualCheckInputs failure.0\n"); - return false; - } - - if (!tx.IsCoinBase()) - { - // While checking, GetBestBlock() refers to the parent block. - // This is also true for mempool checks. - CBlockIndex *pindexPrev = mapBlockIndex.find(inputs.GetBestBlock())->second; - int nSpendHeight = pindexPrev->nHeight + 1; - for (unsigned int i = 0; i < tx.vin.size(); i++) - { - const COutPoint &prevout = tx.vin[i].prevout; - const CCoins *coins = inputs.AccessCoins(prevout.hash); - // Assertion is okay because NonContextualCheckInputs ensures the inputs - // are available. - assert(coins); - - // If prev is coinbase, check that it's matured - if (coins->IsCoinBase()) { - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - COINBASE_MATURITY = _COINBASE_MATURITY; - if (nSpendHeight - coins->nHeight < COINBASE_MATURITY) { - fprintf(stderr,"ContextualCheckInputs failure.1 i.%d of %d\n",i,(int32_t)tx.vin.size()); - - return state.Invalid( - error("CheckInputs(): tried to spend coinbase at depth %d", nSpendHeight - coins->nHeight),REJECT_INVALID, "bad-txns-premature-spend-of-coinbase"); - } - } - } - } - - return true; - }*/ - namespace { bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint256& hashBlock, const CMessageHeader::MessageStartChars& messageStart) @@ -3007,7 +2923,6 @@ namespace { hasher << hashBlock; hasher << blockundo; fileout << hasher.GetHash(); -//fprintf(stderr,"hashBlock.%s hasher.%s\n",hashBlock.GetHex().c_str(),hasher.GetHash().GetHex().c_str()); return true; } @@ -3156,7 +3071,6 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex *pfClean = false; bool fClean = true; - //komodo_disconnect(pindex,block); does nothing? CBlockUndo blockUndo; CDiskBlockPos pos = pindex->GetUndoPos(); if (pos.IsNull()) @@ -3220,11 +3134,9 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex // restore inputs if (!tx.IsMint()) { CTxUndo &txundo = blockUndo.vtxundo[i-1]; - if (tx.IsPegsImport()) txundo.vprevout.insert(txundo.vprevout.begin(),CTxInUndo()); if (txundo.vprevout.size() != tx.vin.size()) return error("DisconnectBlock(): transaction and undo data inconsistent"); for (unsigned int j = tx.vin.size(); j-- > 0;) { - if (tx.IsPegsImport() && j==0) continue; const COutPoint &out = tx.vin[j].prevout; const CTxInUndo &undo = txundo.vprevout[j]; if (!ApplyTxInUndo(undo, view, out)) @@ -3258,7 +3170,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex } } } - else if (tx.IsCoinImport() || tx.IsPegsImport()) + else if (tx.IsCoinImport()) { RemoveImportTombstone(tx, view); } @@ -3404,6 +3316,25 @@ static int64_t nTimeTotal = 0; bool FindBlockPos(int32_t tmpflag,CValidationState &state, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false); bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos); +/***** + * Only for testing, DO NOT USE + * @returns the cs_main mutex + */ +CCriticalSection& get_cs_main() +{ + return cs_main; +} + +/***** + * @brief Apply the effects of this block (with given index) on the UTXO set represented by coins + * @param block the block to add + * @param state the result status + * @param pindex where to insert the block + * @param view the chain + * @param fJustCheck do not actually modify, only do checks + * @param fcheckPOW + * @returns true on success + */ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck,bool fCheckPOW) { CDiskBlockPos blockPos; @@ -3412,7 +3343,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return(true); if ( KOMODO_STOPAT != 0 && pindex->nHeight > KOMODO_STOPAT ) return(false); - //fprintf(stderr,"connectblock ht.%d\n",(int32_t)pindex->nHeight); AssertLockHeld(cs_main); bool fExpensiveChecks = true; if (fCheckpointsEnabled) { @@ -3430,7 +3360,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // Check it again to verify JoinSplit proofs, and in case a previous version let a bad block in if ( !CheckBlock(&futureblock,pindex->nHeight,pindex,block, state, fExpensiveChecks ? verifier : disabledVerifier, fCheckPOW, !fJustCheck) || futureblock != 0 ) { - //fprintf(stderr,"checkblock failure in connectblock futureblock.%d\n",futureblock); return false; } if ( fCheckPOW != 0 && (pindex->nStatus & BLOCK_VALID_CONTEXT) != BLOCK_VALID_CONTEXT ) // Activate Jan 15th, 2019 @@ -3465,7 +3394,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin REJECT_INVALID, "bad-cb-amount"); // calculate the notaries compensation and validate the amounts and pubkeys are correct. notarypaycheque = komodo_checknotarypay((CBlock *)&block,(int32_t)pindex->nHeight); - //fprintf(stderr, "notarypaycheque.%lu\n", notarypaycheque); if ( notarypaycheque > 0 ) blockReward += notarypaycheque; else @@ -3487,7 +3415,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) return error("AcceptBlock(): ReceivedBlockTransactions failed"); setDirtyFileInfo.insert(blockPos.nFile); - //fprintf(stderr,"added ht.%d copy of tmpfile to %d.%d\n",pindex->nHeight,blockPos.nFile,blockPos.nPos); } // verify that the view's current state corresponds to the previous block uint256 hashPrevBlock = pindex->pprev == NULL ? uint256() : pindex->pprev->GetBlockHash(); @@ -3514,8 +3441,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } bool fScriptChecks = (!fCheckpointsEnabled || pindex->nHeight >= Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints())); - //if ( KOMODO_TESTNET_EXPIRATION != 0 && pindex->nHeight > KOMODO_TESTNET_EXPIRATION ) // "testnet" - // return(false); // Do not allow blocks that contain transactions which 'overwrite' older transactions, // unless those are already completely spent. BOOST_FOREACH(const CTransaction& tx, block.vtx) { @@ -3592,7 +3517,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (nSigOps > MAX_BLOCK_SIGOPS) return state.DoS(100, error("ConnectBlock(): too many sigops"), REJECT_INVALID, "bad-blk-sigops"); - //fprintf(stderr,"ht.%d vout0 t%u\n",pindex->nHeight,tx.nLockTime); if (!tx.IsMint()) { if (!view.HaveInputs(tx)) @@ -3610,7 +3534,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin { for (size_t j = 0; j < tx.vin.size(); j++) { - if (tx.IsPegsImport() && j==0) continue; const CTxIn input = tx.vin[j]; const CTxOut &prevout = view.GetOutputFor(tx.vin[j]); @@ -3656,21 +3579,10 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin fprintf(stderr,"valueout %.8f too big\n",(double)valueout/COIN); return state.DoS(100, error("ConnectBlock(): GetValueOut too big"),REJECT_INVALID,"tx valueout is too big"); } - //prevsum = voutsum; - //voutsum += valueout; - /*if ( KOMODO_VALUETOOBIG(voutsum) != 0 ) - { - fprintf(stderr,"voutsum %.8f too big\n",(double)voutsum/COIN); - return state.DoS(100, error("ConnectBlock(): voutsum too big"),REJECT_INVALID,"tx valueout is too big"); - } - else - if ( voutsum < prevsum ) // PRLPAY overflows this and it isnt a conclusive test anyway - return state.DoS(100, error("ConnectBlock(): voutsum less after adding valueout"),REJECT_INVALID,"tx valueout is too big");*/ if (!tx.IsCoinBase()) { - nFees += (stakeTxValue= view.GetValueIn(chainActive.LastTip()->nHeight,&interest,tx,chainActive.LastTip()->nTime) - valueout); + nFees += (stakeTxValue= view.GetValueIn(chainActive.Tip()->nHeight,interest,tx) - valueout); sum += interest; - //fprintf(stderr, "tx.%s nFees.%li interest.%li\n", tx.GetHash().ToString().c_str(), stakeTxValue, interest); std::vector vChecks; if (!ContextualCheckInputs(tx, state, view, fExpensiveChecks, flags, false, txdata[i], chainparams.GetConsensus(), consensusBranchId, nScriptCheckThreads ? &vChecks : NULL)) @@ -3703,8 +3615,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } } - //if ( ASSETCHAINS_SYMBOL[0] == 0 ) - // komodo_earned_interest(pindex->nHeight,sum); CTxUndo undoDummy; if (i > 0) { blockundo.vtxundo.push_back(CTxUndo()); @@ -3714,7 +3624,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { BOOST_FOREACH(const uint256 ¬e_commitment, joinsplit.commitments) { // Insert the note commitments into our temporary tree. - sprout_tree.append(note_commitment); } } @@ -3728,7 +3637,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } // This is moved from CheckBlock for staking chains, so we can enforce the staking tx value was indeed paid to the coinbase. - //fprintf(stderr, "blockReward.%li stakeTxValue.%li sum.%li\n",blockReward,stakeTxValue,sum); if ( ASSETCHAINS_STAKED != 0 && fCheckPOW && komodo_checkPOW(blockReward+stakeTxValue-notarypaycheque,1,(CBlock *)&block,pindex->nHeight) < 0 ) return state.DoS(100, error("ConnectBlock: ac_staked chain failed slow komodo_checkPOW"),REJECT_INVALID, "failed-slow_checkPOW"); @@ -3752,7 +3660,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime1 - nTimeStart), 0.001 * (nTime1 - nTimeStart) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime1 - nTimeStart) / (nInputs-1), nTimeConnect * 0.000001); blockReward += nFees + sum; - if ( ASSETCHAINS_SYMBOL[0] == 0 && pindex->nHeight >= KOMODO_NOTARIES_HEIGHT2) + if ( chainName.isKMD() && pindex->nHeight >= KOMODO_NOTARIES_HEIGHT2) blockReward -= sum; if ( ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 ) //ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && @@ -3766,17 +3674,15 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin fprintf(stderr,"checktoshis %.8f vs %.8f numvouts %d\n",dstr(checktoshis),dstr(block.vtx[0].vout[1].nValue),(int32_t)block.vtx[0].vout.size()); } } - if (ASSETCHAINS_SYMBOL[0] != 0 && pindex->nHeight == 1 && block.vtx[0].GetValueOut() != blockReward) + if ( !chainName.isKMD() && pindex->nHeight == 1 && block.vtx[0].GetValueOut() != blockReward) { return state.DoS(100, error("ConnectBlock(): coinbase for block 1 pays wrong amount (actual=%d vs correct=%d)", block.vtx[0].GetValueOut(), blockReward), REJECT_INVALID, "bad-cb-amount"); } if ( block.vtx[0].GetValueOut() > blockReward+KOMODO_EXTRASATOSHI ) { - if ( ASSETCHAINS_SYMBOL[0] != 0 || pindex->nHeight >= KOMODO_NOTARIES_HEIGHT1 || block.vtx[0].vout[0].nValue > blockReward ) + if ( !chainName.isKMD() || pindex->nHeight >= KOMODO_NOTARIES_HEIGHT1 || block.vtx[0].vout[0].nValue > blockReward ) { - //fprintf(stderr, "coinbase pays too much\n"); - //sleepflag = true; return state.DoS(100, error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)", block.vtx[0].GetValueOut(), blockReward), @@ -3793,7 +3699,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return true; // Write undo information to disk - //fprintf(stderr,"nFile.%d isNull %d vs isvalid %d nStatus %x\n",(int32_t)pindex->nFile,pindex->GetUndoPos().IsNull(),pindex->IsValid(BLOCK_VALID_SCRIPTS),(uint32_t)pindex->nStatus); if (pindex->GetUndoPos().IsNull() || !pindex->IsValid(BLOCK_VALID_SCRIPTS)) { if (pindex->GetUndoPos().IsNull()) @@ -3880,13 +3785,11 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin int64_t nTime4 = GetTimeMicros(); nTimeCallbacks += nTime4 - nTime3; LogPrint("bench", " - Callbacks: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeCallbacks * 0.000001); - //FlushStateToDisk(); komodo_connectblock(false,pindex,*(CBlock *)&block); // dPoW state update. if ( ASSETCHAINS_NOTARY_PAY[0] != 0 ) { // Update the notary pay with the latest payment. pindex->nNotaryPay = pindex->pprev->nNotaryPay + notarypaycheque; - //fprintf(stderr, "total notary pay.%li\n", pindex->nNotaryPay); } return true; } @@ -3961,7 +3864,7 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) { vFiles.push_back(make_pair(*it, &vinfoBlockFile[*it])); setDirtyFileInfo.erase(it++); } - std::vector vBlocks; + std::vector vBlocks; vBlocks.reserve(setDirtyBlockIndex.size()); for (set::iterator it = setDirtyBlockIndex.begin(); it != setDirtyBlockIndex.end(); ) { vBlocks.push_back(*it); @@ -3970,6 +3873,12 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) { if (!pblocktree->WriteBatchSync(vFiles, nLastBlockFile, vBlocks)) { return AbortNode(state, "Files to write to block index database"); } + // Now that we have written the block indices to the database, we do not + // need to store solutions for these CBlockIndex objects in memory. + // cs_main must be held here. + for (CBlockIndex *pblockindex : vBlocks) { + pblockindex->TrimSolution(); + } } // Finally remove any pruned files if (fFlushForPrune) @@ -4023,18 +3932,18 @@ void static UpdateTip(CBlockIndex *pindexNew) { mempool.AddTransactionsUpdated(1); KOMODO_NEWBLOCKS++; double progress; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) { - progress = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.LastTip()); + if ( chainName.isKMD() ) { + progress = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip()); } else { - int32_t longestchain = komodo_longestchain(); - progress = (longestchain > 0 ) ? (double) chainActive.Height() / longestchain : 1.0; + int32_t longestchain = komodo_longestchain(); + progress = (longestchain > 0 ) ? (double) chainActive.Height() / longestchain : 1.0; } LogPrintf("%s: new best=%s height=%d log2_work=%.8g tx=%lu date=%s progress=%f cache=%.1fMiB(%utx)\n", __func__, - chainActive.LastTip()->GetBlockHash().ToString(), chainActive.Height(), + chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), - (unsigned long)chainActive.LastTip()->nChainTx, - DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.LastTip()->GetBlockTime()), progress, + (unsigned long)chainActive.Tip()->nChainTx, + DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()), progress, pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize()); cvBlockChange.notify_all(); @@ -4078,7 +3987,6 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { CBlock block; if (!ReadBlockFromDisk(block, pindexDelete,1)) return AbortNode(state, "Failed to read block"); - //if ( ASSETCHAINS_SYMBOL[0] != 0 || pindexDelete->nHeight > 1400000 ) { int32_t notarizedht,prevMoMheight; uint256 notarizedhash,txid; notarizedht = komodo_notarized_height(&prevMoMheight,¬arizedhash,&txid); @@ -4214,7 +4122,7 @@ int32_t komodo_activate_sapling(CBlockIndex *pindex) if ( prevtime <= KOMODO_SAPLING_ACTIVATION && blocktime > KOMODO_SAPLING_ACTIVATION ) { activation = height + 60; - fprintf(stderr,"%s transition at %d (%d, %u) -> (%d, %u)\n",ASSETCHAINS_SYMBOL,height,prevht,prevtime,height,blocktime); + fprintf(stderr,"%s transition at %d (%d, %u) -> (%d, %u)\n",chainName.symbol().c_str(),height,prevht,prevtime,height,blocktime); } if ( prevtime < KOMODO_SAPLING_ACTIVATION-3600*24 ) break; @@ -4226,7 +4134,7 @@ int32_t komodo_activate_sapling(CBlockIndex *pindex) if ( activation != 0 ) { komodo_setactivation(activation); - fprintf(stderr,"%s sapling activation at %d\n",ASSETCHAINS_SYMBOL,activation); + fprintf(stderr,"%s sapling activation at %d\n",chainName.symbol().c_str(),activation); ASSETCHAINS_SAPLING = activation; } return activation; @@ -4238,13 +4146,16 @@ static int64_t nTimeFlush = 0; static int64_t nTimeChainState = 0; static int64_t nTimePostConnect = 0; -/** - * Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock - * corresponding to pindexNew, to bypass loading it again from disk. - * You probably want to call mempool.removeWithoutBranchId after this, with cs_main held. +/*** + * @brief Connect a new block to chainActive. + * @note You probably want to call mempool.removeWithoutBranchId after this, with cs_main held. + * @param[out] state holds the state + * @param pindexNew the new index + * @param pblock a pointer to a CBlock (nullptr will load it from disk) + * @returns true on success */ -bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *pblock) { - +bool ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *pblock) +{ assert(pindexNew->pprev == chainActive.Tip()); // Read block from disk. int64_t nTime1 = GetTimeMicros(); @@ -4255,7 +4166,6 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * pblock = █ } KOMODO_CONNECTING = (int32_t)pindexNew->nHeight; - //fprintf(stderr,"%s connecting ht.%d maxsize.%d vs %d\n",ASSETCHAINS_SYMBOL,(int32_t)pindexNew->nHeight,MAX_BLOCK_SIZE(pindexNew->nHeight),(int32_t)::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION)); // Get the current commitment tree SproutMerkleTree oldSproutTree; SaplingMerkleTree oldSaplingTree; @@ -4265,9 +4175,10 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * assert(pcoinsTip->GetSaplingAnchorAt(pcoinsTip->GetBestAnchor(SAPLING), oldSaplingTree)); } // Apply the block atomically to the chain state. - int64_t nTime2 = GetTimeMicros(); nTimeReadFromDisk += nTime2 - nTime1; - int64_t nTime3; + int64_t nTime2 = GetTimeMicros(); + nTimeReadFromDisk += nTime2 - nTime1; LogPrint("bench", " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001); + int64_t nTime3; { CCoinsViewCache view(pcoinsTip); bool rv = ConnectBlock(*pblock, state, pindexNew, view, false, true); @@ -4277,11 +4188,6 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * if (state.IsInvalid()) { InvalidBlockFound(pindexNew, state); - /*if ( ASSETCHAINS_CBOPRET != 0 ) - { - pindexNew->nStatus &= ~BLOCK_FAILED_MASK; - fprintf(stderr,"reconsiderblock %d\n",(int32_t)pindexNew->nHeight); - }*/ } return error("ConnectTip(): ConnectBlock %s failed", pindexNew->GetBlockHash().ToString()); } @@ -4333,15 +4239,8 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * if ( KOMODO_LONGESTCHAIN != 0 && (pindexNew->nHeight == KOMODO_LONGESTCHAIN || pindexNew->nHeight == KOMODO_LONGESTCHAIN+1) ) KOMODO_INSYNC = (int32_t)pindexNew->nHeight; else KOMODO_INSYNC = 0; - //fprintf(stderr,"connect.%d insync.%d ASSETCHAINS_SAPLING.%d\n",(int32_t)pindexNew->nHeight,KOMODO_INSYNC,ASSETCHAINS_SAPLING); - /*if ( KOMODO_INSYNC != 0 ) //ASSETCHAINS_SYMBOL[0] == 0 && - komodo_broadcast(pblock,8); - else if ( ASSETCHAINS_SYMBOL[0] != 0 ) - komodo_broadcast(pblock,4);*/ if ( KOMODO_NSPV_FULLNODE ) { - if ( ASSETCHAINS_CBOPRET != 0 ) - komodo_pricesupdate(pindexNew->nHeight,pblock); if ( ASSETCHAINS_SAPLING <= 0 && pindexNew->nTime > KOMODO_SAPLING_ACTIVATION - 24*3600 ) komodo_activate_sapling(pindexNew); if ( ASSETCHAINS_CC != 0 && KOMODO_SNAPSHOT_INTERVAL != 0 && (pindexNew->nHeight % KOMODO_SNAPSHOT_INTERVAL) == 0 && pindexNew->nHeight >= KOMODO_SNAPSHOT_INTERVAL ) @@ -4421,7 +4320,7 @@ static void PruneBlockIndexCandidates() { // Note that we can't delete the current block itself, as we may need to return to it later in case a // reorganization to a better block fails. std::set::iterator it = setBlockIndexCandidates.begin(); - while (it != setBlockIndexCandidates.end() && setBlockIndexCandidates.value_comp()(*it, chainActive.LastTip())) { + while (it != setBlockIndexCandidates.end() && setBlockIndexCandidates.value_comp()(*it, chainActive.Tip())) { setBlockIndexCandidates.erase(it++); } // Either the current tip or a successor of it we're working towards is left in setBlockIndexCandidates. @@ -4494,7 +4393,7 @@ static bool ActivateBestChainStep(bool fSkipdpow, CValidationState &state, CBloc "- " + strprintf(_("New tip: %s, height %d, work %s\n"), pindexMostWork->phashBlock->GetHex(), pindexMostWork->nHeight, pindexMostWork->nChainWork.GetHex()) + "- " + strprintf(_("Fork point: %s %s, height %d"), - ASSETCHAINS_SYMBOL,pindexFork->phashBlock->GetHex(), pindexFork->nHeight) + "\n\n" + + chainName.symbol().c_str(),pindexFork->phashBlock->GetHex(), pindexFork->nHeight) + "\n\n" + _("Please help, human!"); LogPrintf("*** %s\nif you launch with -maxreorg=%d it might be able to resolve this automatically", msg,reorgLength+10); fprintf(stderr,"*** %s\nif you launch with -maxreorg=%d it might be able to resolve this automatically", msg.c_str(),reorgLength+10); @@ -4514,8 +4413,8 @@ static bool ActivateBestChainStep(bool fSkipdpow, CValidationState &state, CBloc if ( KOMODO_REWIND != 0 ) { CBlockIndex *tipindex; - fprintf(stderr,">>>>>>>>>>> rewind start ht.%d -> KOMODO_REWIND.%d\n",chainActive.LastTip()->nHeight,KOMODO_REWIND); - while ( KOMODO_REWIND > 0 && (tipindex= chainActive.LastTip()) != 0 && tipindex->nHeight > KOMODO_REWIND ) + fprintf(stderr,">>>>>>>>>>> rewind start ht.%d -> KOMODO_REWIND.%d\n",chainActive.Tip()->nHeight,KOMODO_REWIND); + while ( KOMODO_REWIND > 0 && (tipindex= chainActive.Tip()) != 0 && tipindex->nHeight > KOMODO_REWIND ) { fBlocksDisconnected = true; fprintf(stderr,"%d ",(int32_t)tipindex->nHeight); @@ -4523,7 +4422,7 @@ static bool ActivateBestChainStep(bool fSkipdpow, CValidationState &state, CBloc if ( !DisconnectTip(state) ) break; } - fprintf(stderr,"reached rewind.%d, best to do: ./komodo-cli -ac_name=%s stop\n",KOMODO_REWIND,ASSETCHAINS_SYMBOL); + fprintf(stderr,"reached rewind.%d, best to do: ./komodo-cli -ac_name=%s stop\n",KOMODO_REWIND,chainName.symbol().c_str()); sleep(20); fprintf(stderr,"resuming normal operations\n"); KOMODO_REWIND = 0; @@ -4547,8 +4446,10 @@ static bool ActivateBestChainStep(bool fSkipdpow, CValidationState &state, CBloc nHeight = nTargetHeight; // Connect new blocks. - BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) { - if (!ConnectTip(state, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL)) { + BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) + { + if (!ConnectTip(state, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL)) + { if (state.IsInvalid()) { // The block violates a consensus rule. if (!state.CorruptionPossible()) @@ -4625,17 +4526,23 @@ bool ActivateBestChain(bool fSkipdpow, CValidationState &state, CBlock *pblock) nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(chainParams.Checkpoints()); // Don't relay blocks if pruning -- could cause a peer to try to download, resulting // in a stalled download if the block file is pruned before the request. - if (nLocalServices & NODE_NETWORK) { + if (nLocalServices & NODE_NETWORK) + { + int ht = 0; + { + LOCK(cs_main); + ht = chainActive.Height(); + } LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) - if (chainActive.Height() > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) - pnode->PushInventory(CInv(MSG_BLOCK, hashNewTip)); + for(CNode* pnode : vNodes) + if (ht > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) + pnode->PushInventory(CInv(MSG_BLOCK, hashNewTip)); } // Notify external listeners about the new tip. GetMainSignals().UpdatedBlockTip(pindexNewTip); uiInterface.NotifyBlockTip(hashNewTip); } //else fprintf(stderr,"initial download skips propagation\n"); - } while(pindexMostWork != chainActive.Tip()); + } while(pindexMostWork != pindexNewTip); CheckBlockIndex(); // Write changes periodically to disk, after relay. @@ -5052,9 +4959,9 @@ bool CheckBlockHeader(int32_t *futureblockp,int32_t height,CBlockIndex *pindex, for (i=31; i>=0; i--) fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); fprintf(stderr," <- CheckBlockHeader\n"); - if ( chainActive.LastTip() != 0 ) + if ( chainActive.Tip() != 0 ) { - hash = chainActive.LastTip()->GetBlockHash(); + hash = chainActive.Tip()->GetBlockHash(); for (i=31; i>=0; i--) fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); fprintf(stderr," <- chainTip\n"); @@ -5105,16 +5012,28 @@ bool CheckBlockHeader(int32_t *futureblockp,int32_t height,CBlockIndex *pindex, return true; } -int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtime); int32_t komodo_checkPOW(int64_t stakeTxValue,int32_t slowflag,CBlock *pblock,int32_t height); -bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const CBlock& block, CValidationState& state, - libzcash::ProofVerifier& verifier, - bool fCheckPOW, bool fCheckMerkleRoot) +/**** + * @brief various checks of block validity + * @param[out] futureblockp pointer to the future block + * @param[in] height the new height + * @param[out] pindex the block index + * @param[in] block the block to check + * @param[out] state stores results + * @param[in] verifier verification routine + * @param[in] fCheckPOW pass true to check PoW + * @param[in] fCheckMerkleRoot pass true to check merkle root + * @returns true on success, on error, state will contain info + */ +bool CheckBlock(int32_t *futureblockp, int32_t height, CBlockIndex *pindex, const CBlock& block, + CValidationState& state, libzcash::ProofVerifier& verifier, bool fCheckPOW, + bool fCheckMerkleRoot) { - uint8_t pubkey33[33]; uint256 hash; uint32_t tiptime = (uint32_t)block.nTime; + uint8_t pubkey33[33]; + uint32_t tiptime = (uint32_t)block.nTime; // These are checks that are independent of context. - hash = block.GetHash(); + uint256 hash = block.GetHash(); // Check that the header is valid (particularly PoW). This is mostly redundant with the call in AcceptBlockHeader. if (!CheckBlockHeader(futureblockp,height,pindex,block,state,fCheckPOW)) { @@ -5124,24 +5043,23 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C return false; } } - if ( pindex != 0 && pindex->pprev != 0 ) + if ( pindex != nullptr && pindex->pprev != nullptr ) tiptime = (uint32_t)pindex->pprev->nTime; if ( fCheckPOW ) { - //if ( !CheckEquihashSolution(&block, Params()) ) - // return state.DoS(100, error("CheckBlock: Equihash solution invalid"),REJECT_INVALID, "invalid-solution"); komodo_block2pubkey33(pubkey33,(CBlock *)&block); if ( !CheckProofOfWork(block,pubkey33,height,Params().GetConsensus()) ) { - int32_t z; for (z=31; z>=0; z--) + for (int32_t z = 31; z >= 0; z--) fprintf(stderr,"%02x",((uint8_t *)&hash)[z]); fprintf(stderr," failed hash ht.%d\n",height); return state.DoS(50, error("CheckBlock: proof of work failed"),REJECT_INVALID, "high-hash"); } if ( ASSETCHAINS_STAKED == 0 && komodo_checkPOW(0,1,(CBlock *)&block,height) < 0 ) // checks Equihash - return state.DoS(100, error("CheckBlock: failed slow_checkPOW"),REJECT_INVALID, "failed-slow_checkPOW"); + return state.DoS(100, error("CheckBlock: failed slow_checkPOW"),REJECT_INVALID, + "failed-slow_checkPOW"); } - if ( height > nDecemberHardforkHeight && ASSETCHAINS_SYMBOL[0] == 0 ) // December 2019 hardfork + if ( height > nDecemberHardforkHeight && chainName.isKMD() ) // December 2019 hardfork { int32_t notaryid; int32_t special = komodo_chosennotary(¬aryid,height,pubkey33,tiptime); @@ -5150,14 +5068,17 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C CBlock blockcopy = block; // block shouldn't be changed below, so let's make it's copy CBlock *pblockcopy = (CBlock *)&blockcopy; if (!komodo_checkopret(pblockcopy, merkleroot)) { - fprintf(stderr, "failed or missing merkleroot expected.%s != merkleroot.%s\n", komodo_makeopret(pblockcopy, false).ToString().c_str(), merkleroot.ToString().c_str()); - return state.DoS(100, error("CheckBlock: failed or missing merkleroot opret in easy-mined"),REJECT_INVALID, "failed-merkle-opret-in-easy-mined"); + fprintf(stderr, "failed or missing merkleroot expected.%s != merkleroot.%s\n", + komodo_makeopret(pblockcopy, false).ToString().c_str(), merkleroot.ToString().c_str()); + return state.DoS(100, error("CheckBlock: failed or missing merkleroot opret in easy-mined"), + REJECT_INVALID, "failed-merkle-opret-in-easy-mined"); } } } // Check the merkle root. - if (fCheckMerkleRoot) { + if (fCheckMerkleRoot) + { bool mutated; uint256 hashMerkleRoot2 = block.BuildMerkleTree(&mutated); if (block.hashMerkleRoot != hashMerkleRoot2) @@ -5177,8 +5098,8 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C // because we receive the wrong transactions for it. // Size limits - //fprintf(stderr,"%s checkblock %d -> %d vs blocksize.%d\n",ASSETCHAINS_SYMBOL,height,MAX_BLOCK_SIZE(height),(int32_t)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)); - if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE(height) || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE(height)) + if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE(height) + || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE(height)) return state.DoS(100, error("CheckBlock: size limits failed"), REJECT_INVALID, "bad-blk-length"); @@ -5193,44 +5114,48 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C REJECT_INVALID, "bad-cb-multiple"); // Check transactions - CTransaction sTx; - CTransaction *ptx = NULL; if ( ASSETCHAINS_CC != 0 && !fCheckPOW ) return true; - if ( ASSETCHAINS_CC != 0 ) // CC contracts might refer to transactions in the current block, from a CC spend within the same block and out of order + CTransaction sTx; + CTransaction *ptx = nullptr; + + // CC contracts might refer to transactions in the current block, from a + // CC spend within the same block and out of order + if ( ASSETCHAINS_CC != 0 ) { int32_t i,j,rejects=0,lastrejects=0; - //fprintf(stderr,"put block's tx into mempool\n"); - // Copy all non Z-txs in mempool to temporary mempool because there can be tx in local mempool that make the block invalid. + // Copy all non Z-txs in mempool to temporary mempool because there can + // be tx in local mempool that make the block invalid. LOCK2(cs_main,mempool.cs); - //fprintf(stderr, "starting... mempoolsize.%ld\n",mempool.size()); list transactionsToRemove; - BOOST_FOREACH(const CTxMemPoolEntry& e, mempool.mapTx) { + for(const CTxMemPoolEntry& e : mempool.mapTx) + { const CTransaction &tx = e.GetTx(); - const uint256 &hash = tx.GetHash(); - if ( tx.vjoinsplit.empty() && tx.vShieldedSpend.empty()) { + if ( tx.vjoinsplit.empty() && tx.vShieldedSpend.empty()) + { transactionsToRemove.push_back(tx); - tmpmempool.addUnchecked(hash,e,true); + tmpmempool.addUnchecked(tx.GetHash(),e,true); } } - BOOST_FOREACH(const CTransaction& tx, transactionsToRemove) { + for(const CTransaction& tx : transactionsToRemove) { list removed; mempool.remove(tx, removed, false); } - // add all the txs in the block to the empty mempool. - // CC validation shouldnt (cant) depend on the state of mempool! - while ( 1 ) + // add all the txs in the block to the (somewhat) empty mempool. + // CC validation shouldn't (can't) depend on the state of mempool! + while ( true ) { list removed; for (i=0; i all tx in mempool\n",lastrejects); break; } - //fprintf(stderr,"addtomempool ht.%d for CC checking: n.%d rejects.%d last.%d\n",height,(int32_t)block.vtx.size(),rejects,lastrejects); lastrejects = rejects; rejects = 0; } - //fprintf(stderr,"done putting block's tx into mempool\n"); } for (uint32_t i = 0; i < block.vtx.size(); i++) { const CTransaction& tx = block.vtx[i]; - if (!CheckTransaction(tiptime,tx, state, verifier, i, (int32_t)block.vtx.size())) return error("CheckBlock: CheckTransaction failed"); } unsigned int nSigOps = 0; - BOOST_FOREACH(const CTransaction& tx, block.vtx) + for(const CTransaction& tx : block.vtx) { nSigOps += GetLegacySigOpCount(tx); } if (nSigOps > MAX_BLOCK_SIGOPS) return state.DoS(100, error("CheckBlock: out-of-bounds SigOpCount"), REJECT_INVALID, "bad-blk-sigops", true); - if ( fCheckPOW && komodo_check_deposit(height,block,(pindex==0||pindex->pprev==0)?0:pindex->pprev->nTime) < 0 ) + if ( fCheckPOW && komodo_check_deposit(height,block) < 0 ) { - //static uint32_t counter; - //if ( counter++ < 100 && ASSETCHAINS_STAKED == 0 ) - // fprintf(stderr,"check deposit rejection\n"); LogPrintf("CheckBlockHeader komodo_check_deposit error"); return(false); } @@ -5288,13 +5204,12 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C { LOCK2(cs_main,mempool.cs); // here we add back all txs from the temp mempool to the main mempool. - BOOST_FOREACH(const CTxMemPoolEntry& e, tmpmempool.mapTx) + for(const CTxMemPoolEntry& e : tmpmempool.mapTx) { const CTransaction &tx = e.GetTx(); const uint256 &hash = tx.GetHash(); mempool.addUnchecked(hash,e,true); } - //fprintf(stderr, "finished adding back. mempoolsize.%ld\n",mempool.size()); // empty the temp mempool for next time. tmpmempool.clear(); } @@ -5314,7 +5229,7 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta int nHeight = pindexPrev->nHeight+1; // Check proof of work - if ( (ASSETCHAINS_SYMBOL[0] != 0 || nHeight < 235300 || nHeight > 236000) && block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams)) + if ( (!chainName.isKMD() || nHeight < 235300 || nHeight > 236000) && block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams)) { cout << block.nBits << " block.nBits vs. calc " << GetNextWorkRequired(pindexPrev, &block, consensusParams) << " for block #" << nHeight << endl; @@ -5365,7 +5280,7 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta // Don't accept any forks from the main chain prior to last checkpoint CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(chainParams.Checkpoints()); int32_t notarized_height; - if ( nHeight == 1 && chainActive.LastTip() != 0 && chainActive.LastTip()->nHeight > 1 ) + if ( nHeight == 1 && chainActive.Tip() != 0 && chainActive.Tip()->nHeight > 1 ) { CBlockIndex *heightblock = chainActive[nHeight]; if ( heightblock != 0 && heightblock->GetBlockHash() == hash ) @@ -5405,7 +5320,7 @@ bool ContextualCheckBlock(int32_t slowflag,const CBlock& block, CValidationState const int32_t txheight = nHeight == 0 ? komodo_block2height((CBlock *)&block) : nHeight; /* HF22 - check interest validation against pindexPrev->GetMedianTimePast() + 777 */ - if (ASSETCHAINS_SYMBOL[0] == 0 && + if (chainName.isKMD() && consensusParams.nHF22Height != boost::none && txheight > consensusParams.nHF22Height.get() ) { if (pindexPrev) { @@ -5422,10 +5337,10 @@ bool ContextualCheckBlock(int32_t slowflag,const CBlock& block, CValidationState const CTransaction& tx = block.vtx[i]; // Interest validation - if (komodo_validate_interest(tx, txheight, cmptime, 0) < 0) + if (!komodo_validate_interest(tx, txheight, cmptime)) { - fprintf(stderr, "validate intrest failed for txnum.%i tx.%s\n", i, tx.ToString().c_str()); - return error("%s: komodo_validate_interest failed", __func__); + fprintf(stderr, "validate interest failed for txnum.%i tx.%s\n", i, tx.ToString().c_str()); + return state.DoS(0, error("%s: komodo_validate_interest failed", __func__), REJECT_INVALID, "komodo-interest-invalid"); } // Check transaction contextually against consensus rules at block height @@ -5553,7 +5468,18 @@ bool AcceptBlockHeader(int32_t *futureblockp,const CBlockHeader& block, CValidat uint256 Queued_reconsiderblock; -bool AcceptBlock(int32_t *futureblockp,CBlock& block, CValidationState& state, CBlockIndex** ppindex, bool fRequested, CDiskBlockPos* dbp) +/***** + * @brief + * @param futureblockp + * @param block + * @param state + * @param ppindex + * @param fRequested + * @param dbp + * @returns true if block accepted + */ +bool AcceptBlock(int32_t *futureblockp,CBlock& block, CValidationState& state, CBlockIndex** ppindex, + bool fRequested, CDiskBlockPos* dbp) { const CChainParams& chainparams = Params(); AssertLockHeld(cs_main); @@ -5573,7 +5499,6 @@ bool AcceptBlock(int32_t *futureblockp,CBlock& block, CValidationState& state, C *futureblockp = true; return false; } - //fprintf(stderr,"acceptblockheader passed\n"); // Try to process all requested blocks that we don't have, but only // process an unrequested block if it's new and has enough work to // advance our tip, and isn't too many blocks ahead. @@ -5608,23 +5533,11 @@ bool AcceptBlock(int32_t *futureblockp,CBlock& block, CValidationState& state, C if ( saplinght < 0 ) *futureblockp = 1; // the problem is when a future sapling block comes in before we detected saplinght - if ( saplinght > 0 && (tmpptr= chainActive.LastTip()) != 0 ) + if ( saplinght > 0 && (tmpptr= chainActive.Tip()) != 0 ) { fprintf(stderr,"saplinght.%d tipht.%d blockht.%d cmp.%d\n",saplinght,(int32_t)tmpptr->nHeight,pindex->nHeight,pindex->nHeight < 0 || (pindex->nHeight >= saplinght && pindex->nHeight < saplinght+50000) || (tmpptr->nHeight > saplinght-720 && tmpptr->nHeight < saplinght+720)); if ( pindex->nHeight < 0 || (pindex->nHeight >= saplinght && pindex->nHeight < saplinght+50000) || (tmpptr->nHeight > saplinght-720 && tmpptr->nHeight < saplinght+720) ) *futureblockp = 1; - if ( ASSETCHAINS_CBOPRET != 0 ) - { - CValidationState tmpstate; CBlockIndex *tmpindex; int32_t ht,longest; - ht = (int32_t)pindex->nHeight; - longest = komodo_longestchain(); - if ( (longest == 0 || ht < longest-6) && (tmpindex=komodo_chainactive(ht)) != 0 ) - { - fprintf(stderr,"reconsider height.%d, longest.%d\n",(int32_t)ht,longest); - if ( Queued_reconsiderblock == zeroid ) - Queued_reconsiderblock = pindex->GetBlockHash(); - } - } } if ( *futureblockp == 0 ) { @@ -5685,8 +5598,6 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned return (nFound >= nRequired); } -void komodo_currentheight_set(int32_t height); - CBlockIndex *komodo_ensure(CBlock *pblock, uint256 hash) { CBlockIndex *pindex = 0; @@ -5767,28 +5678,43 @@ CBlockIndex *oldkomodo_ensure(CBlock *pblock, uint256 hash) return(pindex); } -bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp) +/***** + * @brief Process a new block + * @note can come from the network or locally mined + * @note This only returns after the best known valid + * block is made active. Note that it does not, however, guarantee that the + * specific block passed to it has been checked for validity! + * @param from_miner no longer used + * @param height the new height + * @param[out] state the results + * @param pfrom the node that produced the block (nullptr for local) + * @param pblock the block to process + * @param fForceProcessing Process this block even if unrequested; used for non-network block sources and whitelisted peers. + * @param[out] dbp set to position on disk for block + * @returns true on success + */ +bool ProcessNewBlock(bool from_miner, int32_t height, CValidationState &state, CNode* pfrom, + CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp) { // Preliminary checks - bool checked; uint256 hash; int32_t futureblock=0; + bool checked; + int32_t futureblock=0; auto verifier = libzcash::ProofVerifier::Disabled(); - hash = pblock->GetHash(); - //fprintf(stderr,"ProcessBlock %d\n",(int32_t)chainActive.LastTip()->nHeight); + uint256 hash = pblock->GetHash(); { LOCK(cs_main); - if ( chainActive.LastTip() != 0 ) - komodo_currentheight_set(chainActive.LastTip()->nHeight); + if ( chainActive.Tip() != 0 ) + komodo_currentheight_set(chainActive.Tip()->nHeight); checked = CheckBlock(&futureblock,height!=0?height:komodo_block2height(pblock),0,*pblock, state, verifier,0); bool fRequested = MarkBlockAsReceived(hash); fRequested |= fForceProcessing; - if ( checked != 0 && komodo_checkPOW(0,0,pblock,height) < 0 ) //from_miner && ASSETCHAINS_STAKED == 0 + if ( checked && komodo_checkPOW(0,0,pblock,height) < 0 ) { - checked = 0; - //fprintf(stderr,"passed checkblock but failed checkPOW.%d\n",from_miner && ASSETCHAINS_STAKED == 0); + checked = false; } if (!checked && futureblock == 0) { - if ( pfrom != 0 ) + if ( pfrom != nullptr ) { Misbehaving(pfrom->GetId(), 1); } @@ -5797,27 +5723,20 @@ bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNo // Store to disk CBlockIndex *pindex = NULL; - bool ret = AcceptBlock(&futureblock,*pblock, state, &pindex, fRequested, dbp); + bool accepted = AcceptBlock(&futureblock,*pblock, state, &pindex, fRequested, dbp); if (pindex && pfrom) { mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId(); } CheckBlockIndex(); - if (!ret && futureblock == 0) + if (!accepted && futureblock == 0) { - /*if ( ASSETCHAINS_SYMBOL[0] == 0 ) - { - //fprintf(stderr,"request headers from failed process block peer\n"); - pfrom->PushMessage("getheaders", chainActive.GetLocator(chainActive.LastTip()), uint256()); - }*/ komodo_longestchain(); return error("%s: AcceptBlock FAILED", __func__); } - //else fprintf(stderr,"added block %s %p\n",pindex->GetBlockHash().ToString().c_str(),pindex->pprev); } if (futureblock == 0 && !ActivateBestChain(false, state, pblock)) return error("%s: ActivateBestChain failed", __func__); - //fprintf(stderr,"finished ProcessBlock %d\n",(int32_t)chainActive.LastTip()->nHeight); return true; } @@ -5836,23 +5755,19 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex // NOTE: CheckBlockHeader is called by CheckBlock if (!ContextualCheckBlockHeader(block, state, pindexPrev)) { - //fprintf(stderr,"TestBlockValidity failure A checkPOW.%d\n",fCheckPOW); return false; } int32_t futureblock; if (!CheckBlock(&futureblock,indexDummy.nHeight,0,block, state, verifier, fCheckPOW, fCheckMerkleRoot)) { - //fprintf(stderr,"TestBlockValidity failure B checkPOW.%d\n",fCheckPOW); return false; } if (!ContextualCheckBlock(0,block, state, pindexPrev)) { - //fprintf(stderr,"TestBlockValidity failure C checkPOW.%d\n",fCheckPOW); return false; } if (!ConnectBlock(block, state, &indexDummy, viewNew, true,fCheckPOW)) { - //fprintf(stderr,"TestBlockValidity failure D checkPOW.%d\n",fCheckPOW); return false; } assert(state.IsValid()); @@ -5886,7 +5801,7 @@ bool PruneOneBlockFile(bool tempfile, const int fileNumber) CBlockIndex* pindex = it->second; if (pindex && pindex->nFile == fileNumber) { - if ( tempfile && (pindex->nStatus & BLOCK_IN_TMPFILE != 0) ) + if ( tempfile && ( (pindex->nStatus & BLOCK_IN_TMPFILE) != 0) ) { if ( chainActive.Contains(pindex) ) { @@ -6007,30 +5922,35 @@ bool CheckDiskSpace(uint64_t nAdditionalBytes) /**** * Open a file * @param pos where to position for the next read - * @param prefix the type of file (i.e. "blk", "rev", etc. + * @param prefix the type of file ("blk" or "rev") * @param fReadOnly open in read only mode - * @returns the file pointer or NULL on error + * @returns the file pointer with the position set to pos.nPos, or NULL on error */ FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly) { - static int32_t didinit[256]; + static int32_t didinit[256]; // keeps track of which files have been initialized if (pos.IsNull()) return NULL; boost::filesystem::path path = GetBlockPosFilename(pos, prefix); - boost::filesystem::create_directories(path.parent_path()); + boost::filesystem::create_directories(path.parent_path()); // create directory if necessary FILE* file = fopen(path.string().c_str(), "rb+"); // open existing file for reading and writing - if (!file && !fReadOnly) + if (!file && !fReadOnly) // problem. Try opening read only if that is what was requested file = fopen(path.string().c_str(), "wb+"); // create an empty file for reading and writing if (!file) { LogPrintf("Unable to open file %s\n", path.string()); return NULL; } - if ( pos.nFile < sizeof(didinit)/sizeof(*didinit) && didinit[pos.nFile] == 0 && strcmp(prefix,(char *)"blk") == 0 ) + // the file was successfully opened + if ( pos.nFile < sizeof(didinit)/sizeof(*didinit) // if pos.nFile doesn't go beyond our array + && didinit[pos.nFile] == 0 // we have not initialized this file + && strcmp(prefix,(char *)"blk") == 0 ) // we are attempting to read a block file { komodo_prefetch(file); didinit[pos.nFile] = 1; } - if (pos.nPos) { + + if (pos.nPos) // it has been asked to move to a specific location within the file + { if (fseek(file, pos.nPos, SEEK_SET)) { LogPrintf("Unable to seek to position %u of %s\n", pos.nPos, path.string()); fclose(file); @@ -6092,30 +6012,33 @@ CBlockIndex * InsertBlockIndex(uint256 hash) return pindexNew; } -//void komodo_pindex_init(CBlockIndex *pindex,int32_t height); - +/**** + * Load the block index database + * @returns true on success + */ bool static LoadBlockIndexDB() { const CChainParams& chainparams = Params(); LogPrintf("%s: start loading guts\n", __func__); - if (!pblocktree->LoadBlockIndexGuts()) - return false; + { + LOCK(cs_main); + if (!pblocktree->LoadBlockIndexGuts()) + return false; + } LogPrintf("%s: loaded guts\n", __func__); boost::this_thread::interruption_point(); // Calculate nChainWork vector > vSortedByHeight; vSortedByHeight.reserve(mapBlockIndex.size()); - BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) + for(const auto& item : mapBlockIndex) { CBlockIndex* pindex = item.second; vSortedByHeight.push_back(make_pair(pindex->nHeight, pindex)); - //komodo_pindex_init(pindex,(int32_t)pindex->nHeight); } - //fprintf(stderr,"load blockindexDB paired %u\n",(uint32_t)time(NULL)); sort(vSortedByHeight.begin(), vSortedByHeight.end()); - //fprintf(stderr,"load blockindexDB sorted %u\n",(uint32_t)time(NULL)); - BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight) + + for(const auto& item : vSortedByHeight) { CBlockIndex* pindex = item.second; pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + GetBlockProof(*pindex); @@ -6168,9 +6091,7 @@ bool static LoadBlockIndexDB() pindex->BuildSkip(); if (pindex->IsValid(BLOCK_VALID_TREE) && (pindexBestHeader == NULL || CBlockIndexWorkComparator()(pindexBestHeader, pindex))) pindexBestHeader = pindex; - //komodo_pindex_init(pindex,(int32_t)pindex->nHeight); } - //fprintf(stderr,"load blockindexDB chained %u\n",(uint32_t)time(NULL)); // Load block file info pblocktree->ReadLastBlockFile(nLastBlockFile); @@ -6193,14 +6114,13 @@ bool static LoadBlockIndexDB() // Check presence of blk files LogPrintf("Checking all blk files are present...\n"); set setBlkDataFiles; - BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) + for(const auto& item : mapBlockIndex) { CBlockIndex* pindex = item.second; if (pindex->nStatus & BLOCK_HAVE_DATA) { setBlkDataFiles.insert(pindex->nFile); } } - //fprintf(stderr,"load blockindexDB %u\n",(uint32_t)time(NULL)); for (std::set::iterator it = setBlkDataFiles.begin(); it != setBlkDataFiles.end(); it++) { CDiskBlockPos pos(*it, 0); @@ -6235,7 +6155,7 @@ bool static LoadBlockIndexDB() LogPrintf("%s: spent index %s\n", __func__, fSpentIndex ? "enabled" : "disabled"); // Fill in-memory data - BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) + for(const auto& item : mapBlockIndex) { CBlockIndex* pindex = item.second; // - This relationship will always be true even if pprev has multiple @@ -6246,7 +6166,6 @@ bool static LoadBlockIndexDB() if (pindex->pprev) { pindex->pprev->hashFinalSproutRoot = pindex->hashSproutAnchor; } - //komodo_pindex_init(pindex,(int32_t)pindex->nHeight); } // Load pointer to end of best chain @@ -6254,6 +6173,7 @@ bool static LoadBlockIndexDB() if (it == mapBlockIndex.end()) return true; + LOCK(cs_main); chainActive.SetTip(it->second); // Set hashFinalSproutRoot for the end of best chain @@ -6262,8 +6182,8 @@ bool static LoadBlockIndexDB() PruneBlockIndexCandidates(); double progress; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) { - progress = Checkpoints::GuessVerificationProgress(chainparams.Checkpoints(), chainActive.LastTip()); + if ( chainName.isKMD() ) { + progress = Checkpoints::GuessVerificationProgress(chainparams.Checkpoints(), chainActive.Tip()); } else { int32_t longestchain = komodo_longestchain(); // TODO: komodo_longestchain does not have the data it needs at the time LoadBlockIndexDB @@ -6271,13 +6191,13 @@ bool static LoadBlockIndexDB() progress = (longestchain > 0 ) ? (double) chainActive.Height() / longestchain : 0.5; } LogPrintf("%s: hashBestChain=%s height=%d date=%s progress=%f\n", __func__, - chainActive.LastTip()->GetBlockHash().ToString(), chainActive.Height(), - DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.LastTip()->GetBlockTime()), + chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), + DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()), progress); EnforceNodeDeprecation(chainActive.Height(), true); CBlockIndex *pindex; - if ( (pindex= chainActive.LastTip()) != 0 ) + if ( (pindex= chainActive.Tip()) != 0 ) { if ( ASSETCHAINS_SAPLING <= 0 ) { @@ -6381,7 +6301,14 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth return true; } -bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches) +/** + * When there are blocks in the active chain with missing data (e.g. if the + * activation height and branch ID of a particular upgrade have been altered), + * rewind the chainstate and remove them from the block index. + * @param params the chain parameters + * @returns true on success + */ +bool RewindBlockIndex(const CChainParams& params) { LOCK(cs_main); @@ -6526,6 +6453,9 @@ bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches) return true; } +/*** + * Clear all values related to the block index + */ void UnloadBlockIndex() { LOCK(cs_main); @@ -6551,32 +6481,38 @@ void UnloadBlockIndex() mapNodeState.clear(); recentRejects.reset(NULL); - BOOST_FOREACH(BlockMap::value_type& entry, mapBlockIndex) { + for(BlockMap::value_type& entry : mapBlockIndex) + { delete entry.second; } mapBlockIndex.clear(); fHavePruned = false; } -/*** - * Load block index +/****** + * @brief Load the block tree and coins database from disk + * @param reindex true if we will be reindexing (will skip the load if we are) * @returns true on success */ -bool LoadBlockIndex() +bool LoadBlockIndex(bool reindex) { // Load block index from databases - KOMODO_LOADINGBLOCKS = 1; - if (!fReindex && !LoadBlockIndexDB()) + KOMODO_LOADINGBLOCKS = true; + if (!reindex && !LoadBlockIndexDB()) { - KOMODO_LOADINGBLOCKS = 0; + KOMODO_LOADINGBLOCKS = false; return false; } - fprintf(stderr,"finished loading blocks %s\n",ASSETCHAINS_SYMBOL); + fprintf(stderr,"finished loading blocks %s\n",chainName.symbol().c_str()); return true; } - -bool InitBlockIndex() { +/** + * Initialize a new block tree database + block data on disk + * @returns true on success + */ +bool InitBlockIndex() +{ const CChainParams& chainparams = Params(); LOCK(cs_main); tmpBlockFiles.clear(); @@ -6637,8 +6573,6 @@ bool InitBlockIndex() { return true; } - - bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) { const CChainParams& chainparams = Params(); @@ -6880,7 +6814,11 @@ void static CheckBlockIndex() } } } + // try { // assert(pindex->GetBlockHash() == pindex->GetBlockHeader().GetHash()); // Perhaps too slow + // } catch (const runtime_error&) { + // assert(!"Failed to read index entry"); + // } // End: actual consistency checks. // Try descending into the first subnode. @@ -7003,7 +6941,7 @@ std::string GetWarnings(const std::string& strFor) // -bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main) +bool static AlreadyHave(const CInv& inv) REQUIRES(cs_main) { switch (inv.type) { @@ -7154,9 +7092,6 @@ void static ProcessGetData(CNode* pfrom) } } - // Track requests for our stuff. - GetMainSignals().Inventory(inv.hash); - if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK) break; } @@ -7182,6 +7117,8 @@ void static ProcessGetData(CNode* pfrom) #include "komodo_nSPV_superlite.h" // nSPV superlite client, issuing requests and handling nSPV responses #include "komodo_nSPV_wallet.h" // nSPV_send and support functions, really all the rest is to support this +void komodo_netevent(std::vector payload); + bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived) { int32_t nProtocolVersion; @@ -7214,7 +7151,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, uint64_t nNonce = 1; int nVersion; // use temporary for version, don't set version number until validated as connected int minVersion = MIN_PEER_PROTO_VERSION; - if ( is_STAKED(ASSETCHAINS_SYMBOL) != 0 ) + if ( is_STAKED(chainName.symbol()) != 0 ) minVersion = STAKEDMIN_PEER_PROTO_VERSION; vRecv >> nVersion >> pfrom->nServices >> nTime >> addrMe; if (nVersion == 10300) @@ -7306,6 +7243,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, { pfrom->PushMessage("getaddr"); pfrom->fGetAddr = true; + // When requesting a getaddr, accept an additional MAX_ADDR_TO_SEND addresses in response + // (bypassing the MAX_ADDR_PROCESSING_TOKEN_BUCKET limit). + pfrom->m_addr_token_bucket += MAX_ADDR_TO_SEND; } addrman.Good(pfrom->addr); } else { @@ -7383,12 +7323,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, else if (pfrom->nVersion < chainparams.GetConsensus().vUpgrades[ CurrentEpoch(GetHeight(), chainparams.GetConsensus())].nProtocolVersion) { - LogPrintf("peer=%d using obsolete version %i vs %d; disconnecting\n", pfrom->id, pfrom->nVersion,(int32_t)chainparams.GetConsensus().vUpgrades[ - CurrentEpoch(GetHeight(), chainparams.GetConsensus())].nProtocolVersion); + LogPrintf("peer=%d using obsolete version %i vs %d; disconnecting\n", + pfrom->id, pfrom->nVersion,(int32_t)chainparams.GetConsensus().vUpgrades[ + CurrentEpoch(GetHeight(), chainparams.GetConsensus())].nProtocolVersion); pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE, - strprintf("Version must be %d or greater", - chainparams.GetConsensus().vUpgrades[ - CurrentEpoch(GetHeight(), chainparams.GetConsensus())].nProtocolVersion)); + strprintf("Version must be %d or greater", chainparams.GetConsensus().vUpgrades[ + CurrentEpoch(GetHeight(), chainparams.GetConsensus())].nProtocolVersion)); pfrom->fDisconnect = true; return false; } @@ -7412,13 +7352,39 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, vector vAddrOk; int64_t nNow = GetTime(); int64_t nSince = nNow - 10 * 60; + + // Update/increment addr rate limiting bucket. + const int64_t current_time = GetTimeMicros(); + if (pfrom->m_addr_token_bucket < MAX_ADDR_PROCESSING_TOKEN_BUCKET) { + // Don't increment bucket if it's already full + const auto time_diff = std::max(current_time - pfrom->m_addr_token_timestamp, (int64_t) 0); + const double increment = (time_diff / 1000000) * MAX_ADDR_RATE_PER_SECOND; + pfrom->m_addr_token_bucket = std::min(pfrom->m_addr_token_bucket + increment, MAX_ADDR_PROCESSING_TOKEN_BUCKET); + } + pfrom->m_addr_token_timestamp = current_time; + + uint64_t num_proc = 0; /* nProcessedAddrs */ + uint64_t num_rate_limit = 0; /* nRatelimitedAddrs */ + random_shuffle(vAddr.begin(), vAddr.end(), GetRandInt); + BOOST_FOREACH(CAddress& addr, vAddr) { boost::this_thread::interruption_point(); + // Apply rate limiting if the address is not whitelisted + if (pfrom->m_addr_token_bucket < 1.0) { + if (!pfrom->IsWhitelistedRange(addr)) { + ++num_rate_limit; + continue; + } + } else { + pfrom->m_addr_token_bucket -= 1.0; + } + if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60) addr.nTime = nNow - 5 * 24 * 60 * 60; pfrom->AddAddressKnown(addr); + ++num_proc; bool fReachable = IsReachable(addr); if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable()) { @@ -7452,8 +7418,20 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Do not store addresses outside our network if (fReachable) vAddrOk.push_back(addr); + pfrom->m_addr_processed += num_proc; + pfrom->m_addr_rate_limited += num_rate_limit; } + + LogPrint("net", "ProcessMessage: Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d%s\n", + vAddr.size(), + num_proc, + num_rate_limit, + pfrom->GetId(), + fLogIPs ? ", peeraddr=" + pfrom->addr.ToString() : "" + ); + addrman.Add(vAddrOk, pfrom->addr, 2 * 60 * 60); + if (vAddr.size() < 1000) pfrom->fGetAddr = false; if (pfrom->fOneShot) @@ -7625,9 +7603,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } } - // Track requests for our stuff - GetMainSignals().Inventory(inv.hash); - if (pfrom->nSendSize > (SendBufferSize() * 2)) { Misbehaving(pfrom->GetId(), 50); return error("send buffer size() = %u", pfrom->nSendSize); @@ -7704,7 +7679,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, LOCK(cs_main); - if (chainActive.LastTip() != 0 && chainActive.LastTip()->nHeight > 100000 && IsInitialBlockDownload()) + if (chainActive.Tip() != 0 && chainActive.Tip()->nHeight > 100000 && IsInitialBlockDownload()) { //fprintf(stderr,"dont process getheaders during initial download\n"); return true; @@ -7913,7 +7888,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // only KMD have checkpoints in sources, so, using IsInitialBlockDownload() here is // not applicable for assetchains (!) - if (GetBoolArg("-fixibd", false) && ASSETCHAINS_SYMBOL[0] == 0 && IsInitialBlockDownload()) { + if (GetBoolArg("-fixibd", false) && chainName.isKMD() && IsInitialBlockDownload()) { /** * This is experimental feature avaliable only for KMD during initial block download running with diff --git a/src/main.h b/src/main.h index 9ba9303a65d..3444058259e 100644 --- a/src/main.h +++ b/src/main.h @@ -66,7 +66,6 @@ class PrecomputedTransactionData; struct CNodeStateStats; #define DEFAULT_MEMPOOL_EXPIRY 1 -#define _COINBASE_MATURITY 100 /** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/ static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 2000000;//MAX_BLOCK_SIZE; @@ -78,7 +77,7 @@ static const bool DEFAULT_ALERTS = true; /** Minimum alert priority for enabling safe mode. */ static const int ALERT_PRIORITY_SAFE_MODE = 4000; /** Maximum reorg length we will accept before we shut down and alert the user. */ -static unsigned int MAX_REORG_LENGTH = _COINBASE_MATURITY - 1; +static unsigned int MAX_REORG_LENGTH = 100 - 1; // based on COINBASE_MATURITY /** Maximum number of signature check operations in an IsStandard() P2SH script */ static const unsigned int MAX_P2SH_SIGOPS = 15; /** The maximum number of sigops we're willing to relay/mine in a single tx */ @@ -202,17 +201,20 @@ void RegisterNodeSignals(CNodeSignals& nodeSignals); /** Unregister a network node */ void UnregisterNodeSignals(CNodeSignals& nodeSignals); -/** - * Process an incoming block. This only returns after the best known valid +/***** + * @brief Process a new block + * @note can come from the network or locally mined + * @note This only returns after the best known valid * block is made active. Note that it does not, however, guarantee that the * specific block passed to it has been checked for validity! - * - * @param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganisation; or it may be set to an Invalid state if pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface (see validationinterface.h) - this will have its BlockChecked method called whenever *any* block completes validation. - * @param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid. - * @param[in] pblock The block we want to process. - * @param[in] fForceProcessing Process this block even if unrequested; used for non-network block sources and whitelisted peers. - * @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location. - * @return True if state.IsValid() + * @param from_miner no longer used + * @param height the new height + * @param[out] state the results + * @param pfrom the node that produced the block (nullptr for local) + * @param pblock the block to process + * @param fForceProcessing Process this block even if unrequested; used for non-network block sources and whitelisted peers. + * @param[out] dbp set to position on disk for block + * @returns true on success */ bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp); /** Check whether enough disk space is available for an incoming block */ @@ -225,11 +227,20 @@ FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false); boost::filesystem::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix); /** Import blocks from an external file */ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp = NULL); -/** Initialize a new block tree database + block data on disk */ +/** + * Initialize a new block tree database + block data on disk + * @returns true on success + */ bool InitBlockIndex(); -/** Load the block tree and coins database from disk */ -bool LoadBlockIndex(); -/** Unload database information */ +/****** + * @brief Load the block tree and coins database from disk + * @param reindex true if we will be reindexing (will skip the load if we are) + * @returns true on success + */ +bool LoadBlockIndex(bool reindex); +/*** + * Clear all values related to the block index + */ void UnloadBlockIndex(); /** Process protocol messages received from a given node */ bool ProcessMessages(CNode* pfrom); @@ -252,7 +263,14 @@ bool IsInitialBlockDownload(); int IsNotInSync(); /** Format a string that describes several potential problems detected by the core */ std::string GetWarnings(const std::string& strFor); -/** Retrieve a transaction (from memory pool, or from disk, if possible) */ +/** + * @brief Find a transaction (uses locks) + * @param[in] hash the transaction to look for + * @param[out] txOut the transaction found + * @param[out] hashBlock the block where the transaction was found (all zeros if found in mempool) + * @param[in] fAllowSlow true to continue searching even if there are no transaction indexes + * @returns true if found + */ bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, bool fAllowSlow = false); /** Find the best known block, and make it the tip of the block chain */ bool ActivateBestChain(bool fSkipdpow, CValidationState &state, CBlock *pblock = NULL); @@ -291,7 +309,17 @@ void FlushStateToDisk(); /** Prune block files and flush state to disk. */ void PruneAndFlush(); -/** (try to) add transaction to memory pool **/ +/** + * @brief Try to add transaction to memory pool + * @param pool + * @param state + * @param tx + * @param fLimitFree + * @param pfMissingInputs + * @param fRejectAbsurdFee + * @param dosLevel + * @returns true on success + */ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree, bool* pfMissingInputs, bool fRejectAbsurdFee=false, int dosLevel=-1); @@ -746,6 +774,9 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime); /** * Check if transaction is expired and can be included in a block with the * specified height. Consensus critical. + * @param tx the transaction + * @param nBlockHeight the current block height + * @returns true if transaction is expired (mainly tx.expiryHeight > nBlockHeight) */ bool IsExpiredTx(const CTransaction &tx, int nBlockHeight); @@ -820,7 +851,16 @@ bool PruneOneBlockFile(bool tempfile, const int fileNumber); * of problems. Note that in any case, coins may be modified. */ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool* pfClean = NULL); -/** Apply the effects of this block (with given index) on the UTXO set represented by coins */ +/***** + * @brief Apply the effects of this block (with given index) on the UTXO set represented by coins + * @param block the block to add + * @param state the result status + * @param pindex where to insert the block + * @param view the chain + * @param fJustCheck do not actually modify, only do checks + * @param fcheckPOW + * @returns true on success + */ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false,bool fCheckPOW = false); /** Context-independent validity checks */ @@ -846,17 +886,14 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex bool AcceptBlock(int32_t *futureblockp,CBlock& block, CValidationState& state, CBlockIndex **pindex, bool fRequested, CDiskBlockPos* dbp); bool AcceptBlockHeader(int32_t *futureblockp,const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL); - - /** * When there are blocks in the active chain with missing data (e.g. if the * activation height and branch ID of a particular upgrade have been altered), * rewind the chainstate and remove them from the block index. - * - * clearWitnessCaches is an output parameter that will be set to true iff - * witness caches should be cleared in order to handle an intended long rewind. + * @param params the chain parameters + * @returns true on success */ -bool RewindBlockIndex(const CChainParams& params, bool& clearWitnessCaches); +bool RewindBlockIndex(const CChainParams& params); class CBlockFileInfo { @@ -930,7 +967,11 @@ bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex); bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex); /** The currently-connected chain of blocks (protected by cs_main). */ +#ifdef DEBUG_LOCKORDER +extern MultithreadedCChain chainActive; +#else extern CChain chainActive; +#endif /** Global variable that points to the active CCoinsView (protected by cs_main) */ extern CCoinsViewCache *pcoinsTip; @@ -950,4 +991,7 @@ uint64_t CalculateCurrentUsage(); /** Return a CMutableTransaction with contextual default values based on set of consensus rules at height */ CMutableTransaction CreateNewContextualCMutableTransaction(const Consensus::Params& consensusParams, int nHeight); +int32_t komodo_isnotaryvout(char *coinaddr,uint32_t tiptime); // from ac_private chains only +bool komodo_dailysnapshot(int32_t height); + #endif // BITCOIN_MAIN_H diff --git a/src/metrics.cpp b/src/metrics.cpp index 7ec6298b03e..3d057b6e8a3 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -27,6 +27,8 @@ #include "utiltime.h" #include "utilmoneystr.h" #include "utilstrencodings.h" +#include "komodo_utils.h" +#include "komodo_globals.h" #include #include @@ -40,7 +42,6 @@ #include #include "komodo_defs.h" -int64_t komodo_block_unlocktime(uint32_t nHeight); void AtomicTimer::start() { @@ -240,7 +241,7 @@ int printStats(bool mining) { LOCK2(cs_main, cs_vNodes); height = chainActive.Height(); - tipmediantime = chainActive.LastTip()->GetMedianTimePast(); + tipmediantime = chainActive.Tip()->GetMedianTimePast(); connections = vNodes.size(); netsolps = GetNetworkHashPS(120, -1); } @@ -365,7 +366,7 @@ int printMetrics(size_t cols, bool mining) subsidy -= subsidy/5; } - if ((std::max(0, COINBASE_MATURITY - (tipHeight - height)) > 0) || + if ((std::max( 0U, Params().CoinbaseMaturity() - (tipHeight - height)) > 0) || (tipHeight < komodo_block_unlocktime(height) && subsidy >= ASSETCHAINS_TIMELOCKGTE)) { immature += subsidy; } else { diff --git a/src/miner.cpp b/src/miner.cpp index 8a811b4fa25..09b931eca03 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -20,6 +20,12 @@ #include "pubkey.h" #include "miner.h" +#include "komodo_utils.h" +#include "komodo_globals.h" +#include "komodo_bitcoind.h" +#include "komodo_gateway.h" +#include "komodo_defs.h" +#include "cc/CCinclude.h" #ifdef ENABLE_MINING #include "pow/tromp/equi_miner.h" #endif @@ -58,6 +64,8 @@ #include "notaries_staked.h" #include "komodo_notary.h" +#include "komodo_bitcoind.h" +#include "komodo_extern_globals.h" #include #include @@ -135,56 +143,45 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams); } } -#include "komodo_defs.h" -#include "cc/CCinclude.h" extern CCriticalSection cs_metrics; -void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len); - uint32_t Mining_start,Mining_height; int32_t My_notaryid = -1; -int32_t komodo_pax_opreturn(int32_t height,uint8_t *opret,int32_t maxsize); -int32_t komodo_baseid(char *origbase); -int32_t komodo_longestchain(); -int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag); -int64_t komodo_block_unlocktime(uint32_t nHeight); -uint64_t komodo_commission(const CBlock *block,int32_t height); -int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig, uint256 merkleroot); -uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHeight, bool fNew, CScript scriptPubKey); -int32_t komodo_newStakerActive(int32_t height, uint32_t timestamp); -int32_t komodo_notaryvin(CMutableTransaction &txNew, uint8_t *notarypub33, const CScript &opretIn, uint32_t nLockTimeIn); -int32_t komodo_is_notarytx(const CTransaction& tx); -uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector &NotarisationNotaries, uint32_t timestamp, int32_t height, uint8_t *script, int32_t len); -int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); -int32_t komodo_getnotarizedheight(uint32_t timestamp,int32_t height, uint8_t *script, int32_t len); -CScript komodo_mineropret(int32_t nHeight); -bool komodo_appendACscriptpub(); -CScript komodo_makeopret(CBlock *pblock, bool fNew); int32_t komodo_waituntilelegible(uint32_t blocktime, int32_t stakeHeight, uint32_t delay) { int64_t adjustedtime = (int64_t)GetTime(); while ( (int64_t)blocktime-ASSETCHAINS_STAKED_BLOCK_FUTURE_MAX > adjustedtime ) { + boost::this_thread::interruption_point(); // allow to interrupt int64_t secToElegible = (int64_t)blocktime-ASSETCHAINS_STAKED_BLOCK_FUTURE_MAX-adjustedtime; if ( delay <= ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF && secToElegible <= ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF ) break; if ( (rand() % 100) < 2-(secToElegible>ASSETCHAINS_STAKED_BLOCK_FUTURE_MAX) ) - fprintf(stderr, "[%s:%i] %llds until elegible...\n", ASSETCHAINS_SYMBOL, stakeHeight, (long long)secToElegible); - if ( chainActive.LastTip()->nHeight >= stakeHeight ) + fprintf(stderr, "[%s:%i] %llds until elegible...\n", chainName.symbol().c_str(), stakeHeight, (long long)secToElegible); + if ( chainActive.Tip()->nHeight >= stakeHeight ) { - fprintf(stderr, "[%s:%i] Chain advanced, reset staking loop.\n", ASSETCHAINS_SYMBOL, stakeHeight); + fprintf(stderr, "[%s:%i] Chain advanced, reset staking loop.\n", chainName.symbol().c_str(), stakeHeight); return(0); } if( !GetBoolArg("-gen",false) ) return(0); - sleep(1); + //sleep(1); + boost::this_thread::sleep_for(boost::chrono::seconds(1)); // allow to interrupt adjustedtime = (int64_t)GetTime(); } return(1); } -CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32_t gpucount, bool isStake) +/***** + * @breif Generate a new block based on mempool txs, without valid proof-of-work + * @param _pk the public key + * @param _scriptPubKeyIn the script for the public key + * @param gpucount assists in calculating the block's nTime + * @param isStake + * @returns the block template + */ +CBlockTemplate* CreateNewBlock(const CPubKey _pk, const CScript& _scriptPubKeyIn, int32_t gpucount, bool isStake) { CScript scriptPubKeyIn(_scriptPubKeyIn); @@ -201,18 +198,23 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 } } else pk = _pk; - uint64_t deposits; int32_t isrealtime,kmdheight; uint32_t blocktime; const CChainParams& chainparams = Params(); - bool fNotarisationBlock = false; std::vector NotarisationNotaries; + uint32_t blocktime; + const CChainParams& chainparams = Params(); + bool fNotarisationBlock = false; + std::vector NotarisationNotaries; + // TODO: remove + //uint64_t deposits; int32_t kmdheight; uint32_t blocktime; const CChainParams& chainparams = Params(); + //bool fNotarisationBlock = false; std::vector NotarisationNotaries; - //fprintf(stderr,"create new block\n"); // Create new block if ( gpucount < 0 ) gpucount = KOMODO_MAXGPUCOUNT; + std::unique_ptr pblocktemplate(new CBlockTemplate()); - if(!pblocktemplate.get()) + if(pblocktemplate == nullptr) { fprintf(stderr,"pblocktemplate.get() failure\n"); - return NULL; + return nullptr; } CBlock *pblock = &pblocktemplate->block; // pointer for convenience // -regtest only: allow overriding block.nVersion with @@ -225,10 +227,15 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 pblocktemplate->vTxFees.push_back(-1); // updated at end pblocktemplate->vTxSigOps.push_back(-1); // updated at end + CBlockIndex *tipindex = nullptr; + { + LOCK(cs_main); + tipindex = chainActive.Tip(); + } // Largest block you're willing to create: - unsigned int nBlockMaxSize = GetArg("-blockmaxsize", MAX_BLOCK_SIZE(chainActive.LastTip()->nHeight+1)); + unsigned int nBlockMaxSize = GetArg("-blockmaxsize", MAX_BLOCK_SIZE(tipindex->nHeight+1)); // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity: - nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE(chainActive.LastTip()->nHeight+1)-1000), nBlockMaxSize)); + nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE(tipindex->nHeight+1)-1000), nBlockMaxSize)); // How much of the block should be dedicated to high-priority transactions, // included regardless of the fees they pay @@ -251,7 +258,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 boost::this_thread::disable_interruption(); ENTER_CRITICAL_SECTION(cs_main); ENTER_CRITICAL_SECTION(mempool.cs); - pindexPrev = chainActive.LastTip(); + pindexPrev = chainActive.Tip(); const int nHeight = pindexPrev->nHeight + 1; const Consensus::Params &consensusParams = chainparams.GetConsensus(); uint32_t consensusBranchId = CurrentEpochBranchId(nHeight, consensusParams); @@ -264,11 +271,11 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 { // too fast or stuck, this addresses the too fast issue, while moving // forward as quickly as possible - for (int i; i < 100; i++) + for (int i = 0; i < 100; i++) { proposedTime = GetTime(); if (proposedTime == nMedianTimePast) - MilliSleep(10); + MilliSleep(10); // allow to interrupt } } pblock->nTime = GetTime(); @@ -281,7 +288,6 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 } CCoinsViewCache view(pcoinsTip); - uint32_t expired; uint64_t commission; SaplingMerkleTree sapling_tree; assert(view.GetSaplingAnchorAt(view.GetBestAnchor(SAPLING), sapling_tree)); @@ -309,7 +315,6 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, nLockTimeCutoff) || IsExpiredTx(tx, nHeight)) { - //fprintf(stderr,"coinbase.%d finaltx.%d expired.%d\n",tx.IsCoinBase(),IsFinalTx(tx, nHeight, nLockTimeCutoff),IsExpiredTx(tx, nHeight)); continue; } txvalue = tx.GetValueOut(); @@ -319,7 +324,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 /* HF22 - check interest validation against pindexPrev->GetMedianTimePast() + 777 */ uint32_t cmptime = (uint32_t)pblock->nTime; - if (ASSETCHAINS_SYMBOL[0] == 0 && + if (chainName.isKMD() && consensusParams.nHF22Height != boost::none && nHeight > consensusParams.nHF22Height.get() ) { uint32_t cmptime_old = cmptime; @@ -328,7 +333,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 LogPrint("hfnet","%s[%d]: ht.%ld\n", __func__, __LINE__, nHeight); } - if (ASSETCHAINS_SYMBOL[0] == 0 && komodo_validate_interest(tx, nHeight, cmptime, 0) < 0) + if (chainName.isKMD() && !komodo_validate_interest(tx, nHeight, cmptime)) { LogPrintf("%s: komodo_validate_interest failure txid.%s nHeight.%d nTime.%u vs locktime.%u (cmptime.%lu)\n", __func__, tx.GetHash().ToString(), nHeight, (uint32_t)pblock->nTime, (uint32_t)tx.nLockTime, cmptime); continue; @@ -353,13 +358,6 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 BOOST_FOREACH(const CTxIn& txin, tx.vin) { - if (tx.IsPegsImport() && txin.prevout.n==10e8) - { - CAmount nValueIn = GetCoinImportValue(tx); // burn amount - nTotalIn += nValueIn; - dPriority += (double)nValueIn * 1000; // flat multiplier... max = 1e16. - continue; - } // Read prev transaction if (!view.HaveCoins(txin.prevout.hash)) { @@ -573,7 +571,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 //fprintf(stderr,"dont have inputs\n"); continue; } - CAmount nTxFees = view.GetValueIn(chainActive.LastTip()->nHeight,&interest,tx,chainActive.LastTip()->nTime)-tx.GetValueOut(); + CAmount nTxFees = view.GetValueIn(chainActive.Tip()->nHeight,interest,tx)-tx.GetValueOut(); nTxSigOps += GetP2SHSigOpCount(tx, view); if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1) @@ -634,14 +632,12 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 if ( ASSETCHAINS_ADAPTIVEPOW <= 0 ) blocktime = 1 + std::max(pindexPrev->GetMedianTimePast()+1, GetTime()); else blocktime = 1 + std::max((int64_t)(pindexPrev->nTime+1), GetTime()); - //pblock->nTime = blocktime + 1; pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus()); - //fprintf(stderr, "nBits.%u\n",pblock->nBits); int32_t stakeHeight = chainActive.Height() + 1; //LogPrintf("CreateNewBlock(): total size %u blocktime.%u nBits.%08x stake.%i\n", nBlockSize,blocktime,pblock->nBits,isStake); - if ( ASSETCHAINS_SYMBOL[0] != 0 && isStake ) + if ( !chainName.isKMD() && isStake ) { LEAVE_CRITICAL_SECTION(cs_main); LEAVE_CRITICAL_SECTION(mempool.cs); @@ -687,7 +683,6 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txStaked)); nFees += txfees; pblock->nTime = blocktime; - //printf("staking PoS ht.%d t%u lag.%u\n",(int32_t)chainActive.LastTip()->nHeight+1,blocktime,(uint32_t)(GetAdjustedTime() - (blocktime-13))); } else return(0); //fprintf(stderr,"no utxos eligible for staking\n"); } @@ -700,22 +695,18 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 txNew.vout[0].scriptPubKey = scriptPubKeyIn; txNew.vout[0].nValue = GetBlockSubsidy(nHeight,consensusParams) + nFees; txNew.nExpiryHeight = 0; - //fprintf(stderr, "coinbase txid.%s\n", txNew.GetHash().ToString().c_str()); - //fprintf(stderr, "MINER: coinbasetx.%s\n", EncodeHexTx(txNew).c_str()); - //fprintf(stderr,"mine ht.%d with %.8f\n",nHeight,(double)txNew.vout[0].nValue/COIN); - - //if ((uint32_t)chainActive.LastTip()->nTime < ASSETCHAINS_STAKED_HF_TIMESTAMP) { if ( ASSETCHAINS_ADAPTIVEPOW <= 0 ) txNew.nLockTime = std::max(pindexPrev->GetMedianTimePast()+1, GetTime()); else txNew.nLockTime = std::max((int64_t)(pindexPrev->nTime+1), GetTime()); - if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY && My_notaryid >= 0 ) + if ( chainName.isKMD() && IS_KOMODO_NOTARY && My_notaryid >= 0 ) txNew.vout[0].nValue += 5000; pblock->vtx[0] = txNew; - if ( nHeight > 1 && ASSETCHAINS_SYMBOL[0] != 0 && (ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1) && (ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0) && (commission= komodo_commission((CBlock*)&pblocktemplate->block,(int32_t)nHeight)) != 0 ) + uint64_t commission; + if ( nHeight > 1 && !chainName.isKMD() && (ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1) && (ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0) && (commission= komodo_commission((CBlock*)&pblocktemplate->block,(int32_t)nHeight)) != 0 ) { - int32_t i; uint8_t *ptr; + uint8_t *ptr; txNew.vout.resize(2); txNew.vout[1].nValue = commission; if ( ASSETCHAINS_SCRIPTPUB.size() > 1 ) @@ -726,8 +717,6 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 fprintf(stderr, "appended ccopreturn to ASSETCHAINS_SCRIPTPUB.%s\n", ASSETCHAINS_SCRIPTPUB.c_str()); didinit = true; } - //fprintf(stderr,"mine to -ac_script\n"); - //txNew.vout[1].scriptPubKey = CScript() << ParseHex(); int32_t len = strlen(ASSETCHAINS_SCRIPTPUB.c_str()); len >>= 1; txNew.vout[1].scriptPubKey.resize(len); @@ -739,15 +728,12 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 txNew.vout[1].scriptPubKey.resize(35); ptr = (uint8_t *)&txNew.vout[1].scriptPubKey[0]; ptr[0] = 33; - for (i=0; i<33; i++) + for (int32_t i=0; i<33; i++) { ptr[i+1] = ASSETCHAINS_OVERRIDE_PUBKEY33[i]; - //fprintf(stderr,"%02x",ptr[i+1]); } ptr[34] = OP_CHECKSIG; - //fprintf(stderr," set ASSETCHAINS_OVERRIDE_PUBKEY33 into vout[1]\n"); } - //printf("autocreate commision vout\n"); } else if ( (uint64_t)(txNew.vout[0].nValue) >= ASSETCHAINS_TIMELOCKGTE) { @@ -762,7 +748,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 if (scriptPubKeyIn.IsPayToScriptHash() || scriptPubKeyIn.IsPayToCryptoCondition()) { fprintf(stderr,"CreateNewBlock: attempt to add timelock to pay2sh or pay2cc\n"); - if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) ) + if ( chainName.isKMD() || (!chainName.isKMD() && !isStake) ) { LEAVE_CRITICAL_SECTION(cs_main); LEAVE_CRITICAL_SECTION(mempool.cs); @@ -788,7 +774,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 if ( totalsats == 0 ) { fprintf(stderr, "Could not create notary payment, trying again.\n"); - if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) ) + if ( chainName.isKMD() || (!chainName.isKMD() && !isStake) ) { LEAVE_CRITICAL_SECTION(cs_main); LEAVE_CRITICAL_SECTION(mempool.cs); @@ -798,14 +784,6 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 //fprintf(stderr, "Created notary payment coinbase totalsat.%lu\n",totalsats); } else fprintf(stderr, "vout 2 of notarisation is not OP_RETURN scriptlen.%i\n", scriptlen); } - if ( ASSETCHAINS_CBOPRET != 0 ) - { - int32_t numv = (int32_t)txNew.vout.size(); - txNew.vout.resize(numv+1); - txNew.vout[numv].nValue = 0; - txNew.vout[numv].scriptPubKey = komodo_mineropret(nHeight); - //printf("autocreate commision/cbopret.%lld vout[%d]\n",(long long)ASSETCHAINS_CBOPRET,(int32_t)txNew.vout.size()); - } pblock->vtx[0] = txNew; pblocktemplate->vTxFees[0] = -nFees; @@ -823,14 +801,14 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 pblock->hashFinalSaplingRoot = sapling_tree.root(); // all Verus PoS chains need this data in the block at all times - if ( ASSETCHAINS_SYMBOL[0] == 0 || ASSETCHAINS_STAKED == 0 || KOMODO_MININGTHREADS > 0 ) + if ( chainName.isKMD() || ASSETCHAINS_STAKED == 0 || KOMODO_MININGTHREADS > 0 ) { UpdateTime(pblock, Params().GetConsensus(), pindexPrev); pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus()); } pblock->nSolution.clear(); pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]); - if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY && My_notaryid >= 0 ) + if ( chainName.isKMD() && IS_KOMODO_NOTARY && My_notaryid >= 0 ) { uint32_t r; CScript opret; CMutableTransaction txNotary = CreateNewContextualCMutableTransaction(Params().GetConsensus(), chainActive.Height() + 1); @@ -866,7 +844,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 else { fprintf(stderr,"error adding notaryvin, need to create 0.0001 utxos\n"); - if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) ) + if ( chainName.isKMD() || (!chainName.isKMD() && !isStake) ) { LEAVE_CRITICAL_SECTION(cs_main); LEAVE_CRITICAL_SECTION(mempool.cs); @@ -874,75 +852,28 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 return(0); } } - else if ( ASSETCHAINS_CC == 0 && pindexPrev != 0 && ASSETCHAINS_STAKED == 0 && (ASSETCHAINS_SYMBOL[0] != 0 || !IS_KOMODO_NOTARY || My_notaryid < 0) ) + else if ( ASSETCHAINS_CC == 0 && pindexPrev != 0 && ASSETCHAINS_STAKED == 0 && (!chainName.isKMD() || !IS_KOMODO_NOTARY || My_notaryid < 0) ) { CValidationState state; - //fprintf(stderr,"check validity\n"); if ( !TestBlockValidity(state, *pblock, pindexPrev, false, false)) // invokes CC checks { - if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) ) + if ( chainName.isKMD() || (!chainName.isKMD() && !isStake) ) { LEAVE_CRITICAL_SECTION(cs_main); LEAVE_CRITICAL_SECTION(mempool.cs); } - //throw std::runtime_error("CreateNewBlock(): TestBlockValidity failed"); // crashes the node, moved to GetBlockTemplate and issue return. return(0); } - //fprintf(stderr,"valid\n"); } } - if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) ) + if ( chainName.isKMD() || ( !chainName.isKMD() && !isStake) ) { LEAVE_CRITICAL_SECTION(cs_main); LEAVE_CRITICAL_SECTION(mempool.cs); } - //fprintf(stderr,"done new block\n"); return pblocktemplate.release(); } -/* - #ifdef ENABLE_WALLET - boost::optional GetMinerScriptPubKey(CReserveKey& reservekey) - #else - boost::optional GetMinerScriptPubKey() - #endif - { - CKeyID keyID; - CBitcoinAddress addr; - if (addr.SetString(GetArg("-mineraddress", ""))) { - addr.GetKeyID(keyID); - } else { - #ifdef ENABLE_WALLET - CPubKey pubkey; - if (!reservekey.GetReservedKey(pubkey)) { - return boost::optional(); - } - keyID = pubkey.GetID(); - #else - return boost::optional(); - #endif - } - - CScript scriptPubKey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG; - return scriptPubKey; - } - - #ifdef ENABLE_WALLET - CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey) - { - boost::optional scriptPubKey = GetMinerScriptPubKey(reservekey); - #else - CBlockTemplate* CreateNewBlockWithKey() - { - boost::optional scriptPubKey = GetMinerScriptPubKey(); - #endif - - if (!scriptPubKey) { - return NULL; - } - return CreateNewBlock(*scriptPubKey); - }*/ - ////////////////////////////////////////////////////////////////////////////// // // Internal miner @@ -975,6 +906,14 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& // Internal miner // +/***** + * Create a new block + * @param reserveKey + * @param nHeight + * @param gpucount + * @param isStake + * @returns the block template + */ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, int32_t gpucount, bool isStake) { CPubKey pubkey; CScript scriptPubKey; uint8_t *script,*ptr; int32_t i,len; @@ -996,30 +935,26 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, } else if ( USE_EXTERNAL_PUBKEY != 0 ) { - //fprintf(stderr,"use notary pubkey\n"); pubkey = ParseHex(NOTARY_PUBKEY); scriptPubKey = CScript() << ParseHex(HexStr(pubkey)) << OP_CHECKSIG; } else { - //if ( !isStake || ASSETCHAINS_STAKED != 0 ) - { - if (!GetBoolArg("-disablewallet", false)) { - // wallet enabled - if (!reservekey.GetReservedKey(pubkey)) - return NULL; - scriptPubKey.clear(); - scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; - } else { - // wallet disabled - CTxDestination dest = DecodeDestination(GetArg("-mineraddress", "")); - if (IsValidDestination(dest)) { - // CKeyID keyID = boost::get(dest); - // scriptPubKey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG; - scriptPubKey = GetScriptForDestination(dest); - } else - return NULL; - } + if (!GetBoolArg("-disablewallet", false)) { + // wallet enabled + if (!reservekey.GetReservedKey(pubkey)) + return NULL; + scriptPubKey.clear(); + scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; + } else { + // wallet disabled + CTxDestination dest = DecodeDestination(GetArg("-mineraddress", "")); + if (IsValidDestination(dest)) { + // CKeyID keyID = boost::get(dest); + // scriptPubKey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG; + scriptPubKey = GetScriptForDestination(dest); + } else + return NULL; } } return CreateNewBlock(pubkey, scriptPubKey, gpucount, isStake); @@ -1072,18 +1007,18 @@ static bool ProcessBlockFound(CBlock* pblock) #endif // ENABLE_WALLET { LogPrintf("%s\n", pblock->ToString()); - LogPrintf("generated %s height.%d\n", FormatMoney(pblock->vtx[0].vout[0].nValue),chainActive.LastTip()->nHeight+1); + LogPrintf("generated %s height.%d\n", FormatMoney(pblock->vtx[0].vout[0].nValue),chainActive.Tip()->nHeight+1); // Found a solution { - if (pblock->hashPrevBlock != chainActive.LastTip()->GetBlockHash()) + if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash()) { uint256 hash; int32_t i; hash = pblock->hashPrevBlock; for (i=31; i>=0; i--) fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); fprintf(stderr," <- prev (stale)\n"); - hash = chainActive.LastTip()->GetBlockHash(); + hash = chainActive.Tip()->GetBlockHash(); for (i=31; i>=0; i--) fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); fprintf(stderr," <- chainTip (stale)\n"); @@ -1101,19 +1036,12 @@ static bool ProcessBlockFound(CBlock* pblock) reservekey.KeepKey(); } } - // Track how many getdata requests this block gets - //if ( 0 ) - { - //fprintf(stderr,"lock cs_wallet\n"); - LOCK(wallet.cs_wallet); - wallet.mapRequestCount[pblock->GetHash()] = 0; - } #endif //fprintf(stderr,"process new block\n"); // Process this block the same as if we had received it from another node CValidationState state; - if (!ProcessNewBlock(1,chainActive.LastTip()->nHeight+1,state, NULL, pblock, true, NULL)) + if (!ProcessNewBlock(1,chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL)) return error("KomodoMiner: ProcessNewBlock, block not accepted"); TrackMinedBlock(pblock->GetHash()); @@ -1121,8 +1049,6 @@ static bool ProcessBlockFound(CBlock* pblock) return true; } -int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t *blocktimes,int32_t *nonzpkeysp,int32_t height); -arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive); int32_t FOUND_BLOCK,KOMODO_MAYBEMINED; extern int32_t KOMODO_LASTMINED,KOMODO_INSYNC; arith_uint256 HASHTarget,HASHTarget_POW; @@ -1145,7 +1071,7 @@ void waitForPeers(const CChainParams &chainparams) do { if (fvNodesEmpty) { - MilliSleep(1000 + rand() % 4000); + MilliSleep(1000 + rand() % 4000); // allow to interrupt boost::this_thread::interruption_point(); LOCK(cs_vNodes); fvNodesEmpty = vNodes.empty(); @@ -1162,13 +1088,13 @@ void waitForPeers(const CChainParams &chainparams) { if (++loops <= 10) { - MilliSleep(1000); + MilliSleep(1000); // allow to interrupt } else break; } } } while (fvNodesEmpty || IsNotInSync()); - MilliSleep(100 + rand() % 400); + MilliSleep(100 + rand() % 400); // allow to interrupt } } } @@ -1176,9 +1102,9 @@ void waitForPeers(const CChainParams &chainparams) #ifdef ENABLE_WALLET CBlockIndex *get_chainactive(int32_t height) { - if ( chainActive.LastTip() != 0 ) + if ( chainActive.Tip() != 0 ) { - if ( height <= chainActive.LastTip()->nHeight ) + if ( height <= chainActive.Tip()->nHeight ) { LOCK(cs_main); return(chainActive[height]); @@ -1191,7 +1117,27 @@ CBlockIndex *get_chainactive(int32_t height) #endif int32_t gotinvalid; -extern int32_t getkmdseason(int32_t height); + +bool check_tromp_solution(equi &eq, std::function)> validBlock) +{ + // Convert solution indices to byte array (decompress) and pass it to validBlock method. + for (size_t s = 0; s < std::min(MAXSOLS, eq.nsols); s++) + { + LogPrint("pow", "Checking solution %d\n", s+1); + std::vector index_vector(PROOFSIZE); + for (size_t i = 0; i < PROOFSIZE; i++) { + index_vector[i] = eq.sols[s][i]; + } + std::vector sol_char = GetMinimalFromIndices(index_vector, DIGITBITS); + + if (validBlock(sol_char)) { + // If we find a POW solution, do not try other solutions + // because they become invalid as we created a new block in blockchain. + return true; + } + } + return false; +} #ifdef ENABLE_WALLET void static BitcoinMiner(CWallet *pwallet) @@ -1217,12 +1163,22 @@ void static BitcoinMiner() uint8_t *script; uint64_t total; int32_t i,j,gpucount=KOMODO_MAXGPUCOUNT,notaryid = -1; while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) ) { - sleep(1); - if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 ) + //sleep(1); + boost::this_thread::sleep_for(boost::chrono::seconds(1)); // allow to interrupt + if ( komodo_baseid(chainName.symbol().c_str()) < 0 ) break; } - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - komodo_chosennotary(¬aryid,chainActive.Height()+1,NOTARY_PUBKEY33,(uint32_t)chainActive.Tip()->GetMedianTimePast()); + if ( chainName.isKMD() ) + { + int newHeight; + uint32_t timePast; + { + LOCK(cs_main); + newHeight = chainActive.Height() + 1; + timePast = (uint32_t)chainActive.Tip()->GetMedianTimePast(); + } + komodo_chosennotary(¬aryid,newHeight,NOTARY_PUBKEY33,timePast); + } if ( notaryid != My_notaryid ) My_notaryid = notaryid; std::string solver; @@ -1232,8 +1188,8 @@ void static BitcoinMiner() solver = "default"; assert(solver == "tromp" || solver == "default"); LogPrint("pow", "Using Equihash solver \"%s\" with n = %u, k = %u\n", solver, n, k); - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - fprintf(stderr,"notaryid.%d Mining.%s with %s\n",notaryid,ASSETCHAINS_SYMBOL,solver.c_str()); + if ( chainName.isKMD() ) + fprintf(stderr,"notaryid.%d Mining.%s with %s\n",notaryid,chainName.symbol().c_str(),solver.c_str()); std::mutex m_cs; bool cancelSolver = false; boost::signals2::connection c = uiInterface.NotifyBlockTip.connect( @@ -1245,14 +1201,12 @@ void static BitcoinMiner() miningTimer.start(); try { - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - fprintf(stderr,"try %s Mining with %s\n",ASSETCHAINS_SYMBOL,solver.c_str()); + if ( !chainName.isKMD() ) + fprintf(stderr,"try %s Mining with %s\n",chainName.symbol().c_str(),solver.c_str()); while (true) { - if (chainparams.MiningRequiresPeers()) //chainActive.LastTip()->nHeight != 235300 && + if (chainparams.MiningRequiresPeers()) { - //if ( ASSETCHAINS_SEED != 0 && chainActive.LastTip()->nHeight < 100 ) - // break; // Busy-wait for the network to come online so we don't waste time mining // on an obsolete chain. In regtest mode we expect to fly solo. miningTimer.stop(); @@ -1265,27 +1219,25 @@ void static BitcoinMiner() if (!fvNodesEmpty )//&& !IsInitialBlockDownload()) break; MilliSleep(15000); - //fprintf(stderr,"fvNodesEmpty %d IsInitialBlockDownload(%s) %d\n",(int32_t)fvNodesEmpty,ASSETCHAINS_SYMBOL,(int32_t)IsInitialBlockDownload()); + //fprintf(stderr,"fvNodesEmpty %d IsInitialBlockDownload(%s) %d\n",(int32_t)fvNodesEmpty,chainName.symbol().c_str(),(int32_t)IsInitialBlockDownload()); } while (true); - //fprintf(stderr,"%s Found peers\n",ASSETCHAINS_SYMBOL); miningTimer.start(); } // // Create new block // unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); - CBlockIndex* pindexPrev = chainActive.LastTip(); + CBlockIndex* pindexPrev = nullptr; + { + LOCK(cs_main); + pindexPrev = chainActive.Tip(); + } if ( Mining_height != pindexPrev->nHeight+1 ) { Mining_height = pindexPrev->nHeight+1; Mining_start = (uint32_t)time(NULL); } - if ( ASSETCHAINS_SYMBOL[0] != 0 && ASSETCHAINS_STAKED == 0 ) - { - //fprintf(stderr,"%s create new block ht.%d\n",ASSETCHAINS_SYMBOL,Mining_height); - //sleep(3); - } #ifdef ENABLE_WALLET // notaries always default to staking @@ -1305,7 +1257,8 @@ void static BitcoinMiner() static uint32_t counter; if ( counter++ < 10 && ASSETCHAINS_STAKED == 0 ) fprintf(stderr,"created illegal blockB, retry\n"); - sleep(1); + //sleep(1); + boost::this_thread::sleep_for(boost::chrono::seconds(1)); // allow to interrupt continue; } //fprintf(stderr,"get template\n"); @@ -1321,7 +1274,7 @@ void static BitcoinMiner() return; } CBlock *pblock = &pblocktemplate->block; - if ( ASSETCHAINS_SYMBOL[0] != 0 ) + if ( !chainName.isKMD() ) { if ( ASSETCHAINS_REWARD[0] == 0 && !ASSETCHAINS_LASTERA ) { @@ -1329,14 +1282,15 @@ void static BitcoinMiner() { static uint32_t counter; if ( counter++ < 10 ) - fprintf(stderr,"skip generating %s on-demand block, no tx avail\n",ASSETCHAINS_SYMBOL); - sleep(10); + fprintf(stderr,"skip generating %s on-demand block, no tx avail\n",chainName.symbol().c_str()); + //sleep(10); + boost::this_thread::sleep_for(boost::chrono::seconds(10)); // allow to interrupt continue; - } else fprintf(stderr,"%s vouts.%d mining.%d vs %d\n",ASSETCHAINS_SYMBOL,(int32_t)pblock->vtx[0].vout.size(),Mining_height,ASSETCHAINS_MINHEIGHT); + } else fprintf(stderr,"%s vouts.%d mining.%d vs %d\n",chainName.symbol().c_str(),(int32_t)pblock->vtx[0].vout.size(),Mining_height,ASSETCHAINS_MINHEIGHT); } } // We cant increment nonce for proof transactions, as it modifes the coinbase, meaning CreateBlock must be called again to get a new valid proof to pass validation. - if ( (ASSETCHAINS_SYMBOL[0] == 0 && notaryid >= 0 && Mining_height > nDecemberHardforkHeight ) || (ASSETCHAINS_STAKED != 0 && komodo_newStakerActive(Mining_height, pblock->nTime) != 0) ) //December 2019 hardfork + if ( (chainName.isKMD() && notaryid >= 0 && Mining_height > nDecemberHardforkHeight ) || (ASSETCHAINS_STAKED != 0 && komodo_newStakerActive(Mining_height, pblock->nTime) != 0) ) //December 2019 hardfork nExtraNonce = 0; IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); //fprintf(stderr,"Running KomodoMiner.%s with %u transactions in block\n",solver.c_str(),(int32_t)pblock->vtx.size()); @@ -1348,7 +1302,7 @@ void static BitcoinMiner() pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus()); savebits = pblock->nBits; HASHTarget = arith_uint256().SetCompact(savebits); - if ( ASSETCHAINS_SYMBOL[0] == 0 && notaryid >= 0 ) + if ( chainName.isKMD() && notaryid >= 0 ) { j = 65; if ( (Mining_height >= 235300 && Mining_height < 236000) || (Mining_height % KOMODO_ELECTION_GAP) > 64 || (Mining_height % KOMODO_ELECTION_GAP) == 0 || Mining_height > 1000000 ) @@ -1400,7 +1354,7 @@ void static BitcoinMiner() if ( (Mining_height >= 235300 && Mining_height < 236000) || (j == 65 && Mining_height > KOMODO_MAYBEMINED+1 && Mining_height > KOMODO_LASTMINED+64) ) { HASHTarget = arith_uint256().SetCompact(KOMODO_MINDIFF_NBITS); - fprintf(stderr,"I am the chosen one for %s ht.%d\n",ASSETCHAINS_SYMBOL,pindexPrev->nHeight+1); + fprintf(stderr,"I am the chosen one for %s ht.%d\n",chainName.symbol().c_str(),pindexPrev->nHeight+1); } else fprintf(stderr,"duplicate at j.%d\n",j); /* check if hf22 rule can be applied */ @@ -1459,15 +1413,12 @@ void static BitcoinMiner() if ( ASSETCHAINS_STAKED < 100 ) LogPrintf("Block %d : PoS %d%% vs target %d%% \n",Mining_height,percPoS,(int32_t)ASSETCHAINS_STAKED); } - //else if ( ASSETCHAINS_ADAPTIVEPOW > 0 ) - // HASHTarget_POW = komodo_adaptivepow_target(Mining_height,HASHTarget,pblock->nTime); gotinvalid = 0; while (true) { //fprintf(stderr,"gotinvalid.%d\n",gotinvalid); if ( gotinvalid != 0 ) break; - // komodo_longestchain(); // Hash state crypto_generichash_blake2b_state state; @@ -1504,28 +1455,21 @@ void static BitcoinMiner() solutionTargetChecks.increment(); B = *pblock; h = UintToArith256(B.GetHash()); - /*for (z=31; z>=16; z--) - fprintf(stderr,"%02x",((uint8_t *)&h)[z]); - fprintf(stderr," mined "); - for (z=31; z>=16; z--) - fprintf(stderr,"%02x",((uint8_t *)&HASHTarget)[z]); - fprintf(stderr," hashTarget "); - for (z=31; z>=16; z--) - fprintf(stderr,"%02x",((uint8_t *)&HASHTarget_POW)[z]); - fprintf(stderr," POW\n");*/ if ( h > hashTarget ) { - //if ( ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0 ) - // MilliSleep(30); return false; } if ( IS_KOMODO_NOTARY && B.nTime > GetTime() ) { - //fprintf(stderr,"need to wait %d seconds to submit block\n",(int32_t)(B.nTime - GetAdjustedTime())); while ( GetTime() < B.nTime-2 ) { - sleep(1); - if ( chainActive.LastTip()->nHeight >= Mining_height ) + boost::this_thread::sleep_for(boost::chrono::seconds(1)); // allow to interrupt + CBlockIndex *tip = nullptr; + { + LOCK(cs_main); + tip = chainActive.Tip(); + } + if ( tip->nHeight >= Mining_height ) { fprintf(stderr,"new block arrived\n"); return(false); @@ -1538,7 +1482,7 @@ void static BitcoinMiner() { int32_t r; if ( (r= ((Mining_height + NOTARY_PUBKEY33[16]) % 64) / 8) > 0 ) - MilliSleep((rand() % (r * 1000)) + 1000); + MilliSleep((rand() % (r * 1000)) + 1000); // allow to interrupt } } else @@ -1548,25 +1492,27 @@ void static BitcoinMiner() // Need to rebuild block if the found solution for PoS, meets POW target, otherwise it will be rejected. if ( ASSETCHAINS_STAKED < 100 && komodo_newStakerActive(Mining_height,pblock->nTime) != 0 && h < hashTarget_POW ) { - fprintf(stderr, "[%s:%d] PoS block.%u meets POW_Target.%u building new block\n", ASSETCHAINS_SYMBOL, Mining_height, h.GetCompact(), hashTarget_POW.GetCompact()); + fprintf(stderr, "[%s:%d] PoS block.%u meets POW_Target.%u building new block\n", chainName.symbol().c_str(), Mining_height, h.GetCompact(), hashTarget_POW.GetCompact()); return(false); } if ( komodo_waituntilelegible(B.nTime, Mining_height, ASSETCHAINS_STAKED_BLOCK_FUTURE_MAX) == 0 ) return(false); } uint256 tmp = B.GetHash(); - fprintf(stderr,"[%s:%d] mined block ",ASSETCHAINS_SYMBOL,Mining_height); + fprintf(stderr,"[%s:%d] mined block ",chainName.symbol().c_str(),Mining_height); int32_t z; for (z=31; z>=0; z--) fprintf(stderr,"%02x",((uint8_t *)&tmp)[z]); fprintf(stderr, "\n"); } - CValidationState state; - if ( !TestBlockValidity(state,B, chainActive.LastTip(), true, false)) + bool blockValid; + { + LOCK(cs_main); + CValidationState state; + blockValid = TestBlockValidity(state, B, chainActive.Tip(), true, false); + } + if ( !blockValid ) { h = UintToArith256(B.GetHash()); - //for (z=31; z>=0; z--) - // fprintf(stderr,"%02x",((uint8_t *)&h)[z]); - //fprintf(stderr," Invalid block mined, try again\n"); gotinvalid = 1; return(false); } @@ -1616,33 +1562,14 @@ void static BitcoinMiner() eq.digitK(0); ehSolverRuns.increment(); - // Convert solution indices to byte array (decompress) and pass it to validBlock method. - for (size_t s = 0; s < eq.nsols; s++) { - LogPrint("pow", "Checking solution %d\n", s+1); - std::vector index_vector(PROOFSIZE); - for (size_t i = 0; i < PROOFSIZE; i++) { - index_vector[i] = eq.sols[s][i]; - } - std::vector sol_char = GetMinimalFromIndices(index_vector, DIGITBITS); - - if (validBlock(sol_char)) { - // If we find a POW solution, do not try other solutions - // because they become invalid as we created a new block in blockchain. - break; - } - } + check_tromp_solution(eq, validBlock); + } else { try { // If we find a valid block, we rebuild bool found = EhOptimisedSolve(n, k, curr_state, validBlock, cancelled); ehSolverRuns.increment(); if (found) { - int32_t i; uint256 hash = pblock->GetHash(); - //for (i=0; i<32; i++) - // fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); - //fprintf(stderr," <- %s Block found %d\n",ASSETCHAINS_SYMBOL,Mining_height); - //FOUND_BLOCK = 1; - //KOMODO_MAYBEMINED = Mining_height; break; } } catch (EhSolverCancelledException&) { @@ -1663,7 +1590,7 @@ void static BitcoinMiner() } */ if (vNodes.empty() && chainparams.MiningRequiresPeers()) { - if ( ASSETCHAINS_SYMBOL[0] == 0 || Mining_height > ASSETCHAINS_MINHEIGHT ) + if ( chainName.isKMD() || Mining_height > ASSETCHAINS_MINHEIGHT ) { fprintf(stderr,"no nodes, break\n"); break; @@ -1671,20 +1598,20 @@ void static BitcoinMiner() } if ((UintToArith256(pblock->nNonce) & 0xffff) == 0xffff) { - //if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) fprintf(stderr,"0xffff, break\n"); break; } if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60) { - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - fprintf(stderr,"timeout, break\n"); break; } - if ( pindexPrev != chainActive.LastTip() ) + CBlockIndex *tip = nullptr; + { + LOCK(cs_main); + tip = chainActive.Tip(); + } + if ( pindexPrev != tip ) { - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - fprintf(stderr,"Tip advanced, break\n"); break; } // Update nNonce and nTime @@ -1696,19 +1623,7 @@ void static BitcoinMiner() HASHTarget.SetCompact(pblock->nBits); hashTarget = HASHTarget; savebits = pblock->nBits; - //hashTarget = HASHTarget_POW = komodo_adaptivepow_target(Mining_height,HASHTarget,pblock->nTime); } - /*if ( NOTARY_PUBKEY33[0] == 0 ) - { - int32_t percPoS; - UpdateTime(pblock, consensusParams, pindexPrev); - if (consensusParams.fPowAllowMinDifficultyBlocks) - { - // Changing pblock->nTime can change work required on testnet: - HASHTarget.SetCompact(pblock->nBits); - HASHTarget_POW = komodo_PoWtarget(&percPoS,HASHTarget,Mining_height,ASSETCHAINS_STAKED); - } - }*/ } } } @@ -1744,6 +1659,8 @@ void static BitcoinMiner() if (minerThreads != NULL) { minerThreads->interrupt_all(); + // std::cout << "Waiting for mining threads to stop..." << std::endl; + minerThreads->join_all(); // prevent thread overlapping delete minerThreads; minerThreads = NULL; } @@ -1775,3 +1692,57 @@ void static BitcoinMiner() } #endif // ENABLE_MINING + +/**** + * This should only be called from a unit test, as the equihash code + * can only be included once (no separation of implementation from declaration). + * This verifies that std::min(MAXSOLS, eq.nsols) prevents a SIGSEGV. + */ +bool test_tromp_equihash() +{ + // get the sols to be less than nsols + + // create a context + CBlock block; + const CChainParams& params = Params(); + + crypto_generichash_blake2b_state state; + EhInitialiseState(params.EquihashN(), params.EquihashK(), state); + // I = the block header minus nonce and solution. + CEquihashInput I{block}; + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << I; + // H(I||... + crypto_generichash_blake2b_update(&state, (unsigned char*)&ss[0], ss.size()); + // H(I||V||... + crypto_generichash_blake2b_state curr_state; + curr_state = state; + crypto_generichash_blake2b_update(&state,block.nNonce.begin(),block.nNonce.size()); + + // Create solver and initialize it. + equi eq(1); + eq.setstate(&curr_state); + + // Initialization done, start algo driver. + eq.digit0(0); + eq.xfull = eq.bfull = eq.hfull = 0; + eq.showbsizes(0); + for (u32 r = 1; r < WK; r++) { + (r&1) ? eq.digitodd(r, 0) : eq.digiteven(r, 0); + eq.xfull = eq.bfull = eq.hfull = 0; + eq.showbsizes(r); + } + eq.digitK(0); + + // force nsols to be more than MAXSOLS (8) + while (eq.nsols <= MAXSOLS * 800) + { + tree t(1); + eq.candidate(t); + } + + auto func = [](std::vector) { return false; }; + + // this used to throw a SIGSEGV + return check_tromp_solution(eq, func); +} diff --git a/src/miner.h b/src/miner.h index a3bedd29204..167cce217a9 100644 --- a/src/miner.h +++ b/src/miner.h @@ -34,6 +34,9 @@ class CWallet; #endif namespace Consensus { struct Params; }; +/*** + * Holds data about the block under construction + */ struct CBlockTemplate { CBlock block; @@ -42,8 +45,15 @@ struct CBlockTemplate }; #define KOMODO_MAXGPUCOUNT 65 -/** Generate a new block, without valid proof-of-work */ -CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& scriptPubKeyIn, int32_t gpucount, bool isStake = false); +/***** + * @breif Generate a new block based on mempool txs, without valid proof-of-work + * @param _pk the public key + * @param _scriptPubKeyIn the script for the public key + * @param gpucount assists in calculating the block's nTime + * @param isStake + * @returns the block template + */ +CBlockTemplate* CreateNewBlock(const CPubKey _pk,const CScript& _scriptPubKeyIn, int32_t gpucount, bool isStake = false); #ifdef ENABLE_WALLET boost::optional GetMinerScriptPubKey(CReserveKey& reservekey); CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, int32_t gpucount, bool isStake = false); @@ -64,5 +74,6 @@ void GenerateBitcoins(bool fGenerate, int nThreads); #endif void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev); +void komodo_sendmessage(int32_t minpeers,int32_t maxpeers,const char *message,std::vector payload); #endif // BITCOIN_MINER_H diff --git a/src/mini-gmp.c b/src/mini-gmp.c index f9ee23f1517..f0addaf598f 100644 --- a/src/mini-gmp.c +++ b/src/mini-gmp.c @@ -4374,7 +4374,7 @@ char *bitcoin_base58encode(char *coinaddr,uint8_t *data,int32_t datalen) return(coinaddr); } -int32_t bitcoin_base58decode(uint8_t *data,char *coinaddr) +int32_t bitcoin_base58decode(uint8_t *data,const char *coinaddr) { uint32_t zeroes,be_sz=0; size_t count; const char *p,*p1; mpz_t bn58,bn; mpz_init_set_ui(bn58,58); diff --git a/src/mini-gmp.h b/src/mini-gmp.h index 8d9d7733f97..ea12f425ed9 100644 --- a/src/mini-gmp.h +++ b/src/mini-gmp.h @@ -66,7 +66,7 @@ extern "C" { char *bitcoin_base58encode(char *coinaddr,uint8_t *data,int32_t datalen); -int32_t bitcoin_base58decode(uint8_t *data,char *coinaddr); +int32_t bitcoin_base58decode(uint8_t *data,const char *coinaddr); void mp_set_memory_functions (void *(*) (size_t), void *(*) (void *, size_t, size_t), diff --git a/src/net.cpp b/src/net.cpp index 111e7acdf90..b81bf5b4c16 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -32,6 +32,9 @@ #include "scheduler.h" #include "ui_interface.h" #include "crypto/common.h" +#include "komodo_defs.h" +#include "komodo_globals.h" +#include "notaries_staked.h" #ifdef _WIN32 #include @@ -74,13 +77,6 @@ namespace { }; } -// -// Global state variables -// -extern uint16_t ASSETCHAINS_P2PPORT; -extern int8_t is_STAKED(const char *chain_name); -extern char ASSETCHAINS_SYMBOL[65]; - bool fDiscover = true; bool fListen = true; uint64_t nLocalServices = NODE_NETWORK; @@ -444,7 +440,7 @@ void CNode::CloseSocketDisconnect() vRecvMsg.clear(); } -extern int32_t KOMODO_NSPV; +/* TODO remove #ifndef KOMODO_NSPV_FULLNODE #define KOMODO_NSPV_FULLNODE (KOMODO_NSPV <= 0) #endif // !KOMODO_NSPV_FULLNODE @@ -452,6 +448,7 @@ extern int32_t KOMODO_NSPV; #ifndef KOMODO_NSPV_SUPERLITE #define KOMODO_NSPV_SUPERLITE (KOMODO_NSPV > 0) #endif // !KOMODO_NSPV_SUPERLITE +*/ void CNode::PushVersion() { @@ -597,6 +594,9 @@ void CNode::copyStats(CNodeStats &stats, const std::vector &m_asmap) stats.dPingTime = (((double)nPingUsecTime) / 1e6); stats.dPingWait = (((double)nPingUsecWait) / 1e6); + stats.m_addr_processed = m_addr_processed.load(); + stats.m_addr_rate_limited = m_addr_rate_limited.load(); + // Leave string empty if addrLocal invalid (not filled in yet) stats.addrLocal = addrLocal.IsValid() ? addrLocal.ToString() : ""; } @@ -1394,7 +1394,7 @@ void ThreadOpenConnections() static bool done = false; if (!done) { // skip DNS seeds for staked chains. - if ( is_STAKED(ASSETCHAINS_SYMBOL) == 0 ) { + if ( is_STAKED(chainName.symbol()) == 0 ) { //LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be available.\n"); LogPrintf("Adding fixed seed nodes.\n"); addrman.Add(convertSeed6(Params().FixedSeeds()), CNetAddr("127.0.0.1")); @@ -1817,9 +1817,7 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) Discover(threadGroup); // skip DNS seeds for staked chains. - extern int8_t is_STAKED(const char *chain_name); - extern char ASSETCHAINS_SYMBOL[65]; - if ( is_STAKED(ASSETCHAINS_SYMBOL) != 0 ) + if ( is_STAKED(chainName.symbol()) != 0 ) SoftSetBoolArg("-dnsseed", false); // @@ -2202,7 +2200,7 @@ void CNode::AskFor(const CInv& inv) mapAskFor.insert(std::make_pair(nRequestTime, inv)); } -void CNode::BeginMessage(const char* pszCommand) EXCLUSIVE_LOCK_FUNCTION(cs_vSend) +void CNode::BeginMessage(const char* pszCommand) ACQUIRE(cs_vSend) { ENTER_CRITICAL_SECTION(cs_vSend); assert(ssSend.size() == 0); @@ -2210,7 +2208,7 @@ void CNode::BeginMessage(const char* pszCommand) EXCLUSIVE_LOCK_FUNCTION(cs_vSen LogPrint("net", "sending: %s ", SanitizeString(pszCommand)); } -void CNode::AbortMessage() UNLOCK_FUNCTION(cs_vSend) +void CNode::AbortMessage() RELEASE(cs_vSend) { ssSend.clear(); @@ -2219,7 +2217,7 @@ void CNode::AbortMessage() UNLOCK_FUNCTION(cs_vSend) LogPrint("net", "(aborted)\n"); } -void CNode::EndMessage() UNLOCK_FUNCTION(cs_vSend) +void CNode::EndMessage() RELEASE(cs_vSend) { // The -*messagestest options are intentionally not documented in the help message, // since they are only used during development to debug the networking code and are diff --git a/src/net.h b/src/net.h index 9b841a7f231..6148a363cef 100644 --- a/src/net.h +++ b/src/net.h @@ -63,6 +63,13 @@ static const int TIMEOUT_INTERVAL = 20 * 60; static const unsigned int MAX_INV_SZ = 50000; /** The maximum number of new addresses to accumulate before announcing. */ static const unsigned int MAX_ADDR_TO_SEND = 1000; +/** The maximum rate of address records we're willing to process on average. Can be bypassed using + * the NetPermissionFlags::Addr permission. */ +static constexpr double MAX_ADDR_RATE_PER_SECOND{0.1}; +/** The soft limit of the address processing token bucket (the regular MAX_ADDR_RATE_PER_SECOND + * based increments won't go above this, but the MAX_ADDR_TO_SEND increment following GETADDR + * is exempt from this limit. */ +static constexpr size_t MAX_ADDR_PROCESSING_TOKEN_BUCKET{MAX_ADDR_TO_SEND}; /** Maximum length of incoming protocol messages (no message over 2 MiB is currently acceptable). */ static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = (_MAX_BLOCK_SIZE + 24); // 24 is msgheader size /** Maximum length of strSubVer in `version` message */ @@ -208,6 +215,8 @@ class CNodeStats double dPingTime; double dPingWait; std::string addrLocal; + uint64_t m_addr_processed{0}; + uint64_t m_addr_rate_limited{0}; // Address of this peer CAddress addr; // Bind address of our side of the connection @@ -341,6 +350,16 @@ class CNode bool fGetAddr; std::set setKnown; + /** Number of addr messages that can be processed from this peer. Start at 1 to + * permit self-announcement. */ + double m_addr_token_bucket{1.0}; + /** When m_addr_token_bucket was last updated */ + int64_t m_addr_token_timestamp{GetTimeMicros()}; + /** Total number of addresses that were dropped due to rate limiting. */ + std::atomic m_addr_rate_limited{0}; + /** Total number of addresses that were processed (excludes rate limited ones). */ + std::atomic m_addr_processed{0}; + // inventory based relay mruset setInventoryKnown; std::vector vInventoryToSend; @@ -458,13 +477,13 @@ class CNode void AskFor(const CInv& inv); // TODO: Document the postcondition of this function. Is cs_vSend locked? - void BeginMessage(const char* pszCommand) EXCLUSIVE_LOCK_FUNCTION(cs_vSend); + void BeginMessage(const char* pszCommand) ACQUIRE(cs_vSend); // TODO: Document the precondition of this function. Is cs_vSend locked? - void AbortMessage() UNLOCK_FUNCTION(cs_vSend); + void AbortMessage() RELEASE(cs_vSend); // TODO: Document the precondition of this function. Is cs_vSend locked? - void EndMessage() UNLOCK_FUNCTION(cs_vSend); + void EndMessage() RELEASE(cs_vSend); void PushVersion(); diff --git a/src/notaries_staked.cpp b/src/notaries_staked.cpp index 0a804db2083..439cd430b16 100644 --- a/src/notaries_staked.cpp +++ b/src/notaries_staked.cpp @@ -3,31 +3,50 @@ #include "crosschain.h" #include "cc/CCinclude.h" #include "komodo_defs.h" +#include "komodo_globals.h" #include "komodo_hardfork.h" #include "hex.h" #include -extern pthread_mutex_t staked_mutex; +pthread_mutex_t staked_mutex; // todo remove -int8_t is_STAKED(const char *chain_name) +//static bool doneinit_STAKED = false; + +/***** + * Reset the doneinit static (for unit testing) + */ +/*void undo_init_STAKED() +{ + doneinit_STAKED = false; +}*/ + +/**** + * @brief given the chan name, determine the type of chain + * @param chain_name the chain name + * @returns 0=kmd, 1=LABS, 2=LABSxxx, 3=CFEK, 4=TEST, 255=banned + */ +uint8_t is_STAKED(const std::string& symbol) { - static int8_t STAKED,doneinit; - if ( chain_name[0] == 0 ) + // let's not use static vars: + /* static uint8_t STAKED; + if (symbol.empty()) return(0); - if (doneinit == 1 && ASSETCHAINS_SYMBOL[0] != 0) + if (doneinit_STAKED && !chainName.isKMD()) return(STAKED); - else STAKED = 0; - if ( (strcmp(chain_name, "LABS") == 0) ) + else STAKED = 0;*/ + uint8_t STAKED = 0; + + if ( symbol == "LABS" ) STAKED = 1; // These chains are allowed coin emissions. - else if ( (strncmp(chain_name, "LABS", 4) == 0) ) + else if ( symbol.find("LABS") == 0 ) STAKED = 2; // These chains have no coin emission, block subsidy is always 0, and comission is 0. Notary pay is allowed. - else if ( (strcmp(chain_name, "CFEK") == 0) || (strncmp(chain_name, "CFEK", 4) == 0) ) + else if ( symbol == "CFEK" || symbol.find("CFEK") == 0 ) STAKED = 3; // These chains have no speical rules at all. - else if ( (strcmp(chain_name, "TEST") == 0) || (strncmp(chain_name, "TEST", 4) == 0) ) + else if ( symbol == "TEST" || symbol.find("TEST") == 0 ) STAKED = 4; // These chains are for testing consensus to create a chain etc. Not meant to be actually used for anything important. - else if ( (strcmp(chain_name, "THIS_CHAIN_IS_BANNED") == 0) ) + else if ( symbol == "THIS_CHAIN_IS_BANNED" ) STAKED = 255; // Any chain added to this group is banned, no notarisations are valid, as a consensus rule. Can be used to remove a chain from cluster if needed. - doneinit = 1; + //doneinit_STAKED = true; return(STAKED); }; @@ -45,6 +64,8 @@ int32_t STAKED_era(int timestamp) return(0); }; +//char NOTARYADDRS[64][64]; // todo remove + int8_t StakedNotaryID(std::string ¬aryname, char *Raddress) { if ( STAKED_ERA != 0 ) { @@ -65,10 +86,7 @@ int8_t numStakedNotaries(uint8_t pubkeys[64][33],int8_t era) { if ( ChainName[0] == 0 ) { - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - strcpy(ChainName,"KMD"); - else - strcpy(ChainName,ASSETCHAINS_SYMBOL); + strcpy(ChainName, chainName.ToString().c_str()); } if ( era == 0 ) diff --git a/src/notaries_staked.h b/src/notaries_staked.h index 4095eb0f0de..5d632da7454 100644 --- a/src/notaries_staked.h +++ b/src/notaries_staked.h @@ -89,7 +89,9 @@ static const char *notaries_STAKED[NUM_STAKED_ERAS][64][2] = } }; -int8_t is_STAKED(const char *chain_name); +//void undo_init_STAKED(); + +uint8_t is_STAKED(const std::string& symbol); int32_t STAKED_era(int timestamp); int8_t numStakedNotaries(uint8_t pubkeys[64][33],int8_t era); int8_t StakedNotaryID(std::string ¬aryname, char *Raddress); diff --git a/src/notarisationdb.cpp b/src/notarisationdb.cpp index b148deccf58..471206f6ce3 100644 --- a/src/notarisationdb.cpp +++ b/src/notarisationdb.cpp @@ -14,7 +14,12 @@ NotarisationDB *pnotarisations; NotarisationDB::NotarisationDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "notarisations", nCacheSize, fMemory, fWipe, false, 64) { } - +/**** + * Get notarisations within a block + * @param block the block to scan + * @param height the height (to find appropriate notaries) + * @returns the notarisations found + */ NotarisationsInBlock ScanBlockNotarisations(const CBlock &block, int nHeight) { EvalRef eval; @@ -32,12 +37,11 @@ NotarisationsInBlock ScanBlockNotarisations(const CBlock &block, int nHeight) continue; //printf("Checked notarisation data for %s \n",data.symbol); - int authority = GetSymbolAuthority(data.symbol); + CrosschainType authority = CrossChain::GetSymbolAuthority(data.symbol); if (authority == CROSSCHAIN_KOMODO) { if (!eval->CheckNotaryInputs(tx, nHeight, block.nTime)) continue; - //printf("Authorised notarisation data for %s \n",data.symbol); } else if (authority == CROSSCHAIN_STAKED) { // We need to create auth_STAKED dynamically here based on timestamp int32_t staked_era = STAKED_era(timestamp); @@ -51,15 +55,12 @@ NotarisationsInBlock ScanBlockNotarisations(const CBlock &block, int nHeight) // pass era slection off to notaries_staked.cpp file auth_STAKED = Choose_auth_STAKED(staked_era); } - if (!CheckTxAuthority(tx, auth_STAKED)) + if (!CrossChain::CheckTxAuthority(tx, auth_STAKED)) continue; } if (parsed) { vNotarisations.push_back(std::make_pair(tx.GetHash(), data)); - //printf("Parsed a notarisation for: %s, txid:%s, ccid:%i, momdepth:%i\n", - // data.symbol, tx.GetHash().GetHex().data(), data.ccId, data.MoMDepth); - //if (!data.MoMoM.IsNull()) printf("MoMoM:%s\n", data.MoMoM.GetHex().data()); } else LogPrintf("WARNING: Couldn't parse notarisation for tx: %s at height %i\n", tx.GetHash().GetHex().data(), nHeight); @@ -67,12 +68,6 @@ NotarisationsInBlock ScanBlockNotarisations(const CBlock &block, int nHeight) return vNotarisations; } -bool IsTXSCL(const char* symbol) -{ - return strlen(symbol) >= 5 && strncmp(symbol, "TXSCL", 5) == 0; -} - - bool GetBlockNotarisations(uint256 blockHash, NotarisationsInBlock &nibs) { return pnotarisations->Read(blockHash, nibs); @@ -100,63 +95,48 @@ void WriteBackNotarisations(const NotarisationsInBlock notarisations, CDBBatch & } } - +/*** + * Erase given notarisations from db + * @param notarisations what to erase + * @param batch the collection of db transactions + */ void EraseBackNotarisations(const NotarisationsInBlock notarisations, CDBBatch &batch) { - BOOST_FOREACH(const Notarisation &n, notarisations) + for(const Notarisation &n : notarisations) { if (!n.second.txHash.IsNull()) batch.Erase(n.second.txHash); } } -/* +/***** * Scan notarisationsdb backwards for blocks containing a notarisation * for given symbol. Return height of matched notarisation or 0. + * @param height where to start the search + * @param symbol the symbol to look for + * @param scanLimitBlocks max number of blocks to search + * @param out the first Notarization found + * @returns height (0 indicates error) */ int ScanNotarisationsDB(int height, std::string symbol, int scanLimitBlocks, Notarisation& out) { if (height < 0 || height > chainActive.Height()) - return false; + return 0; - for (int i=0; i height) break; - NotarisationsInBlock notarisations; - uint256 blockHash = *chainActive[height-i]->phashBlock; - if (!GetBlockNotarisations(blockHash, notarisations)) - continue; - - BOOST_FOREACH(Notarisation& nota, notarisations) { - if (strcmp(nota.second.symbol, symbol.data()) == 0) { - out = nota; - return height-i; - } - } - } - return 0; -} - -int ScanNotarisationsDB2(int height, std::string symbol, int scanLimitBlocks, Notarisation& out) -{ - int32_t i,maxheight,ht; - maxheight = chainActive.Height(); - if ( height < 0 || height > maxheight ) - return false; - for (i=0; i maxheight ) + if (i > height) break; NotarisationsInBlock notarisations; - uint256 blockHash = *chainActive[ht]->phashBlock; - if ( !GetBlockNotarisations(blockHash,notarisations) ) - continue; - BOOST_FOREACH(Notarisation& nota,notarisations) + uint256 blockHash = *chainActive[height-i]->phashBlock; + if (GetBlockNotarisations(blockHash, notarisations)) { - if ( strcmp(nota.second.symbol,symbol.data()) == 0 ) - { - out = nota; - return(ht); + for(Notarisation& nota : notarisations) { + if (strcmp(nota.second.symbol, symbol.data()) == 0) + { + out = nota; + return height-i; + } } } } diff --git a/src/notarisationdb.h b/src/notarisationdb.h index af5d4df28d2..a2d64365a66 100644 --- a/src/notarisationdb.h +++ b/src/notarisationdb.h @@ -18,13 +18,48 @@ extern NotarisationDB *pnotarisations; typedef std::pair Notarisation; typedef std::vector NotarisationsInBlock; +/**** + * Get notarisations within a block + * @param block the block to scan + * @param height the height (to find appropriate notaries) + * @returns the notarisations found + */ NotarisationsInBlock ScanBlockNotarisations(const CBlock &block, int nHeight); +/***** + * Get the notarisations of the block + * @param blockHash the block to examine + * @param nibs the notarisations + * @returns true on success + */ bool GetBlockNotarisations(uint256 blockHash, NotarisationsInBlock &nibs); +/*** + * Look up the value of the hash + * @param notarisationHash the key + * @param n the value + * @returns true on success + */ bool GetBackNotarisation(uint256 notarisationHash, Notarisation &n); +/*** + * Write given notarisations into db + * @param notarisations what to write + * @param the collection of db transactions + */ void WriteBackNotarisations(const NotarisationsInBlock notarisations, CDBBatch &batch); +/*** + * Erase given notarisations from db + * @param notarisations what to erase + * @param batch the collection of db transactions + */ void EraseBackNotarisations(const NotarisationsInBlock notarisations, CDBBatch &batch); +/***** + * Scan notarisationsdb backwards for blocks containing a notarisation + * for given symbol. Return height of matched notarisation or 0. + * @param height where to start the search + * @param symbol the symbol to look for + * @param scanLimitBlocks max number of blocks to search + * @param out the first Notarization found + * @returns height (0 indicates error) + */ int ScanNotarisationsDB(int height, std::string symbol, int scanLimitBlocks, Notarisation& out); -int ScanNotarisationsDB2(int height, std::string symbol, int scanLimitBlocks, Notarisation& out); -bool IsTXSCL(const char* symbol); #endif /* NOTARISATIONDB_H */ diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 3d12aee152a..b05412e3522 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -68,15 +68,7 @@ void TxConfirmStats::ClearCurrent(unsigned int nBlockHeight) unsigned int TxConfirmStats::FindBucketIndex(double val) { - extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; - auto it = bucketMap.lower_bound(val); - if ( it != bucketMap.end() ) - { - //static uint32_t counter; - //if ( counter++ < 1 ) - // fprintf(stderr,"%s FindBucketIndex violation: from val %f\n",ASSETCHAINS_SYMBOL,val); - } - return it->second; + return bucketMap.lower_bound(val)->second; } void TxConfirmStats::Record(int blocksToConfirm, double val) diff --git a/src/pow.cpp b/src/pow.cpp index 0ab464906c4..c4bd11179b6 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -29,14 +29,16 @@ #include "streams.h" #include "uint256.h" #include "util.h" +#include "komodo.h" #include "komodo_notary.h" +#include "komodo_extern_globals.h" +#include "komodo_bitcoind.h" #include "sodium.h" #ifdef ENABLE_RUST #include "librustzcash.h" #endif // ENABLE_RUST -uint32_t komodo_chainactive_timestamp(); #include "komodo_defs.h" @@ -383,7 +385,9 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead if (pindexFirst == NULL) return nProofOfWorkLimit; - bool fNegative,fOverflow; int32_t zawyflag = 0; arith_uint256 easy,origtarget,bnAvg {bnTot / params.nPowAveragingWindow}; + bool fNegative,fOverflow; int32_t zawyflag = 0; + arith_uint256 easy,origtarget; + arith_uint256 bnAvg{bnTot / params.nPowAveragingWindow}; // average number of bits in the lookback window nbits = CalculateNextWorkRequired(bnAvg, pindexLast->GetMedianTimePast(), pindexFirst->GetMedianTimePast(), params); if ( ASSETCHAINS_ADAPTIVEPOW > 0 ) { @@ -497,9 +501,16 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead return(nbits); } +/**** + * @brief calculate the nBits value (work required) for the next block + * @param bnAvg the average nBits value (work required) across the lookback window + * @param nLastBlockTime the time of the most recent block in the lookback window + * @param nFirstBlockTime the time of the first block in the lookback window + * @param params the chain's consensus parameters + * @return the nBits value for the next block + */ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, - int64_t nLastBlockTime, int64_t nFirstBlockTime, - const Consensus::Params& params) + int64_t nLastBlockTime, int64_t nFirstBlockTime, const Consensus::Params& params) { // Limit adjustment step // Use medians to prevent time-warp attacks @@ -522,7 +533,7 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, else bnLimit = UintToArith256(params.powAlternate); - const arith_uint256 bnPowLimit = bnLimit; //UintToArith256(params.powLimit); + const arith_uint256 bnPowLimit = bnLimit; arith_uint256 bnNew {bnAvg}; bnNew /= params.AveragingWindowTimespan(); bnNew *= nActualTimespan; @@ -580,11 +591,9 @@ int32_t komodo_currentheight(); void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height); bool komodo_checkopret(CBlock *pblock, CScript &merkleroot); CScript komodo_makeopret(CBlock *pblock, bool fNew); -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; #define KOMODO_ELECTION_GAP 2000 int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t blocktimes[66],int32_t *nonzpkeysp,int32_t height); -int32_t KOMODO_LOADINGBLOCKS = 1; extern std::string NOTARY_PUBKEY; @@ -610,7 +619,6 @@ bool isSecondBlockAllowed(int32_t notaryid, uint32_t blocktime, uint32_t thresho bool CheckProofOfWork(const CBlockHeader &blkHeader, uint8_t *pubkey33, int32_t height, const Consensus::Params& params) { - extern int32_t KOMODO_REWIND; uint256 hash; bool fNegative,fOverflow; uint8_t origpubkey33[33]; int32_t i,nonzpkeys=0,nonz=0,special=0,special2=0,notaryid=-1,flag = 0, mids[66]; uint32_t tiptime,blocktimes[66]; arith_uint256 bnTarget; uint8_t pubkeys[66][33]; @@ -626,7 +634,7 @@ bool CheckProofOfWork(const CBlockHeader &blkHeader, uint8_t *pubkey33, int32_t height = komodo_currentheight() + 1; //fprintf(stderr,"set height to %d\n",height); } - if ( height > 34000 && ASSETCHAINS_SYMBOL[0] == 0 ) // 0 -> non-special notary + if ( height > 34000 && chainName.isKMD() ) // 0 -> non-special notary { special = komodo_chosennotary(¬aryid,height,pubkey33,tiptime); for (i=0; i<33; i++) @@ -667,7 +675,7 @@ bool CheckProofOfWork(const CBlockHeader &blkHeader, uint8_t *pubkey33, int32_t /* in KMD chain after nHeightAfterGAPSecondBlockAllowed height we should allow notary nodes to mine a second block if nMaxGAPAllowed since last block passed */ - if (ASSETCHAINS_SYMBOL[0] == 0 && height > nHeightAfterGAPSecondBlockAllowed) + if (chainName.isKMD() && height > nHeightAfterGAPSecondBlockAllowed) { const uint32_t &blocktime = blkHeader.nTime; if (blocktime /* upcoming block time */ >= tiptime /* last block in chain time */ + nMaxGAPAllowed && @@ -729,15 +737,6 @@ bool CheckProofOfWork(const CBlockHeader &blkHeader, uint8_t *pubkey33, int32_t if ( (flag != 0 || special2 > 0) && special2 != -2 ) { bnTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); - /* - const void* pblock = &blkHeader; - CScript merkleroot = CScript(); - if ( height > nDecemberHardforkHeight && !komodo_checkopret((CBlock*)pblock, merkleroot) ) // December 2019 hardfork - { - fprintf(stderr, "failed or missing expected.%s != %s\n", komodo_makeopret((CBlock*)pblock, false).ToString().c_str(), merkleroot.ToString().c_str()); - return false; - } - */ } } } @@ -749,15 +748,13 @@ bool CheckProofOfWork(const CBlockHeader &blkHeader, uint8_t *pubkey33, int32_t arith_uint256 bnMaxPoSdiff; bnTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); } - //else if ( ASSETCHAINS_ADAPTIVEPOW > 0 && ASSETCHAINS_STAKED == 0 ) - // bnTarget = komodo_adaptivepow_target(height,bnTarget,blkHeader.nTime); // Check proof of work matches claimed amount if ( UintToArith256(hash = blkHeader.GetHash()) > bnTarget ) { - if ( KOMODO_LOADINGBLOCKS != 0 ) + if ( KOMODO_LOADINGBLOCKS ) return true; - if ( ASSETCHAINS_SYMBOL[0] != 0 || height > 792000 ) + if ( !chainName.isKMD() || height > 792000 ) { //if ( 0 && height > 792000 ) if ( Params().NetworkIDString() != "regtest" ) @@ -778,12 +775,7 @@ bool CheckProofOfWork(const CBlockHeader &blkHeader, uint8_t *pubkey33, int32_t return false; } } - /*for (i=31; i>=0; i--) - fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); - fprintf(stderr," hash vs "); - for (i=31; i>=0; i--) - fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); - fprintf(stderr," height.%d notaryid.%d PoW valid\n",height,notaryid);*/ + return true; } diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index c8b9a417df4..8bbd9dca7b8 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -711,11 +711,6 @@ class CTransaction return (vin.size() == 1 && vin[0].prevout.n == 10e8); } - bool IsPegsImport() const - { - return (ASSETCHAINS_SELFIMPORT=="PEGSCC" && vin[0].prevout.n == 10e8); - } - friend bool operator==(const CTransaction& a, const CTransaction& b) { return a.hash == b.hash; diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 32d92bbbe4f..bff14d1bd37 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -17,7 +17,7 @@ #include "util.h" #include "wallet/db.h" #include "wallet/wallet.h" - +#include "assetchain.h" #include #include @@ -266,10 +266,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco if (wtx.IsCoinBase()) { - extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - COINBASE_MATURITY = _COINBASE_MATURITY; - quint32 numBlocksToMaturity = COINBASE_MATURITY + 1; + quint32 numBlockToMaturity = 100 + 1; // COINBASE_MATURITY + 1 strHTML += "
" + tr("Generated coins must mature %1 blocks and have any applicable time locks open before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to \"not accepted\" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.").arg(QString::number(numBlocksToMaturity)) + "
"; // we need to display any possible CLTV lock time } diff --git a/src/rest.cpp b/src/rest.cpp index 3fb87f8f386..18f4e61b45f 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2017-2022 The Zcash developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -28,6 +29,8 @@ #include "txmempool.h" #include "utilstrencodings.h" #include "version.h" +#include "rpc/rawtransaction.h" +#include "rpc/blockchain.h" #include #include @@ -71,13 +74,6 @@ struct CCoin { } }; -extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); -extern UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false); -extern UniValue mempoolInfoToJSON(); -extern UniValue mempoolToJSON(bool fVerbose = false); -extern void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); -extern UniValue blockheaderToJSON(const CBlockIndex* blockindex); - static bool RESTERR(HTTPRequest* req, enum HTTPStatusCode status, string message) { req->WriteHeader("Content-Type", "text/plain"); @@ -154,6 +150,7 @@ static bool rest_headers(HTTPRequest* req, std::vector headers; headers.reserve(count); + CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION); { LOCK(cs_main); BlockMap::const_iterator it = mapBlockIndex.find(hash); @@ -164,11 +161,16 @@ static bool rest_headers(HTTPRequest* req, break; pindex = chainActive.Next(pindex); } - } - CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION); - BOOST_FOREACH(const CBlockIndex *pindex, headers) { - ssHeader << pindex->GetBlockHeader(); + if (rf == RF_BINARY || rf == RF_HEX) { + try { + for (const CBlockIndex *pindex : headers) { + ssHeader << pindex->GetBlockHeader(); + } + } catch (const std::runtime_error&) { + return RESTERR(req, HTTP_INTERNAL_SERVER_ERROR, "Failed to read index entry"); + } + } } switch (rf) { @@ -548,7 +550,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) // serialize data // use exact same output as mentioned in Bip64 CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION); - ssGetUTXOResponse << chainActive.Height() << chainActive.LastTip()->GetBlockHash() << bitmap << outs; + ssGetUTXOResponse << chainActive.Height() << chainActive.Tip()->GetBlockHash() << bitmap << outs; string ssGetUTXOResponseString = ssGetUTXOResponse.str(); req->WriteHeader("Content-Type", "application/octet-stream"); @@ -558,7 +560,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) case RF_HEX: { CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION); - ssGetUTXOResponse << chainActive.Height() << chainActive.LastTip()->GetBlockHash() << bitmap << outs; + ssGetUTXOResponse << chainActive.Height() << chainActive.Tip()->GetBlockHash() << bitmap << outs; string strHex = HexStr(ssGetUTXOResponse.begin(), ssGetUTXOResponse.end()) + "\n"; req->WriteHeader("Content-Type", "text/plain"); @@ -572,7 +574,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) // pack in some essentials // use more or less the same output as mentioned in Bip64 objGetUTXOResponse.push_back(Pair("chainHeight", chainActive.Height())); - objGetUTXOResponse.push_back(Pair("chaintipHash", chainActive.LastTip()->GetBlockHash().GetHex())); + objGetUTXOResponse.push_back(Pair("chaintipHash", chainActive.Tip()->GetBlockHash().GetHex())); objGetUTXOResponse.push_back(Pair("bitmap", bitmapStringRepresentation)); UniValue utxos(UniValue::VARR); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 412e2873426..3eb9b11422d 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2019-2022 The Zcash developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -36,6 +37,15 @@ #include "script/script_error.h" #include "script/sign.h" #include "script/standard.h" +#include "komodo_defs.h" +#include "komodo_structs.h" +#include "komodo_globals.h" +#include "komodo_notary.h" +#include "komodo_bitcoind.h" +#include "komodo_utils.h" +#include "komodo_kv.h" +#include "komodo_gateway.h" +#include "rpc/rawtransaction.h" #include @@ -44,16 +54,17 @@ #include #include "cc/CCinclude.h" -#include "cc/CCPrices.h" using namespace std; -extern int32_t KOMODO_INSYNC; -extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); -void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); -int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp); -#include "komodo_defs.h" +// TODO: remove +//extern int32_t KOMODO_INSYNC; +//extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); +//void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); +//int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp); +//#include "komodo_defs.h" #include "komodo_structs.h" +#include "komodo_interest.h" double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty) { @@ -61,10 +72,10 @@ double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficul // minimum difficulty = 1.0. if (blockindex == NULL) { - if (chainActive.LastTip() == NULL) + if (chainActive.Tip() == NULL) return 1.0; else - blockindex = chainActive.LastTip(); + blockindex = chainActive.Tip(); } uint32_t bits; @@ -150,7 +161,7 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex) result.push_back(Pair("finalsaplingroot", blockindex->hashFinalSaplingRoot.GetHex())); result.push_back(Pair("time", (int64_t)blockindex->nTime)); result.push_back(Pair("nonce", blockindex->nNonce.GetHex())); - result.push_back(Pair("solution", HexStr(blockindex->nSolution))); + result.pushKV("solution", HexStr(blockindex->GetBlockHeader().nSolution)); result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits))); result.push_back(Pair("difficulty", GetDifficulty(blockindex))); result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); @@ -370,7 +381,7 @@ UniValue getbestblockhash(const UniValue& params, bool fHelp, const CPubKey& myp ); LOCK(cs_main); - return chainActive.LastTip()->GetBlockHash().GetHex(); + return chainActive.Tip()->GetBlockHash().GetHex(); } UniValue getdifficulty(const UniValue& params, bool fHelp, const CPubKey& mypk) @@ -619,6 +630,37 @@ UniValue getblockhashes(const UniValue& params, bool fHelp, const CPubKey& mypk) return result; } +//! Sanity-check a height argument and interpret negative values. +int interpretHeightArg(int nHeight, int currentHeight) +{ + if (nHeight < 0) { + nHeight += currentHeight + 1; + } + if (nHeight < 0 || nHeight > currentHeight) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); + } + return nHeight; +} + +//! Parse and sanity-check a height argument, return its integer representation. +int parseHeightArg(const std::string& strHeight, int currentHeight) +{ + // std::stoi allows (locale-dependent) whitespace and optional '+' sign, + // whereas we want to be strict. + regex r("(?:(-?)[1-9][0-9]*|[0-9]+)"); + if (!regex_match(strHeight, r)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter"); + } + int nHeight; + try { + nHeight = std::stoi(strHeight); + } + catch (const std::exception &e) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter"); + } + return interpretHeightArg(nHeight, currentHeight); +} + UniValue getblockhash(const UniValue& params, bool fHelp, const CPubKey& mypk) { if (fHelp || params.size() != 1) @@ -767,15 +809,18 @@ UniValue getblockheader(const UniValue& params, bool fHelp, const CPubKey& mypk) CBlockIndex* pblockindex = mapBlockIndex[hash]; - if (!fVerbose) - { + try { + if (!fVerbose) { CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); ssBlock << pblockindex->GetBlockHeader(); std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()); return strHex; - } - + } else { return blockheaderToJSON(pblockindex); + } + } catch (const runtime_error&) { + throw JSONRPCError(RPC_DATABASE_ERROR, "Failed to read index entry"); + } } UniValue getblock(const UniValue& params, bool fHelp, const CPubKey& mypk) @@ -959,14 +1004,14 @@ UniValue kvsearch(const UniValue& params, bool fHelp, const CPubKey& mypk) LOCK(cs_main); if ( (keylen= (int32_t)strlen(params[0].get_str().c_str())) > 0 ) { - ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL))); - ret.push_back(Pair("currentheight", (int64_t)chainActive.LastTip()->nHeight)); + ret.push_back(Pair("coin",chainName.ToString())); + ret.push_back(Pair("currentheight", (int64_t)chainActive.Tip()->nHeight)); ret.push_back(Pair("key",params[0].get_str())); ret.push_back(Pair("keylen",keylen)); if ( keylen < sizeof(key) ) { memcpy(key,params[0].get_str().c_str(),keylen); - if ( (valuesize= komodo_kvsearch(&refpubkey,chainActive.LastTip()->nHeight,&flags,&height,value,key,keylen)) >= 0 ) + if ( (valuesize= komodo_kvsearch(&refpubkey,chainActive.Tip()->nHeight,&flags,&height,value,key,keylen)) >= 0 ) { std::string val; char *valuestr; val.resize(valuesize); @@ -994,7 +1039,7 @@ UniValue minerids(const UniValue& params, bool fHelp, const CPubKey& mypk) LOCK(cs_main); int32_t height = atoi(params[0].get_str().c_str()); if ( height <= 0 ) - height = chainActive.LastTip()->nHeight; + height = chainActive.Tip()->nHeight; else { CBlockIndex *pblockindex = chainActive[height]; @@ -1056,8 +1101,8 @@ UniValue notaries(const UniValue& params, bool fHelp, const CPubKey& mypk) else timestamp = (uint32_t)time(NULL); if ( height < 0 ) { - height = chainActive.LastTip()->nHeight; - timestamp = chainActive.LastTip()->GetBlockTime(); + height = chainActive.Tip()->nHeight; + timestamp = chainActive.Tip()->GetBlockTime(); } else if ( params.size() < 2 ) { @@ -1100,391 +1145,6 @@ UniValue notaries(const UniValue& params, bool fHelp, const CPubKey& mypk) return ret; } -int32_t komodo_pending_withdraws(char *opretstr); -int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base); -extern char CURRENCIES[][8]; - -UniValue paxpending(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR); char opretbuf[10000*2]; int32_t opretlen,baseid; uint64_t available,deposited,issued,withdrawn,approved,redeemed; - if ( fHelp || params.size() != 0 ) - throw runtime_error("paxpending needs no args\n"); - LOCK(cs_main); - if ( (opretlen= komodo_pending_withdraws(opretbuf)) > 0 ) - ret.push_back(Pair("withdraws", opretbuf)); - else ret.push_back(Pair("withdraws", (char *)"")); - for (baseid=0; baseid<32; baseid++) - { - UniValue item(UniValue::VOBJ); UniValue obj(UniValue::VOBJ); - if ( pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,CURRENCIES[baseid]) == 0 ) - { - if ( deposited != 0 || issued != 0 || withdrawn != 0 || approved != 0 || redeemed != 0 ) - { - item.push_back(Pair("available", ValueFromAmount(available))); - item.push_back(Pair("deposited", ValueFromAmount(deposited))); - item.push_back(Pair("issued", ValueFromAmount(issued))); - item.push_back(Pair("withdrawn", ValueFromAmount(withdrawn))); - item.push_back(Pair("approved", ValueFromAmount(approved))); - item.push_back(Pair("redeemed", ValueFromAmount(redeemed))); - obj.push_back(Pair(CURRENCIES[baseid],item)); - a.push_back(obj); - } - } - } - ret.push_back(Pair("fiatstatus", a)); - return ret; -} - -UniValue paxprice(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - if ( fHelp || params.size() > 4 || params.size() < 2 ) - throw runtime_error("paxprice \"base\" \"rel\" height\n"); - LOCK(cs_main); - UniValue ret(UniValue::VOBJ); uint64_t basevolume=0,relvolume,seed; - std::string base = params[0].get_str(); - std::string rel = params[1].get_str(); - int32_t height; - if ( params.size() == 2 ) - height = chainActive.LastTip()->nHeight; - else height = atoi(params[2].get_str().c_str()); - //if ( params.size() == 3 || (basevolume= COIN * atof(params[3].get_str().c_str())) == 0 ) - basevolume = 100000; - relvolume = komodo_paxprice(&seed,height,(char *)base.c_str(),(char *)rel.c_str(),basevolume); - ret.push_back(Pair("base", base)); - ret.push_back(Pair("rel", rel)); - ret.push_back(Pair("height", height)); - char seedstr[32]; - sprintf(seedstr,"%llu",(long long)seed); - ret.push_back(Pair("seed", seedstr)); - if ( height < 0 || height > chainActive.Height() ) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); - else - { - CBlockIndex *pblockindex = chainActive[height]; - if ( pblockindex != 0 ) - ret.push_back(Pair("timestamp", (int64_t)pblockindex->nTime)); - if ( basevolume != 0 && relvolume != 0 ) - { - ret.push_back(Pair("price",((double)relvolume / (double)basevolume))); - ret.push_back(Pair("invprice",((double)basevolume / (double)relvolume))); - ret.push_back(Pair("basevolume",ValueFromAmount(basevolume))); - ret.push_back(Pair("relvolume",ValueFromAmount(relvolume))); - } else ret.push_back(Pair("error", "overflow or error in one or more of parameters")); - } - return ret; -} -// fills pricedata with raw price, correlated and smoothed values for numblock -/*int32_t prices_extract(int64_t *pricedata,int32_t firstheight,int32_t numblocks,int32_t ind) -{ - int32_t height,i,n,width,numpricefeeds = -1; uint64_t seed,ignore,rngval; uint32_t rawprices[1440*6],*ptr; int64_t *tmpbuf; - width = numblocks+PRICES_DAYWINDOW*2+PRICES_SMOOTHWIDTH; // need 2*PRICES_DAYWINDOW previous raw price points to calc PRICES_DAYWINDOW correlated points to calc, in turn, smoothed point - komodo_heightpricebits(&seed,rawprices,firstheight + numblocks - 1); - if ( firstheight < width ) - return(-1); - for (i=0; i2; i++,ht--) - { - if ( ht < 0 || ht > chainActive.Height() ) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); - else - { - if ( (n= komodo_heightpricebits(0,rawprices,ht)) > 0 ) - { - if ( n != numpricefeeds ) - throw JSONRPCError(RPC_INVALID_PARAMETER, "numprices != first numprices"); - else - { - for (j=0; j= width ) - { - for (i=0; i= 0 ) - { - if ( checkprices[1] != correlated[i] ) - { - //fprintf(stderr,"ind.%d ht.%d %.8f != %.8f\n",j,nextheight-1-i,(double)checkprices[1]/COIN,(double)correlated[i]/COIN); - correlated[i] = checkprices[1]; - } - } - } - } - tmpbuf = (int64_t *)calloc(sizeof(int64_t),2*PRICES_DAYWINDOW); - for (i=0; i= 0 ) - { - if ( checkprices[2] != smoothed ) - { - fprintf(stderr,"ind.%d ht.%d %.8f != %.8f\n",j,nextheight-1-i,(double)checkprices[2]/COIN,(double)smoothed/COIN); - smoothed = checkprices[2]; - } - } - UniValue parr(UniValue::VARR); - parr.push_back(ValueFromAmount((int64_t)prices[offset] * komodo_pricemult(j))); - parr.push_back(ValueFromAmount(correlated[i])); - parr.push_back(ValueFromAmount(smoothed)); - // compare to alternate method - p.push_back(parr); - } - free(tmpbuf); - } - else - { - for (i=0; i vexpr; - SplitStr(sexpr, vexpr); - - // debug print parsed strings: - std::cerr << "parsed synthetic: "; - for (auto s : vexpr) - std::cerr << s << " "; - std::cerr << std::endl; - - return PricesBet(txfee, amount, leverage, vexpr); -} - -// pricesaddfunding rpc implementation -UniValue pricesaddfunding(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - if (fHelp || params.size() != 2) - throw runtime_error("pricesaddfunding bettxid amount\n" - "where amount is in coins\n"); - LOCK(cs_main); - UniValue ret(UniValue::VOBJ); - - if (ASSETCHAINS_CBOPRET == 0) - throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices"); - - CAmount txfee = 10000; - uint256 bettxid = Parseuint256(params[0].get_str().c_str()); - if (bettxid.IsNull()) - throw runtime_error("invalid bettxid\n"); - - CAmount amount = atof(params[1].get_str().c_str()) * COIN; - if (amount <= 0) - throw runtime_error("invalid amount\n"); - - return PricesAddFunding(txfee, bettxid, amount); -} - -// rpc pricessetcostbasis implementation -UniValue pricessetcostbasis(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - if (fHelp || params.size() != 1) - throw runtime_error("pricessetcostbasis bettxid\n"); - LOCK(cs_main); - UniValue ret(UniValue::VOBJ); - - if (ASSETCHAINS_CBOPRET == 0) - throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices"); - - uint256 bettxid = Parseuint256(params[0].get_str().c_str()); - if (bettxid.IsNull()) - throw runtime_error("invalid bettxid\n"); - - int64_t txfee = 10000; - - return PricesSetcostbasis(txfee, bettxid); -} - -// pricescashout rpc implementation -UniValue pricescashout(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - if (fHelp || params.size() != 1) - throw runtime_error("pricescashout bettxid\n"); - LOCK(cs_main); - UniValue ret(UniValue::VOBJ); - - if (ASSETCHAINS_CBOPRET == 0) - throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices"); - - uint256 bettxid = Parseuint256(params[0].get_str().c_str()); - if (bettxid.IsNull()) - throw runtime_error("invalid bettxid\n"); - - int64_t txfee = 10000; - - return PricesCashout(txfee, bettxid); -} - -// pricesrekt rpc implementation -UniValue pricesrekt(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - if (fHelp || params.size() != 2) - throw runtime_error("pricesrekt bettxid height\n"); - LOCK(cs_main); - UniValue ret(UniValue::VOBJ); - - if (ASSETCHAINS_CBOPRET == 0) - throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices"); - - uint256 bettxid = Parseuint256(params[0].get_str().c_str()); - if (bettxid.IsNull()) - throw runtime_error("invalid bettxid\n"); - - int32_t height = atoi(params[0].get_str().c_str()); - - int64_t txfee = 10000; - - return PricesRekt(txfee, bettxid, height); -} - -// pricesrekt rpc implementation -UniValue pricesgetorderbook(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - if (fHelp || params.size() != 0) - throw runtime_error("pricesgetorderbook\n"); - LOCK(cs_main); - UniValue ret(UniValue::VOBJ); - - if (ASSETCHAINS_CBOPRET == 0) - throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices"); - - return PricesGetOrderbook(); -} - -// pricesrekt rpc implementation -UniValue pricesrefillfund(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - if (fHelp || params.size() != 1) - throw runtime_error("pricesrefillfund amount\n"); - LOCK(cs_main); - UniValue ret(UniValue::VOBJ); - - if (ASSETCHAINS_CBOPRET == 0) - throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices"); - - CAmount amount = atof(params[0].get_str().c_str()) * COIN; - - return PricesRefillFund(amount); -} - - UniValue gettxout(const UniValue& params, bool fHelp, const CPubKey& mypk) { if (fHelp || params.size() < 2 || params.size() > 3) @@ -1712,10 +1372,10 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp, const CPubKey& my LOCK(cs_main); double progress; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) { - progress = Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.LastTip()); + if ( chainName.isKMD() ) { + progress = Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip()); } else { - int32_t longestchain = KOMODO_LONGESTCHAIN;//komodo_longestchain(); + int32_t longestchain = KOMODO_LONGESTCHAIN; progress = (longestchain > 0 ) ? (double) chainActive.Height() / longestchain : 1.0; } UniValue obj(UniValue::VOBJ); @@ -1723,17 +1383,17 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp, const CPubKey& my obj.push_back(Pair("blocks", (int)chainActive.Height())); obj.push_back(Pair("synced", KOMODO_INSYNC!=0)); obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1)); - obj.push_back(Pair("bestblockhash", chainActive.LastTip()->GetBlockHash().GetHex())); + obj.push_back(Pair("bestblockhash", chainActive.Tip()->GetBlockHash().GetHex())); obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty())); obj.push_back(Pair("verificationprogress", progress)); - obj.push_back(Pair("chainwork", chainActive.LastTip()->nChainWork.GetHex())); + obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex())); obj.push_back(Pair("pruned", fPruneMode)); SproutMerkleTree tree; pcoinsTip->GetSproutAnchorAt(pcoinsTip->GetBestAnchor(SPROUT), tree); obj.push_back(Pair("commitments", static_cast(tree.size()))); - CBlockIndex* tip = chainActive.LastTip(); + CBlockIndex* tip = chainActive.Tip(); UniValue valuePools(UniValue::VARR); valuePools.push_back(ValuePoolDesc("sprout", tip->nChainSproutValue, boost::none)); valuePools.push_back(ValuePoolDesc("sapling", tip->nChainSaplingValue, boost::none)); @@ -1759,7 +1419,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp, const CPubKey& my if (fPruneMode) { - CBlockIndex *block = chainActive.LastTip(); + CBlockIndex *block = chainActive.Tip(); while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) block = block->pprev; @@ -1852,7 +1512,7 @@ UniValue getchaintips(const UniValue& params, bool fHelp, const CPubKey& mypk) //pthread_mutex_unlock(&mutex); // Always report the currently active tip. - setTips.insert(chainActive.LastTip()); + setTips.insert(chainActive.Tip()); /* Construct the output array. */ UniValue res(UniValue::VARR); const CBlockIndex *forked; @@ -1895,6 +1555,121 @@ UniValue getchaintips(const UniValue& params, bool fHelp, const CPubKey& mypk) return res; } +UniValue z_gettreestate(const UniValue& params, bool fHelp, const CPubKey& mypk) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "z_gettreestate \"hash|height\"\n" + "Return information about the given block's tree state.\n" + "\nArguments:\n" + "1. \"hash|height\" (string, required) The block hash or height. Height can be negative where -1 is the last known valid block\n" + "\nResult:\n" + "{\n" + " \"hash\": \"hash\", (string) hex block hash\n" + " \"height\": n, (numeric) block height\n" + " \"time\": n, (numeric) block time: UTC seconds since the Unix 1970-01-01 epoch\n" + " \"sprout\": {\n" + " \"skipHash\": \"hash\", (string) hash of most recent block with more information\n" + " \"commitments\": {\n" + " \"finalRoot\": \"hex\", (string)\n" + " \"finalState\": \"hex\" (string)\n" + " }\n" + " },\n" + " \"sapling\": {\n" + " \"skipHash\": \"hash\", (string) hash of most recent block with more information\n" + " \"commitments\": {\n" + " \"finalRoot\": \"hex\", (string)\n" + " \"finalState\": \"hex\" (string)\n" + " }\n" + " }\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("z_gettreestate", "\"00000000febc373a1da2bd9f887b105ad79ddc26ac26c2b28652d64e5207c5b5\"") + + HelpExampleRpc("z_gettreestate", "\"00000000febc373a1da2bd9f887b105ad79ddc26ac26c2b28652d64e5207c5b5\"") + + HelpExampleCli("z_gettreestate", "12800") + + HelpExampleRpc("z_gettreestate", "12800") + ); + + LOCK(cs_main); + + std::string strHash = params[0].get_str(); + + // If height is supplied, find the hash + if (strHash.size() < (2 * sizeof(uint256))) { + strHash = chainActive[parseHeightArg(strHash, chainActive.Height())]->GetBlockHash().GetHex(); + } + uint256 hash(uint256S(strHash)); + + if (mapBlockIndex.count(hash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + const CBlockIndex* const pindex = mapBlockIndex[hash]; + if (!chainActive.Contains(pindex)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Requested block is not part of the main chain"); + } + + UniValue res(UniValue::VOBJ); + res.pushKV("hash", pindex->GetBlockHash().GetHex()); + res.pushKV("height", pindex->nHeight); + res.pushKV("time", int64_t(pindex->nTime)); + + // sprout + { + UniValue sprout_result(UniValue::VOBJ); + UniValue sprout_commitments(UniValue::VOBJ); + sprout_commitments.pushKV("finalRoot", pindex->hashFinalSproutRoot.GetHex()); + SproutMerkleTree tree; + if (pcoinsTip->GetSproutAnchorAt(pindex->hashFinalSproutRoot, tree)) { + CDataStream s(SER_NETWORK, PROTOCOL_VERSION); + s << tree; + sprout_commitments.pushKV("finalState", HexStr(s.begin(), s.end())); + } else { + // Set skipHash to the most recent block that has a finalState. + const CBlockIndex* pindex_skip = pindex->pprev; + while (pindex_skip && !pcoinsTip->GetSproutAnchorAt(pindex_skip->hashFinalSproutRoot, tree)) { + pindex_skip = pindex_skip->pprev; + } + if (pindex_skip) { + sprout_result.pushKV("skipHash", pindex_skip->GetBlockHash().GetHex()); + } + } + sprout_result.pushKV("commitments", sprout_commitments); + res.pushKV("sprout", sprout_result); + } + + // sapling + int sapling_activation_height = Params().GetConsensus().vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight; /* ASSETCHAINS_SAPLING */ + if (sapling_activation_height > Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT) + { + UniValue sapling_result(UniValue::VOBJ); + UniValue sapling_commitments(UniValue::VOBJ); + sapling_commitments.pushKV("finalRoot", pindex->hashFinalSaplingRoot.GetHex()); + bool need_skiphash = false; + SaplingMerkleTree tree; + if (pcoinsTip->GetSaplingAnchorAt(pindex->hashFinalSaplingRoot, tree)) { + CDataStream s(SER_NETWORK, PROTOCOL_VERSION); + s << tree; + sapling_commitments.pushKV("finalState", HexStr(s.begin(), s.end())); + } else { + // Set skipHash to the most recent block that has a finalState. + const CBlockIndex* pindex_skip = pindex->pprev; + auto saplingActive = [&](const CBlockIndex* pindex_cur) -> bool { + return pindex_cur && pindex_cur->nHeight >= sapling_activation_height; + }; + while (saplingActive(pindex_skip) && !pcoinsTip->GetSaplingAnchorAt(pindex_skip->hashFinalSaplingRoot, tree)) { + pindex_skip = pindex_skip->pprev; + } + if (saplingActive(pindex_skip)) { + sapling_result.pushKV("skipHash", pindex_skip->GetBlockHash().GetHex()); + } + } + sapling_result.pushKV("commitments", sapling_commitments); + res.pushKV("sapling", sapling_result); + } + + return res; +} + + UniValue mempoolInfoToJSON() { UniValue ret(UniValue::VOBJ); @@ -2097,6 +1872,7 @@ static const CRPCCommand commands[] = { "blockchain", "getblockhash", &getblockhash, true }, { "blockchain", "getblockheader", &getblockheader, true }, { "blockchain", "getchaintips", &getchaintips, true }, + { "blockchain", "z_gettreestate", &z_gettreestate, true }, { "blockchain", "getchaintxstats", &getchaintxstats, true }, { "blockchain", "getdifficulty", &getdifficulty, true }, { "blockchain", "getmempoolinfo", &getmempoolinfo, true }, diff --git a/src/rpc/blockchain.h b/src/rpc/blockchain.h new file mode 100644 index 00000000000..a731b5463bc --- /dev/null +++ b/src/rpc/blockchain.h @@ -0,0 +1,20 @@ +#pragma once +/****************************************************************************** + * Copyright © 2021 Komodo Core Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + +UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false); +UniValue mempoolInfoToJSON(); +UniValue mempoolToJSON(bool fVerbose = false); +UniValue blockheaderToJSON(const CBlockIndex* blockindex); diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index e67153082ae..1c653c77a03 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -160,9 +160,6 @@ static const CRPCConvertParam vRPCConvertParams[] = { "z_shieldcoinbase", 3}, { "z_getoperationstatus", 0}, { "z_getoperationresult", 0}, - { "paxprice", 4 }, - { "paxprices", 3 }, - { "paxpending", 0 }, { "notaries", 2 }, { "minerids", 1 }, { "kvsearch", 1 }, diff --git a/src/rpc/crosschain.cpp b/src/rpc/crosschain.cpp index dd40f1b233f..85be7da093c 100644 --- a/src/rpc/crosschain.cpp +++ b/src/rpc/crosschain.cpp @@ -35,10 +35,15 @@ #include "script/sign.h" #include "script/standard.h" #include "notaries_staked.h" +#include "komodo_notary.h" +#include "komodo_bitcoind.h" +#include "komodo_ccdata.h" +#include "notaries_staked.h" #include "key_io.h" #include "cc/CCImportGateway.h" #include "cc/CCtokens.h" +#include "cc/import.h" #include #include @@ -46,24 +51,6 @@ using namespace std; -extern std::string CCerror; -extern std::string ASSETCHAINS_SELFIMPORT; -extern uint16_t ASSETCHAINS_CODAPORT, ASSETCHAINS_BEAMPORT; -int32_t ensure_CCrequirements(uint8_t evalcode); -bool EnsureWalletIsAvailable(bool avoidException); - - -int32_t komodo_MoM(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip); -int32_t komodo_MoMoMdata(char *hexstr,int32_t hexsize,struct komodo_ccdataMoMoM *mdata,char *symbol,int32_t kmdheight,int32_t notarized_height); -struct komodo_ccdata_entry *komodo_allMoMs(int32_t *nump,uint256 *MoMoMp,int32_t kmdstarti,int32_t kmdendi); -uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth); -int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); -extern std::string ASSETCHAINS_SELFIMPORT; - -//std::string MakeSelfImportSourceTx(CTxDestination &dest, int64_t amount, CMutableTransaction &mtx); -//int32_t GetSelfimportProof(std::string source, CMutableTransaction &mtx, CScript &scriptPubKey, TxProof &proof, std::string rawsourcetx, int32_t &ivout, uint256 sourcetxid, uint64_t burnAmount); -std::string MakeCodaImportTx(uint64_t txfee, std::string receipt, std::string srcaddr, std::vector vouts); - UniValue assetchainproof(const UniValue& params, bool fHelp, const CPubKey& mypk) { uint256 hash; @@ -74,7 +61,7 @@ UniValue assetchainproof(const UniValue& params, bool fHelp, const CPubKey& mypk hash = uint256S(params[0].get_str()); CTransaction tx; - auto proof = GetAssetchainProof(hash,tx); + auto proof = CrossChain::GetAssetchainProof(hash,tx); auto proofData = E_MARSHAL(ss << proof); return HexStr(proofData); } @@ -106,7 +93,7 @@ UniValue height_MoM(const UniValue& params, bool fHelp, const CPubKey& mypk) } //fprintf(stderr,"height_MoM height.%d\n",height); depth = komodo_MoM(¬arized_height,&MoM,&kmdtxid,height,&MoMoM,&MoMoMoffset,&MoMoMdepth,&kmdstarti,&kmdendi); - ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL))); + ret.push_back(Pair("coin", chainName.ToString())); ret.push_back(Pair("height",height)); ret.push_back(Pair("timestamp",(uint64_t)timestamp)); if ( depth > 0 ) @@ -115,7 +102,7 @@ UniValue height_MoM(const UniValue& params, bool fHelp, const CPubKey& mypk) ret.push_back(Pair("notarized_height",notarized_height)); ret.push_back(Pair("MoM",MoM.GetHex())); ret.push_back(Pair("kmdtxid",kmdtxid.GetHex())); - if ( ASSETCHAINS_SYMBOL[0] != 0 ) + if ( !chainName.isKMD() ) { ret.push_back(Pair("MoMoM",MoMoM.GetHex())); ret.push_back(Pair("MoMoMoffset",MoMoMoffset)); @@ -142,7 +129,7 @@ UniValue MoMoMdata(const UniValue& params, bool fHelp, const CPubKey& mypk) uint256 destNotarisationTxid; std::vector moms; - uint256 MoMoM = CalculateProofRoot(symbol, ccid, kmdheight-5, moms, destNotarisationTxid); + uint256 MoMoM = CrossChain::CalculateProofRoot(symbol, ccid, kmdheight-5, moms, destNotarisationTxid); UniValue valMoms(UniValue::VARR); for (int i=0; i txData(ParseHexV(params[0], "argument 1")); @@ -204,7 +191,7 @@ UniValue migrate_converttoexport(const UniValue& params, bool fHelp, const CPubK if (targetSymbol.size() == 0 || targetSymbol.size() > 32) throw runtime_error("targetSymbol length must be >0 and <=32"); - if (strcmp(ASSETCHAINS_SYMBOL,targetSymbol.c_str()) == 0) + if ( chainName.isSymbol( targetSymbol) ) throw runtime_error("cant send a coin to the same chain"); /// Tested 44 vins p2pkh inputs as working. Set this at 25, but its a tx size limit. @@ -222,13 +209,7 @@ UniValue migrate_converttoexport(const UniValue& params, bool fHelp, const CPubK if (burnAmount > 1000000LL*COIN) throw JSONRPCError(RPC_TYPE_ERROR, "Cannot export more than 1 million coins per export."); - /* note: we marshal to rawproof in a different way (to be able to add other objects) - rawproof.resize(strlen(ASSETCHAINS_SYMBOL)); - ptr = rawproof.data(); - for (i=0; i 32) throw runtime_error("targetSymbol length must be >0 and <=32"); - if (strcmp(ASSETCHAINS_SYMBOL, targetSymbol.c_str()) == 0) + if ( chainName.isSymbol(targetSymbol) ) throw runtime_error("cant send a coin to the same chain"); std::string dest_addr_or_pubkey = params[1].get_str(); @@ -307,8 +288,7 @@ UniValue migrate_createburntransaction(const UniValue& params, bool fHelp, const CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - const std::string chainSymbol(ASSETCHAINS_SYMBOL); - std::vector rawproof; //(chainSymbol.begin(), chainSymbol.end()); + std::vector rawproof; if (tokenid.IsNull()) { // coins int64_t inputs; @@ -324,7 +304,7 @@ UniValue migrate_createburntransaction(const UniValue& params, bool fHelp, const mtx.vout.push_back(CTxOut(burnAmount, scriptPubKey)); // 'model' vout ret.push_back(Pair("payouts", HexStr(E_MARSHAL(ss << mtx.vout)))); // save 'model' vout - rawproof = E_MARSHAL(ss << chainSymbol); // add src chain name + rawproof = E_MARSHAL(ss << chainName.symbol()); // add src chain name CTxOut burnOut = MakeBurnOutput(burnAmount+txfee, ccid, targetSymbol, mtx.vout, rawproof); //make opret with burned amount @@ -393,7 +373,7 @@ UniValue migrate_createburntransaction(const UniValue& params, bool fHelp, const mtx.vout.push_back(CTxOut((CAmount)0, EncodeTokenCreateOpRet('c', vorigpubkey, name, description, voprets))); // make token import opret ret.push_back(Pair("payouts", HexStr(E_MARSHAL(ss << mtx.vout)))); // save payouts for import tx - rawproof = E_MARSHAL(ss << chainSymbol << tokenbasetx); // add src chain name and token creation tx + rawproof = E_MARSHAL(ss << chainName.symbol() << tokenbasetx); // add src chain name and token creation tx CTxOut burnOut = MakeBurnOutput(0, ccid, targetSymbol, mtx.vout, rawproof); //make opret with amount=0 because tokens are burned, not coins (see next vout) mtx.vout.clear(); // remove payouts @@ -502,13 +482,13 @@ void CheckBurnTxSource(uint256 burntxid, UniValue &info) { throw std::runtime_error("No opreturn in burn tx"); - if (sourceSymbol != ASSETCHAINS_SYMBOL) + if ( !chainName.isSymbol(sourceSymbol) ) throw std::runtime_error("Incorrect source chain in rawproof"); if (targetCCid != ASSETCHAINS_CC) throw std::runtime_error("Incorrect CCid in burn tx"); - if (targetSymbol == ASSETCHAINS_SYMBOL) + if ( chainName.isSymbol(targetSymbol) ) throw std::runtime_error("Must not be called on the destination chain"); // fill info to return for the notary operator (if manual notarization) or user @@ -548,7 +528,7 @@ UniValue migrate_createimporttransaction(const UniValue& params, bool fHelp, con if (ASSETCHAINS_CC < KOMODO_FIRSTFUNGIBLEID) throw runtime_error("-ac_cc < KOMODO_FIRSTFUNGIBLEID"); - if (ASSETCHAINS_SYMBOL[0] == 0) + if ( chainName.isKMD() ) throw runtime_error("Must be called on assetchain"); vector txData(ParseHexV(params[0], "argument 1")); @@ -571,7 +551,7 @@ UniValue migrate_createimporttransaction(const UniValue& params, bool fHelp, con ImportProof importProof; if (params.size() == 2) { // standard MoMoM based notarization // get MoM import proof - importProof = ImportProof(GetAssetchainProof(burnTx.GetHash(), burnTx)); + importProof = ImportProof(CrossChain::GetAssetchainProof(burnTx.GetHash(), burnTx)); } else { // notarization by manual operators notary tx UniValue info(UniValue::VOBJ); @@ -604,7 +584,7 @@ UniValue migrate_completeimporttransaction(const UniValue& params, bool fHelp, c "and extends proof to target chain proof root\n" "offset is optional, use it to increase the used KMD height, use when import fails."); - if (ASSETCHAINS_SYMBOL[0] != 0) + if ( !chainName.isKMD() ) throw runtime_error("Must be called on KMD"); CTransaction importTx; @@ -615,7 +595,7 @@ UniValue migrate_completeimporttransaction(const UniValue& params, bool fHelp, c if ( params.size() == 2 ) offset = params[1].get_int(); - CompleteImportTransaction(importTx, offset); + CrossChain::CompleteImportTransaction(importTx, offset); std::string importTxHex = HexStr(E_MARSHAL(ss << importTx)); UniValue ret(UniValue::VOBJ); @@ -644,7 +624,7 @@ UniValue migrate_checkburntransactionsource(const UniValue& params, bool fHelp, throw runtime_error("migrate_checkburntransactionsource burntxid\n\n" "checks if params stored in the burn tx match to its tx chain"); - if (ASSETCHAINS_SYMBOL[0] == 0) + if (chainName.isKMD()) throw runtime_error("Must be called on asset chain"); uint256 burntxid = Parseuint256(params[0].get_str().c_str()); @@ -672,7 +652,7 @@ UniValue migrate_createnotaryapprovaltransaction(const UniValue& params, bool fH "Creates a tx for destination chain with burn tx proof\n" "txoutproof should be retrieved by komodo-cli migrate_checkburntransactionsource call on the source chain\n" ); - if (ASSETCHAINS_SYMBOL[0] == 0) + if (chainName.isKMD()) throw runtime_error("Must be called on asset chain"); uint256 burntxid = Parseuint256(params[0].get_str().c_str()); @@ -751,10 +731,6 @@ UniValue selfimport(const UniValue& params, bool fHelp, const CPubKey& mypk) // return(0); return -1; } - else if (source == "PEGSCC") - { - return -1; - } else if (source == "PUBKEY") { ImportProof proofNull; @@ -764,7 +740,7 @@ UniValue selfimport(const UniValue& params, bool fHelp, const CPubKey& mypk) CMutableTransaction templateMtx; // prepare self-import 'quasi-burn' tx and also create vout for import tx (in mtx.vout): - if (GetSelfimportProof(sourceMtx, templateMtx, proofNull) < 0) + if ( !GetSelfimportProof(sourceMtx, templateMtx, proofNull) ) throw std::runtime_error("Failed creating selfimport template tx"); vouts = templateMtx.vout; @@ -789,7 +765,7 @@ UniValue selfimport(const UniValue& params, bool fHelp, const CPubKey& mypk) return result; } -bool GetNotarisationNotaries(uint8_t notarypubkeys[64][33], int8_t &numNN, const std::vector &vin, std::vector &NotarisationNotaries); +///bool GetNotarisationNotaries(uint8_t notarypubkeys[64][33], int8_t &numNN, const std::vector &vin, std::vector &NotarisationNotaries); UniValue importdual(const UniValue& params, bool fHelp, const CPubKey& mypk) @@ -834,10 +810,6 @@ UniValue importdual(const UniValue& params, bool fHelp, const CPubKey& mypk) // confirm via ASSETCHAINS_CODAPORT that burnTx/hash is a valid CODA burn // return(0); } - else if (source == "PEGSCC") - { - return -1; - } RETURN_IF_ERROR(CCerror); if ( hex.size() > 0 ) { diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index d12a17342a5..e043efc9e6d 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -23,6 +23,7 @@ #include "consensus/consensus.h" #include "consensus/validation.h" #include "core_io.h" +#include "komodo_bitcoind.h" #ifdef ENABLE_MINING #include "crypto/equihash.h" #endif @@ -48,14 +49,6 @@ using namespace std; -#include "komodo_defs.h" - -extern int32_t ASSETCHAINS_FOUNDERS; -uint64_t komodo_commission(const CBlock *pblock,int32_t height); -int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex); -arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive); -int32_t komodo_newStakerActive(int32_t height, uint32_t timestamp); - /** * Return average network hashes per second based on the last 'lookup' blocks, * or over the difficulty averaging window if 'lookup' is nonpositive. @@ -63,7 +56,7 @@ int32_t komodo_newStakerActive(int32_t height, uint32_t timestamp); */ int64_t GetNetworkHashPS(int lookup, int height) { - CBlockIndex *pb = chainActive.LastTip(); + CBlockIndex *pb = chainActive.Tip(); if (height >= 0 && height < chainActive.Height()) pb = chainActive[height]; @@ -193,7 +186,99 @@ UniValue getgenerate(const UniValue& params, bool fHelp, const CPubKey& mypk) return obj; } -extern uint8_t NOTARY_PUBKEY33[33]; +/***** + * Calculate the PoW value for a block + * @param pblock the block to work on + * @returns true when the PoW is completed + */ +bool CalcPoW(CBlock *pblock) +{ + unsigned int n = Params().EquihashN(); + unsigned int k = Params().EquihashK(); + // Hash state + crypto_generichash_blake2b_state eh_state; + EhInitialiseState(n, k, eh_state); + + // I = the block header minus nonce and solution. + CEquihashInput I{*pblock}; + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << I; + + // H(I||... + crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size()); + + while (true) { + // Yes, there is a chance every nonce could fail to satisfy the -regtest + // target -- 1 in 2^(2^256). That ain't gonna happen + pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1); + + // H(I||V||... + crypto_generichash_blake2b_state curr_state; + curr_state = eh_state; + crypto_generichash_blake2b_update(&curr_state, + pblock->nNonce.begin(), + pblock->nNonce.size()); + + // (x_1, x_2, ...) = A(I, V, n, k) + std::function)> validBlock = + [&pblock](std::vector soln) + { + LOCK(cs_main); + pblock->nSolution = soln; + solutionTargetChecks.increment(); + return CheckProofOfWork(*pblock,NOTARY_PUBKEY33,chainActive.Height(),Params().GetConsensus()); + }; + bool found = EhBasicSolveUncancellable(n, k, curr_state, validBlock); + ehSolverRuns.increment(); + if (found) { + return true; + } + } + // this should never get hit + return false; +} + +/**** + * @brief Generate 1 block + * @param wallet the wallet that should be used + * @returns the block created or nullptr if there was a problem + */ +std::shared_ptr generateBlock(CWallet* wallet, CValidationState* validationState) +{ + CReserveKey reservekey(wallet); + int nHeight; + + { // Don't keep cs_main locked + LOCK(cs_main); + nHeight = chainActive.Height(); + } + + std::unique_ptr pblocktemplate(CreateNewBlockWithKey(reservekey,nHeight,KOMODO_MAXGPUCOUNT)); + if (pblocktemplate == nullptr) + return nullptr; + + CBlock *pblock = &pblocktemplate->block; + { + unsigned int nExtraNonce = 0; + LOCK(cs_main); + IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce); + } + + CalcPoW(pblock); // add PoW + CValidationState state; + CBlockIndex *tipindex = nullptr; + { + LOCK(cs_main); + tipindex = chainActive.Tip(); + } + if (!ProcessNewBlock(1,tipindex->nHeight+1,state, NULL, pblock, true, NULL)) + { + if (validationState != nullptr) + (*validationState) = state; + return nullptr; + } + return std::shared_ptr( new CBlock(*pblock) ); +} //Value generate(const Array& params, bool fHelp) UniValue generate(const UniValue& params, bool fHelp, const CPubKey& mypk) @@ -251,8 +336,6 @@ UniValue generate(const UniValue& params, bool fHelp, const CPubKey& mypk) } unsigned int nExtraNonce = 0; UniValue blockHashes(UniValue::VARR); - unsigned int n = Params().EquihashN(); - unsigned int k = Params().EquihashK(); uint64_t lastTime = 0; while (nHeight < nHeightEnd) { @@ -270,51 +353,12 @@ UniValue generate(const UniValue& params, bool fHelp, const CPubKey& mypk) CBlock *pblock = &pblocktemplate->block; { LOCK(cs_main); - IncrementExtraNonce(pblock, chainActive.LastTip(), nExtraNonce); + IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce); } - // Hash state - crypto_generichash_blake2b_state eh_state; - EhInitialiseState(n, k, eh_state); - - // I = the block header minus nonce and solution. - CEquihashInput I{*pblock}; - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << I; - - // H(I||... - crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size()); - - while (true) { - // Yes, there is a chance every nonce could fail to satisfy the -regtest - // target -- 1 in 2^(2^256). That ain't gonna happen - pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1); - - // H(I||V||... - crypto_generichash_blake2b_state curr_state; - curr_state = eh_state; - crypto_generichash_blake2b_update(&curr_state, - pblock->nNonce.begin(), - pblock->nNonce.size()); - - // (x_1, x_2, ...) = A(I, V, n, k) - std::function)> validBlock = - [&pblock](std::vector soln) - { - LOCK(cs_main); - pblock->nSolution = soln; - solutionTargetChecks.increment(); - return CheckProofOfWork(*pblock,NOTARY_PUBKEY33,chainActive.Height(),Params().GetConsensus()); - }; - bool found = EhBasicSolveUncancellable(n, k, curr_state, validBlock); - ehSolverRuns.increment(); - if (found) { - goto endloop; - } - } -endloop: + CalcPoW(pblock); // add PoW CValidationState state; - if (!ProcessNewBlock(1,chainActive.LastTip()->nHeight+1,state, NULL, pblock, true, NULL)) + if (!ProcessNewBlock(1,chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL)) throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); ++nHeight; blockHashes.push_back(pblock->GetHash().GetHex()); @@ -386,7 +430,6 @@ UniValue setgenerate(const UniValue& params, bool fHelp, const CPubKey& mypk) } #endif -CBlockIndex *komodo_chainactive(int32_t height); arith_uint256 zawy_ctB(arith_uint256 bnTarget,uint32_t solvetime); UniValue genminingCSV(const UniValue& params, bool fHelp, const CPubKey& mypk) @@ -395,7 +438,7 @@ UniValue genminingCSV(const UniValue& params, bool fHelp, const CPubKey& mypk) if (fHelp || params.size() != 0 ) throw runtime_error("genminingCSV\n"); LOCK(cs_main); - sprintf(fname,"%s_mining.csv",ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL); + sprintf(fname,"%s_mining.csv",chainName.ToString().c_str()); if ( (fp= fopen(fname,"wb")) != 0 ) { fprintf(fp,"height,nTime,nBits,bnTarget,bnTargetB,diff,solvetime\n"); @@ -668,7 +711,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp, const CPubKey& myp return "duplicate-inconclusive"; } - CBlockIndex* const pindexPrev = chainActive.LastTip(); + CBlockIndex* const pindexPrev = chainActive.Tip(); // TestBlockValidity only supports blocks built on the current Tip if (block.hashPrevBlock != pindexPrev->GetBlockHash()) return "inconclusive-not-best-prevblk"; @@ -694,7 +737,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp, const CPubKey& myp } // currently we have checkpoints only in KMD chain, so we checking IsInitialBlockDownload only for KMD itself - if (ASSETCHAINS_SYMBOL[0] == 0 && IsInitialBlockDownload()) { + if (chainName.isKMD() && IsInitialBlockDownload()) { throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Komodo is downloading blocks..."); } @@ -718,7 +761,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp, const CPubKey& myp else { // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier - hashWatchedChain = chainActive.LastTip()->GetBlockHash(); + hashWatchedChain = chainActive.Tip()->GetBlockHash(); nTransactionsUpdatedLastLP = nTransactionsUpdatedLast; } @@ -728,7 +771,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp, const CPubKey& myp checktxtime = boost::get_system_time() + boost::posix_time::minutes(1); boost::unique_lock lock(csBestBlock); - while (chainActive.LastTip()->GetBlockHash() == hashWatchedChain && IsRPCRunning()) + while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning()) { if (!cvBlockChange.timed_wait(lock, checktxtime)) { @@ -750,7 +793,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp, const CPubKey& myp static CBlockIndex* pindexPrev; static int64_t nStart; static CBlockTemplate* pblocktemplate; - if (pindexPrev != chainActive.LastTip() || + if (pindexPrev != chainActive.Tip() || (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5)) { // Clear pindexPrev so future calls make a new block, despite any failures from here on @@ -758,7 +801,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp, const CPubKey& myp // Store the pindexBest used before CreateNewBlockWithKey, to avoid races nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); - CBlockIndex* pindexPrevNew = chainActive.LastTip(); + CBlockIndex* pindexPrevNew = chainActive.Tip(); nStart = GetTime(); // Create new block @@ -777,7 +820,6 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp, const CPubKey& myp ENTER_CRITICAL_SECTION(cs_main); if (!pblocktemplate) throw std::runtime_error("CreateNewBlock(): create block failed"); - //throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory or no available utxo for staking"); // Need to update only after we know CreateNewBlockWithKey succeeded pindexPrev = pindexPrevNew; @@ -825,7 +867,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp, const CPubKey& myp // Correct this if GetBlockTemplate changes the order entry.push_back(Pair("foundersreward", (int64_t)tx.vout[1].nValue)); } - CAmount nReward = GetBlockSubsidy(chainActive.LastTip()->nHeight+1, Params().GetConsensus()); + CAmount nReward = GetBlockSubsidy(chainActive.Tip()->nHeight+1, Params().GetConsensus()); entry.push_back(Pair("coinbasevalue", nReward)); entry.push_back(Pair("required", true)); txCoinbase = entry; @@ -859,7 +901,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp, const CPubKey& myp // result.push_back(Pair("coinbaseaux", aux)); // result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue)); //} - result.push_back(Pair("longpollid", chainActive.LastTip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast))); + result.push_back(Pair("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast))); if ( ASSETCHAINS_STAKED != 0 ) { arith_uint256 POWtarget; int32_t PoSperc; @@ -869,15 +911,13 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp, const CPubKey& myp result.push_back(Pair("ac_staked", (int64_t)ASSETCHAINS_STAKED)); result.push_back(Pair("origtarget", hashTarget.GetHex())); } - /*else if ( ASSETCHAINS_ADAPTIVEPOW > 0 ) - result.push_back(Pair("target",komodo_adaptivepow_target((int32_t)(pindexPrev->nHeight+1),hashTarget,pblock->nTime).GetHex()));*/ else result.push_back(Pair("target", hashTarget.GetHex())); result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1)); result.push_back(Pair("mutable", aMutable)); result.push_back(Pair("noncerange", "00000000ffffffff")); result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS)); - result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE(chainActive.LastTip()->nHeight+1))); + result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE(chainActive.Tip()->nHeight+1))); result.push_back(Pair("curtime", pblock->GetBlockTime())); result.push_back(Pair("bits", strprintf("%08x", pblock->nBits))); result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1))); @@ -959,8 +999,8 @@ UniValue submitblock(const UniValue& params, bool fHelp, const CPubKey& mypk) CValidationState state; submitblock_StateCatcher sc(block.GetHash()); RegisterValidationInterface(&sc); - //printf("submitblock, height=%d, coinbase sequence: %d, scriptSig: %s\n", chainActive.LastTip()->nHeight+1, block.vtx[0].vin[0].nSequence, block.vtx[0].vin[0].scriptSig.ToString().c_str()); - bool fAccepted = ProcessNewBlock(1,chainActive.LastTip()->nHeight+1,state, NULL, &block, true, NULL); + //printf("submitblock, height=%d, coinbase sequence: %d, scriptSig: %s\n", chainActive.Tip()->nHeight+1, block.vtx[0].vin[0].nSequence, block.vtx[0].vin[0].scriptSig.ToString().c_str()); + bool fAccepted = ProcessNewBlock(1,chainActive.Tip()->nHeight+1,state, NULL, &block, true, NULL); UnregisterValidationInterface(&sc); if (fBlockPresent) { diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index cc875f25c2f..0ba94c1a513 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -31,6 +31,11 @@ #include "cc/eval.h" #include "cc/CCinclude.h" #include "hex.h" +#include "komodo_bitcoind.h" +#include "komodo_notary.h" +#include "komodo_utils.h" +#include "komodo_globals.h" +#include "cc/CCinclude.h" #ifdef ENABLE_WALLET #include "wallet/wallet.h" #include "wallet/walletdb.h" @@ -60,10 +65,8 @@ using namespace std; * Or alternatively, create a specific query method for the information. **/ -int32_t Jumblr_depositaddradd(char *depositaddr); +/*int32_t Jumblr_depositaddradd(char *depositaddr); int32_t Jumblr_secretaddradd(char *secretaddr); -uint64_t komodo_interestsum(); -int32_t komodo_longestchain(); int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp); bool komodo_txnotarizedconfirmed(uint256 txid); uint32_t komodo_chainactive_timestamp(); @@ -71,15 +74,14 @@ int32_t komodo_whoami(char *pubkeystr,int32_t height,uint32_t timestamp); extern uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; extern bool IS_KOMODO_NOTARY; extern int32_t KOMODO_LASTMINED,JUMBLR_PAUSE,KOMODO_LONGESTCHAIN,STAKED_NOTARY_ID,STAKED_ERA,KOMODO_INSYNC; -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; uint32_t komodo_segid32(char *coinaddr); int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height); int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp); int8_t StakedNotaryID(std::string ¬aryname, char *Raddress); uint64_t komodo_notarypayamount(int32_t nHeight, int64_t notarycount); -int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); +int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);*/ -#define KOMODO_VERSION "0.7.2" +#define KOMODO_VERSION "0.8.0" extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; extern uint32_t ASSETCHAINS_CC; extern uint32_t ASSETCHAINS_MAGIC,ASSETCHAINS_ALGO; @@ -176,7 +178,7 @@ UniValue geterablockheights(const UniValue& params, bool fHelp, const CPubKey& m CBlockIndex *pindex; int8_t lastera,era = 0; UniValue ret(UniValue::VOBJ); - for (size_t i = 1; i < chainActive.LastTip()->nHeight; i++) + for (size_t i = 1; i < chainActive.Tip()->nHeight; i++) { pindex = chainActive[i]; era = getera(pindex->nTime)+1; @@ -192,6 +194,19 @@ UniValue geterablockheights(const UniValue& params, bool fHelp, const CPubKey& m return(ret); } +/** + * @note Do not add or change anything in the information returned by this + * method. `getinfo` exists for backwards-compatibility only. It combines + * information from wildly different sources in the program, which is a mess, + * and is thus planned to be deprecated eventually. + * + * Based on the source of the information, new information should be added to: + * - `getblockchaininfo`, + * - `getnetworkinfo` or + * - `getwalletinfo` + * + * Or alternatively, create a specific query method for the information. + **/ UniValue getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) { uint256 notarized_hash,notarized_desttxid; int32_t prevMoMheight,notarized_height,longestchain,kmdnotarized_height,txid_height; @@ -244,18 +259,18 @@ UniValue getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) obj.push_back(Pair("notarizedtxid", notarized_desttxid.ToString())); if ( KOMODO_NSPV_FULLNODE ) { - txid_height = notarizedtxid_height(ASSETCHAINS_SYMBOL[0] != 0 ? (char *)"KMD" : (char *)"BTC",(char *)notarized_desttxid.ToString().c_str(),&kmdnotarized_height); + txid_height = notarizedtxid_height(!chainName.isKMD() ? (char *)"KMD" : (char *)"BTC",(char *)notarized_desttxid.ToString().c_str(),&kmdnotarized_height); if ( txid_height > 0 ) obj.push_back(Pair("notarizedtxid_height", txid_height)); else obj.push_back(Pair("notarizedtxid_height", "mempool")); - if ( ASSETCHAINS_SYMBOL[0] != 0 ) + if ( !chainName.isKMD() ) obj.push_back(Pair("KMDnotarized_height", kmdnotarized_height)); obj.push_back(Pair("notarized_confirms", txid_height < kmdnotarized_height ? (kmdnotarized_height - txid_height + 1) : 0)); //fprintf(stderr,"after notarized_confirms %u\n",(uint32_t)time(NULL)); #ifdef ENABLE_WALLET if (pwalletMain) { obj.push_back(Pair("walletversion", pwalletMain->GetVersion())); - if ( ASSETCHAINS_SYMBOL[0] == 0 ) + if ( chainName.isKMD() ) { obj.push_back(Pair("interest", ValueFromAmount(KOMODO_INTERESTSUM))); obj.push_back(Pair("balance", ValueFromAmount(KOMODO_WALLETBALANCE))); //pwalletMain->GetBalance() @@ -272,8 +287,8 @@ UniValue getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) longestchain = chainActive.Height(); //fprintf(stderr,"after longestchain %u\n",(uint32_t)time(NULL)); obj.push_back(Pair("longestchain", longestchain)); - if ( chainActive.LastTip() != 0 ) - obj.push_back(Pair("tiptime", (int)chainActive.LastTip()->nTime)); + if ( chainActive.Tip() != 0 ) + obj.push_back(Pair("tiptime", (int)chainActive.Tip()->nTime)); obj.push_back(Pair("difficulty", (double)GetDifficulty())); #ifdef ENABLE_WALLET if (pwalletMain) { @@ -297,7 +312,7 @@ UniValue getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) if ( (notaryid= StakedNotaryID(notaryname, (char *)NOTARY_ADDRESS.c_str())) != -1 ) { obj.push_back(Pair("notaryid", notaryid)); obj.push_back(Pair("notaryname", notaryname)); - } else if( (notaryid= komodo_whoami(pubkeystr,(int32_t)chainActive.LastTip()->nHeight,komodo_chainactive_timestamp())) >= 0 ) { + } else if( (notaryid= komodo_whoami(pubkeystr,(int32_t)chainActive.Tip()->nHeight,komodo_chainactive_timestamp())) >= 0 ) { obj.push_back(Pair("notaryid", notaryid)); if ( KOMODO_LASTMINED != 0 ) obj.push_back(Pair("lastmined", KOMODO_LASTMINED)); @@ -306,15 +321,14 @@ UniValue getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) } if ( ASSETCHAINS_CC != 0 ) obj.push_back(Pair("CCid", (int)ASSETCHAINS_CC)); - obj.push_back(Pair("name", ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL)); + obj.push_back(Pair("name", chainName.ToString())); obj.push_back(Pair("p2pport", ASSETCHAINS_P2PPORT)); obj.push_back(Pair("rpcport", ASSETCHAINS_RPCPORT)); - if ( ASSETCHAINS_SYMBOL[0] != 0 ) + if ( !chainName.isKMD() ) { - if ( is_STAKED(ASSETCHAINS_SYMBOL) != 0 ) + if ( is_STAKED(chainName.symbol()) != 0 ) obj.push_back(Pair("StakedEra", STAKED_ERA)); - //obj.push_back(Pair("name", ASSETCHAINS_SYMBOL)); obj.push_back(Pair("magic", (int)ASSETCHAINS_MAGIC)); obj.push_back(Pair("premine", ASSETCHAINS_SUPPLY)); @@ -445,7 +459,7 @@ UniValue coinsupply(const UniValue& params, bool fHelp, const CPubKey& mypk) if ( (supply= komodo_coinsupply(&zfunds,&sproutfunds,height)) > 0 ) { result.push_back(Pair("result", "success")); - result.push_back(Pair("coin", ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL)); + result.push_back(Pair("coin", chainName.ToString())); result.push_back(Pair("height", (int)height)); result.push_back(Pair("supply", ValueFromAmount(supply))); result.push_back(Pair("zfunds", ValueFromAmount(zfunds))); @@ -479,64 +493,6 @@ UniValue coinsupply(const UniValue& params, bool fHelp, const CPubKey& mypk) return(result); } -UniValue jumblr_deposit(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - int32_t retval; UniValue result(UniValue::VOBJ); - if (fHelp || params.size() != 1) - throw runtime_error("jumblr_deposit \"depositaddress\"\n"); - CBitcoinAddress address(params[0].get_str()); - bool isValid = address.IsValid(); - if ( isValid != 0 ) - { - string addr = params[0].get_str(); - if ( (retval= Jumblr_depositaddradd((char *)addr.c_str())) >= 0 ) - { - result.push_back(Pair("result", retval)); - JUMBLR_PAUSE = 0; - } - else result.push_back(Pair("error", retval)); - } else result.push_back(Pair("error", "invalid address")); - return(result); -} - -UniValue jumblr_secret(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - int32_t retval; UniValue result(UniValue::VOBJ); - if (fHelp || params.size() != 1) - throw runtime_error("jumblr_secret \"secretaddress\"\n"); - CBitcoinAddress address(params[0].get_str()); - bool isValid = address.IsValid(); - if ( isValid != 0 ) - { - string addr = params[0].get_str(); - retval = Jumblr_secretaddradd((char *)addr.c_str()); - result.push_back(Pair("result", "success")); - result.push_back(Pair("num", retval)); - JUMBLR_PAUSE = 0; - } else result.push_back(Pair("error", "invalid address")); - return(result); -} - -UniValue jumblr_pause(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - int32_t retval; UniValue result(UniValue::VOBJ); - if (fHelp ) - throw runtime_error("jumblr_pause\n"); - JUMBLR_PAUSE = 1; - result.push_back(Pair("result", "paused")); - return(result); -} - -UniValue jumblr_resume(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - int32_t retval; UniValue result(UniValue::VOBJ); - if (fHelp ) - throw runtime_error("jumblr_resume\n"); - JUMBLR_PAUSE = 0; - result.push_back(Pair("result", "resumed")); - return(result); -} - UniValue validateaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) { if (fHelp || params.size() != 1) @@ -1085,7 +1041,7 @@ UniValue getaddressutxos(const UniValue& params, bool fHelp, const CPubKey& mypk result.push_back(Pair("utxos", utxos)); LOCK(cs_main); - result.push_back(Pair("hash", chainActive.LastTip()->GetBlockHash().GetHex())); + result.push_back(Pair("hash", chainActive.Tip()->GetBlockHash().GetHex())); result.push_back(Pair("height", (int)chainActive.Height())); return result; } else { @@ -1235,7 +1191,7 @@ CAmount checkburnaddress(CAmount &received, int64_t &nNotaryPay, int32_t &height balance += it->second; } // Get notary pay from current chain tip - CBlockIndex* pindex = chainActive.LastTip(); + CBlockIndex* pindex = chainActive.Tip(); nNotaryPay = pindex->nNotaryPay; height = pindex->nHeight; } @@ -1412,12 +1368,12 @@ UniValue getsnapshot(const UniValue& params, bool fHelp, const CPubKey& mypk) " \"amount\": \"23.45\"\n" " }\n" " ],\n" - " \"total\": 123.45 (numeric) Total amount in snapshot\n" + " \"total\": 123.45, (numeric) Total amount in snapshot\n" " \"average\": 61.7, (numeric) Average amount in each address \n" " \"utxos\": 14, (number) Total number of UTXOs in snapshot\n" - " \"total_addresses\": 2, (number) Total number of addresses in snapshot,\n" + " \"total_addresses\": 2, (number) Total number of addresses in snapshot\n" " \"start_height\": 91, (number) Block height snapshot began\n" - " \"ending_height\": 91 (number) Block height snapsho finished,\n" + " \"ending_height\": 91, (number) Block height snapshot finished\n" " \"start_time\": 1531982752, (number) Unix epoch time snapshot started\n" " \"end_time\": 1531982752 (number) Unix epoch time snapshot finished\n" "}\n" diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index f87d953eaf1..a234028ca37 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -28,6 +28,7 @@ #include "util.h" #include "version.h" #include "deprecation.h" +#include "komodo_defs.h" #include @@ -163,6 +164,8 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) } obj.push_back(Pair("inflight", heights)); } + obj.push_back(Pair("addr_processed", stats.m_addr_processed)); + obj.push_back(Pair("addr_rate_limited", stats.m_addr_rate_limited)); obj.push_back(Pair("whitelisted", stats.fWhitelisted)); ret.push_back(obj); @@ -202,7 +205,6 @@ int32_t komodo_longestchain() } BOOST_FOREACH(const CNodeStats& stats, vstats) { - //fprintf(stderr,"komodo_longestchain iter.%d\n",n); CNodeStateStats statestats; bool fStateStats = GetNodeStateStats(stats.nodeid,statestats); if ( statestats.nSyncHeight < 0 ) @@ -225,7 +227,7 @@ int32_t komodo_longestchain() if ( num > (n >> 1) ) { if ( 0 && height != KOMODO_LONGESTCHAIN ) - fprintf(stderr,"set %s KOMODO_LONGESTCHAIN <- %d\n",ASSETCHAINS_SYMBOL,height); + fprintf(stderr,"set %s KOMODO_LONGESTCHAIN <- %d\n",chainName.symbol().c_str(),height); KOMODO_LONGESTCHAIN = height; return(height); } diff --git a/src/rpc/net.h b/src/rpc/net.h new file mode 100644 index 00000000000..e00ae3d6428 --- /dev/null +++ b/src/rpc/net.h @@ -0,0 +1,20 @@ +#pragma once +// Copyright (c) 2009-2014 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +/****************************************************************************** + * Copyright © 2021 Komodo Core Developers * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ +int32_t komodo_longestchain(); \ No newline at end of file diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index de5b1d6d1d4..04a3a3c3aac 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -36,11 +36,15 @@ #include "script/standard.h" #include "uint256.h" #include "importcoin.h" +#include "komodo_notary.h" +#include "komodo_bitcoind.h" #ifdef ENABLE_WALLET #include "wallet/wallet.h" #endif #include "komodo_defs.h" +#include "assetchain.h" +#include "komodo_interest.h" #include @@ -48,13 +52,8 @@ #include -int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp); - using namespace std; -extern char ASSETCHAINS_SYMBOL[]; -int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); - void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex) { txnouttype type; @@ -140,8 +139,6 @@ UniValue TxJoinSplitToJSON(const CTransaction& tx) { return vjoinsplit; } -uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); - UniValue TxShieldedSpendsToJSON(const CTransaction& tx) { UniValue vdesc(UniValue::VARR); for (const SpendDescription& spendDesc : tx.vShieldedSpend) { @@ -272,7 +269,7 @@ void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue& const CTxOut& txout = tx.vout[i]; UniValue out(UniValue::VOBJ); out.push_back(Pair("value", ValueFromAmount(txout.nValue))); - if ( ASSETCHAINS_SYMBOL[0] == 0 && pindex != 0 && tx.nLockTime >= 500000000 && (tipindex= chainActive.LastTip()) != 0 ) + if ( chainName.isKMD() && pindex != 0 && tx.nLockTime >= 500000000 && (tipindex= chainActive.Tip()) != 0 ) { int64_t interest; int32_t txheight; uint32_t locktime; interest = komodo_accrued_interest(&txheight,&locktime,tx.GetHash(),i,0,txout.nValue,(int32_t)tipindex->nHeight); @@ -374,7 +371,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) const CTxOut& txout = tx.vout[i]; UniValue out(UniValue::VOBJ); out.push_back(Pair("value", ValueFromAmount(txout.nValue))); - if ( KOMODO_NSPV_FULLNODE && ASSETCHAINS_SYMBOL[0] == 0 && tx.nLockTime >= 500000000 && (tipindex= chainActive.LastTip()) != 0 ) + if ( KOMODO_NSPV_FULLNODE && chainName.isKMD() && tx.nLockTime >= 500000000 && (tipindex= chainActive.Tip()) != 0 ) { int64_t interest; int32_t txheight; uint32_t locktime; interest = komodo_accrued_interest(&txheight,&locktime,tx.GetHash(),i,0,txout.nValue,(int32_t)tipindex->nHeight); @@ -561,56 +558,6 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp, const CPubKey& my return result; } -int32_t gettxout_scriptPubKey(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid,int32_t n) -{ - int32_t i,m; uint8_t *ptr; - LOCK(cs_main); - /*CCoins coins; - for (iter=0; iter<2; iter++) - { - if ( iter == 0 ) - { - LOCK(mempool.cs); - CCoinsViewMemPool view(pcoinsTip,mempool); - if ( view.GetCoins(txid,coins) == 0 ) - { - //fprintf(stderr,"cant get view\n"); - continue; - } - mempool.pruneSpent(txid, coins); // TODO: this should be done by the CCoinsViewMemPool - } - else if ( pcoinsTip->GetCoins(txid,coins) == 0 ) - { - //fprintf(stderr,"cant get pcoinsTip->GetCoins\n"); - continue; - } - if ( n < 0 || (unsigned int)n >= coins.vout.size() || coins.vout[n].IsNull() ) - { - fprintf(stderr,"iter.%d n.%d vs voutsize.%d\n",iter,n,(int32_t)coins.vout.size()); - continue; - } - ptr = (uint8_t *)coins.vout[n].scriptPubKey.data(); - m = coins.vout[n].scriptPubKey.size(); - for (i=0; i @@ -255,8 +255,6 @@ UniValue help(const UniValue& params, bool fHelp, const CPubKey& mypk) return tableRPC.help(strCommand); } -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; - #ifdef ENABLE_WALLET void GenerateBitcoins(bool b, CWallet *pw, int t); #else @@ -281,7 +279,7 @@ UniValue stop(const UniValue& params, bool fHelp, const CPubKey& mypk) // Shutdown will take long enough that the response should get back StartShutdown(); - sprintf(buf,"%s server stopping",ASSETCHAINS_SYMBOL[0] != 0 ? ASSETCHAINS_SYMBOL : "Komodo"); + sprintf(buf,"%s server stopping", !chainName.isKMD() ? chainName.symbol().c_str() : "Komodo"); return buf; } @@ -333,9 +331,6 @@ static const CRPCCommand vRPCCommands[] = { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true }, { "blockchain", "verifychain", &verifychain, true }, { "blockchain", "getspentinfo", &getspentinfo, false }, - //{ "blockchain", "paxprice", &paxprice, true }, - //{ "blockchain", "paxpending", &paxpending, true }, - //{ "blockchain", "paxprices", &paxprices, true }, { "blockchain", "notaries", ¬aries, true }, //{ "blockchain", "height_MoM", &height_MoM, true }, //{ "blockchain", "txMoMproof", &txMoMproof, true }, @@ -478,23 +473,6 @@ static const CRPCCommand vRPCCommands[] = { "oracles", "oraclessample", &oraclessample, true }, { "oracles", "oraclessamples", &oraclessamples, true }, - // Prices - { "prices", "prices", &prices, true }, - { "prices", "pricesaddress", &pricesaddress, true }, - { "prices", "priceslist", &priceslist, true }, - { "prices", "mypriceslist", &mypriceslist, true }, - { "prices", "pricesinfo", &pricesinfo, true }, - { "prices", "pricesbet", &pricesbet, true }, - { "prices", "pricessetcostbasis", &pricessetcostbasis, true }, - { "prices", "pricescashout", &pricescashout, true }, - { "prices", "pricesrekt", &pricesrekt, true }, - { "prices", "pricesaddfunding", &pricesaddfunding, true }, - { "prices", "pricesgetorderbook", &pricesgetorderbook, true }, - { "prices", "pricesrefillfund", &pricesrefillfund, true }, - - // Pegs - { "pegs", "pegsaddress", &pegsaddress, true }, - // Payments { "payments", "paymentsaddress", &paymentsaddress, true }, { "payments", "paymentstxidopret", &payments_txidopret, true }, @@ -558,17 +536,6 @@ static const CRPCCommand vRPCCommands[] = //{ "tokens", "tokenfillswap", &tokenfillswap, true }, { "tokens", "tokenconvert", &tokenconvert, true }, - // pegs - { "pegs", "pegscreate", &pegscreate, true }, - { "pegs", "pegsfund", &pegsfund, true }, - { "pegs", "pegsget", &pegsget, true }, - { "pegs", "pegsredeem", &pegsredeem, true }, - { "pegs", "pegsliquidate", &pegsliquidate, true }, - { "pegs", "pegsexchange", &pegsexchange, true }, - { "pegs", "pegsaccounthistory", &pegsaccounthistory, true }, - { "pegs", "pegsaccountinfo", &pegsaccountinfo, true }, - { "pegs", "pegsworstaccounts", &pegsworstaccounts, true }, - { "pegs", "pegsinfo", &pegsinfo, true }, /* Address index */ { "addressindex", "getaddressmempool", &getaddressmempool, true }, @@ -589,10 +556,6 @@ static const CRPCCommand vRPCCommands[] = { "util", "estimatefee", &estimatefee, true }, { "util", "estimatepriority", &estimatepriority, true }, { "util", "z_validateaddress", &z_validateaddress, true }, /* uses wallet if enabled */ - { "util", "jumblr_deposit", &jumblr_deposit, true }, - { "util", "jumblr_secret", &jumblr_secret, true }, - { "util", "jumblr_pause", &jumblr_pause, true }, - { "util", "jumblr_resume", &jumblr_resume, true }, { "util", "invalidateblock", &invalidateblock, true }, { "util", "reconsiderblock", &reconsiderblock, true }, @@ -846,7 +809,7 @@ UniValue CRPCTable::execute(const std::string &strMethod, const UniValue ¶ms // Return immediately if in warmup { LOCK(cs_rpcWarmup); - if (fRPCInWarmup) + if (fRPCInWarmup && strMethod != "help") throw JSONRPCError(RPC_IN_WARMUP, rpcWarmupStatus); } @@ -874,12 +837,10 @@ UniValue CRPCTable::execute(const std::string &strMethod, const UniValue ¶ms std::string HelpExampleCli(const std::string& methodname, const std::string& args) { - if ( ASSETCHAINS_SYMBOL[0] == 0 ) { + if ( chainName.isKMD() ) { return "> komodo-cli " + methodname + " " + args + "\n"; - } else if ((strncmp(ASSETCHAINS_SYMBOL, "HUSH3", 5) == 0) ) { - return "> hush-cli " + methodname + " " + args + "\n"; } else { - return "> komodo-cli -ac_name=" + strprintf("%s", ASSETCHAINS_SYMBOL) + " " + methodname + " " + args + "\n"; + return "> komodo-cli -ac_name=" + strprintf("%s", chainName.symbol().c_str()) + " " + methodname + " " + args + "\n"; } } @@ -891,8 +852,8 @@ std::string HelpExampleRpc(const std::string& methodname, const std::string& arg string experimentalDisabledHelpMsg(const string& rpc, const string& enableArg) { - string daemon = ASSETCHAINS_SYMBOL[0] == 0 ? "komodod" : "hushd"; - string ticker = ASSETCHAINS_SYMBOL[0] == 0 ? "komodo" : ASSETCHAINS_SYMBOL; + string daemon = "komodod"; + string ticker = chainName.isKMD() ? "komodo" : chainName.symbol(); return "\nWARNING: " + rpc + " is disabled.\n" "To enable it, restart " + daemon + " with the -experimentalfeatures and\n" diff --git a/src/rpc/server.h b/src/rpc/server.h index 1484f56d5c4..e1e2f318609 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -274,11 +274,6 @@ extern UniValue oraclessubscribe(const UniValue& params, bool fHelp, const CPubK extern UniValue oraclesdata(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue oraclessample(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue oraclessamples(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue priceslist(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue mypriceslist(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue paymentsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue payments_release(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue payments_fund(const UniValue& params, bool fHelp, const CPubKey& mypk); @@ -340,16 +335,6 @@ extern UniValue FSMcreate(const UniValue& params, bool fHelp, const CPubKey& myp extern UniValue FSMlist(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue FSMinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue auctionaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegscreate(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsfund(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsget(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsredeem(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsliquidate(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsexchange(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsaccounthistory(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsaccountinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsworstaccounts(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pegsinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp //extern UniValue getnewaddress64(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp @@ -406,11 +391,6 @@ extern UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp, const CPubK extern UniValue zc_raw_receive(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue jumblr_deposit(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue jumblr_secret(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue jumblr_pause(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue jumblr_resume(const UniValue& params, bool fHelp, const CPubKey& mypk); - extern UniValue getrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rcprawtransaction.cpp extern UniValue listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue lockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk); @@ -515,21 +495,5 @@ extern UniValue notaries(const UniValue& params, bool fHelp, const CPubKey& mypk extern UniValue minerids(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue kvsearch(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue kvupdate(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue paxprice(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue paxpending(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue paxprices(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue paxdeposit(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue paxwithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk); - -extern UniValue prices(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesbet(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricessetcostbasis(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricescashout(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesrekt(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesaddfunding(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesgetorderbook(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue pricesrefillfund(const UniValue& params, bool fHelp, const CPubKey& mypk); - - #endif // BITCOIN_RPCSERVER_H diff --git a/src/rpc/testtransactions.cpp b/src/rpc/testtransactions.cpp deleted file mode 100644 index c41e97e1036..00000000000 --- a/src/rpc/testtransactions.cpp +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -/****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * - * * - * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * - * the top-level directory of this distribution for the individual copyright * - * holder information and the developer policies on copyright and licensing. * - * * - * Unless otherwise agreed in a custom licensing agreement, no part of the * - * SuperNET software, including this file may be copied, modified, propagated * - * or distributed except according to the terms contained in the LICENSE file * - * * - * Removal or modification of this copyright notice is prohibited. * - * * - ******************************************************************************/ - -#include - -#include "amount.h" -#include "chain.h" -#include "chainparams.h" -#include "checkpoints.h" -#include "crosschain.h" -#include "base58.h" -#include "consensus/validation.h" -#include "cc/eval.h" -#include "main.h" -#include "primitives/transaction.h" -#include "rpc/server.h" -#include "streams.h" -#include "sync.h" -#include "util.h" -#include "script/script.h" -#include "script/script_error.h" -#include "script/sign.h" -#include "script/standard.h" - -#include - -#include - -#include - - -#include "cc/CCinclude.h" -#include "cc/CCPrices.h" - -using namespace std; - -int32_t ensure_CCrequirements(uint8_t evalcode); - -UniValue test_ac(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - // make fake token tx: - struct CCcontract_info *cp, C; - - if (fHelp || (params.size() != 4)) - throw runtime_error("incorrect params\n"); - if (ensure_CCrequirements(EVAL_HEIR) < 0) - throw runtime_error(CC_REQUIREMENTS_MSG); - - std::vector pubkey1; - std::vector pubkey2; - - pubkey1 = ParseHex(params[0].get_str().c_str()); - pubkey2 = ParseHex(params[1].get_str().c_str()); - - CPubKey pk1 = pubkey2pk(pubkey1); - CPubKey pk2 = pubkey2pk(pubkey2); - - if (!pk1.IsValid() || !pk2.IsValid()) - throw runtime_error("invalid pubkey\n"); - - int64_t txfee = 10000; - int64_t amount = atoll(params[2].get_str().c_str()) * COIN; - uint256 fundingtxid = Parseuint256((char *)params[3].get_str().c_str()); - - CPubKey myPubkey = pubkey2pk(Mypubkey()); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - - int64_t normalInputs = AddNormalinputs(mtx, myPubkey, txfee + amount, 60); - - if (normalInputs < txfee + amount) - throw runtime_error("not enough normals\n"); - - mtx.vout.push_back(MakeCC1of2vout(EVAL_HEIR, amount, pk1, pk2)); - - CScript opret; - fundingtxid = revuint256(fundingtxid); - - opret << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'A' << fundingtxid << (uint8_t)0); - - cp = CCinit(&C, EVAL_HEIR); - return(FinalizeCCTx(0, cp, mtx, myPubkey, txfee, opret)); -} - -UniValue test_heirmarker(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - // make fake token tx: - struct CCcontract_info *cp, C; - - if (fHelp || (params.size() != 1)) - throw runtime_error("incorrect params\n"); - if (ensure_CCrequirements(EVAL_HEIR) < 0) - throw runtime_error(CC_REQUIREMENTS_MSG); - - uint256 fundingtxid = Parseuint256((char *)params[0].get_str().c_str()); - - CPubKey myPubkey = pubkey2pk(Mypubkey()); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - - int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60); - if (normalInputs < 10000) - throw runtime_error("not enough normals\n"); - - mtx.vin.push_back(CTxIn(fundingtxid, 1)); - mtx.vout.push_back(MakeCC1vout(EVAL_HEIR, 10000, myPubkey)); - - CScript opret; - fundingtxid = revuint256(fundingtxid); - - opret << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'C' << fundingtxid << (uint8_t)0); - - cp = CCinit(&C, EVAL_HEIR); - return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, opret)); -} - -UniValue test_burntx(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - // make fake token tx: - struct CCcontract_info *cp, C; - - if (fHelp || (params.size() != 1)) - throw runtime_error("incorrect params\n"); - if (ensure_CCrequirements(EVAL_TOKENS) < 0) - throw runtime_error(CC_REQUIREMENTS_MSG); - - uint256 tokenid = Parseuint256((char *)params[0].get_str().c_str()); - - CPubKey myPubkey = pubkey2pk(Mypubkey()); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - - int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60); - if (normalInputs < 10000) - throw runtime_error("not enough normals\n"); - - CPubKey burnpk = pubkey2pk(ParseHex(CC_BURNPUBKEY)); - - mtx.vin.push_back(CTxIn(tokenid, 0)); - mtx.vin.push_back(CTxIn(tokenid, 1)); - mtx.vout.push_back(MakeTokensCC1vout(EVAL_TOKENS, 1, burnpk)); - - std::vector voutPubkeys; - voutPubkeys.push_back(burnpk); - - cp = CCinit(&C, EVAL_TOKENS); - - std::vector vopret; - GetNonfungibleData(tokenid, vopret); - if (vopret.size() > 0) - cp->additionalTokensEvalcode2 = vopret.begin()[0]; - - uint8_t tokenpriv[33]; - char unspendableTokenAddr[64]; - CPubKey unspPk = GetUnspendable(cp, tokenpriv); - GetCCaddress(cp, unspendableTokenAddr, unspPk); - CCaddr2set(cp, EVAL_TOKENS, unspPk, tokenpriv, unspendableTokenAddr); - return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, EncodeTokenOpRet(tokenid, voutPubkeys, std::make_pair(0, vscript_t())))); -} - -UniValue test_proof(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); - std::vectorproof; - - if (fHelp || (params.size() != 2)) - throw runtime_error("incorrect params\n"); - - - proof = ParseHex(params[0].get_str()); - uint256 cointxid = Parseuint256((char *)params[1].get_str().c_str()); - - std::vector txids; - - CMerkleBlock merkleBlock; - if (!E_UNMARSHAL(proof, ss >> merkleBlock)) { - result.push_back(Pair("error", "could not unmarshal proof")); - return result; - } - uint256 merkleRoot = merkleBlock.txn.ExtractMatches(txids); - - result.push_back(Pair("source_root", merkleRoot.GetHex())); - - for (int i = 0; i < txids.size(); i++) - std::cerr << "merkle block txid=" << txids[0].GetHex() << std::endl; - - - std::vector vMatches(txids.size()); - for (auto v : vMatches) v = true; - CPartialMerkleTree verifTree(txids, vMatches); - - result.push_back(Pair("verif_root", verifTree.ExtractMatches(txids).GetHex())); - - if (std::find(txids.begin(), txids.end(), cointxid) == txids.end()) { - fprintf(stderr, "invalid proof for this cointxid\n"); - } - - std::vector vMerkleTree; - bool f; - ::BuildMerkleTree(&f, txids, vMerkleTree); - - std::vector vMerkleBranch = ::GetMerkleBranch(0, txids.size(), vMerkleTree); - - uint256 ourResult = SafeCheckMerkleBranch(zeroid, vMerkleBranch, 0); - result.push_back(Pair("SafeCheckMerkleBranch", ourResult.GetHex())); - - return result; -} - -extern CScript prices_costbasisopret(uint256 bettxid, CPubKey mypk, int32_t height, int64_t costbasis); -UniValue test_pricesmarker(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - // make fake token tx: - struct CCcontract_info *cp, C; - - if (fHelp || (params.size() != 1)) - throw runtime_error("incorrect params\n"); - if (ensure_CCrequirements(EVAL_PRICES) < 0) - throw runtime_error(CC_REQUIREMENTS_MSG); - - uint256 bettxid = Parseuint256((char *)params[0].get_str().c_str()); - - cp = CCinit(&C, EVAL_PRICES); - CPubKey myPubkey = pubkey2pk(Mypubkey()); - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - - int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60); - if (normalInputs < 10000) - throw runtime_error("not enough normals\n"); - - mtx.vin.push_back(CTxIn(bettxid, 1)); - mtx.vout.push_back(CTxOut(1000, CScript() << ParseHex(HexStr(myPubkey)) << OP_CHECKSIG)); - - return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, prices_costbasisopret(bettxid, myPubkey, 100, 100))); -} - - -static const CRPCCommand commands[] = -{ // category name actor (function) okSafeMode - // --------------------- ------------------------ ----------------------- ---------- - - /* Not shown in help */ - { "hidden", "test_ac", &test_ac, true }, - { "hidden", "test_heirmarker", &test_heirmarker, true }, - { "hidden", "test_proof", &test_proof, true }, - { "hidden", "test_burntx", &test_burntx, true }, - { "hidden", "test_pricesmarker", &test_pricesmarker, true } -}; - -void RegisterTesttransactionsRPCCommands(CRPCTable &tableRPC) -{ - for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) - tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); -} diff --git a/src/rpcblockchain.old b/src/rpcblockchain.old deleted file mode 100644 index a91f73a6364..00000000000 --- a/src/rpcblockchain.old +++ /dev/null @@ -1,1625 +0,0 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "amount.h" -#include "chain.h" -#include "chainparams.h" -#include "checkpoints.h" -#include "crosschain.h" -#include "base58.h" -#include "consensus/validation.h" -#include "cc/eval.h" -#include "main.h" -#include "primitives/transaction.h" -#include "rpcserver.h" -#include "sync.h" -#include "util.h" -#include "script/script.h" -#include "script/script_error.h" -#include "script/sign.h" -#include "script/standard.h" - -#include - -#include - -#include - -using namespace std; - -extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); -void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); -int32_t komodo_longestchain(); -int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); -<<<<<<< HEAD:src/rpcblockchain.old -extern int32_t KOMODO_LONGESTCHAIN; -======= ->>>>>>> master:src/rpcblockchain.cpp - -double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty) -{ - // Floating point number that is a multiple of the minimum difficulty, - // minimum difficulty = 1.0. - if (blockindex == NULL) - { - if (chainActive.LastTip() == NULL) - return 1.0; - else - blockindex = chainActive.LastTip(); - } - - uint32_t bits; - if (networkDifficulty) { - bits = GetNextWorkRequired(blockindex, nullptr, Params().GetConsensus()); - } else { - bits = blockindex->nBits; - } - - uint32_t powLimit = - UintToArith256(Params().GetConsensus().powLimit).GetCompact(); - int nShift = (bits >> 24) & 0xff; - int nShiftAmount = (powLimit >> 24) & 0xff; - - double dDiff = - (double)(powLimit & 0x00ffffff) / - (double)(bits & 0x00ffffff); - - while (nShift < nShiftAmount) - { - dDiff *= 256.0; - nShift++; - } - while (nShift > nShiftAmount) - { - dDiff /= 256.0; - nShift--; - } - - return dDiff; -} - -double GetDifficulty(const CBlockIndex* blockindex) -{ - return GetDifficultyINTERNAL(blockindex, false); -} - -double GetNetworkDifficulty(const CBlockIndex* blockindex) -{ - return GetDifficultyINTERNAL(blockindex, true); -} - -static UniValue ValuePoolDesc( - const std::string &name, - const boost::optional chainValue, - const boost::optional valueDelta) -{ - UniValue rv(UniValue::VOBJ); - rv.push_back(Pair("id", name)); - rv.push_back(Pair("monitored", (bool)chainValue)); - if (chainValue) { - rv.push_back(Pair("chainValue", ValueFromAmount(*chainValue))); - rv.push_back(Pair("chainValueZat", *chainValue)); - } - if (valueDelta) { - rv.push_back(Pair("valueDelta", ValueFromAmount(*valueDelta))); - rv.push_back(Pair("valueDeltaZat", *valueDelta)); - } - return rv; -} - -UniValue blockheaderToJSON(const CBlockIndex* blockindex) -{ - UniValue result(UniValue::VOBJ); - if ( blockindex == 0 ) - { - result.push_back(Pair("error", "null blockhash")); - return(result); - } - result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex())); - int confirmations = -1; - // Only report confirmations if the block is on the main chain - if (chainActive.Contains(blockindex)) - confirmations = chainActive.Height() - blockindex->nHeight + 1; - result.push_back(Pair("confirmations", komodo_dpowconfs(blockindex->nHeight,confirmations))); - result.push_back(Pair("rawconfirmations", confirmations)); - result.push_back(Pair("height", blockindex->nHeight)); - result.push_back(Pair("version", blockindex->nVersion)); - result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex())); - result.push_back(Pair("time", (int64_t)blockindex->nTime)); - result.push_back(Pair("nonce", blockindex->nNonce.GetHex())); - result.push_back(Pair("solution", HexStr(blockindex->nSolution))); - result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits))); - result.push_back(Pair("difficulty", GetDifficulty(blockindex))); - result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); - result.push_back(Pair("segid", (int64_t)blockindex->segid)); - - if (blockindex->pprev) - result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); - CBlockIndex *pnext = chainActive.Next(blockindex); - if (pnext) - result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex())); - return result; -} - -UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex) -{ - UniValue result(UniValue::VOBJ); - result.push_back(Pair("hash", block.GetHash().GetHex())); - int confirmations = -1; - // Only report confirmations if the block is on the main chain - if (chainActive.Contains(blockindex)) { - confirmations = chainActive.Height() - blockindex->nHeight + 1; - } else { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block is an orphan"); - } - result.push_back(Pair("confirmations", komodo_dpowconfs(blockindex->nHeight,confirmations))); - result.push_back(Pair("rawconfirmations", confirmations)); - result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); - result.push_back(Pair("height", blockindex->nHeight)); - result.push_back(Pair("version", block.nVersion)); - result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); - result.push_back(Pair("segid", (int64_t)blockindex->segid)); - - UniValue deltas(UniValue::VARR); - - for (unsigned int i = 0; i < block.vtx.size(); i++) { - const CTransaction &tx = block.vtx[i]; - const uint256 txhash = tx.GetHash(); - - UniValue entry(UniValue::VOBJ); - entry.push_back(Pair("txid", txhash.GetHex())); - entry.push_back(Pair("index", (int)i)); - - UniValue inputs(UniValue::VARR); - - if (!tx.IsCoinBase()) { - - for (size_t j = 0; j < tx.vin.size(); j++) { - const CTxIn input = tx.vin[j]; - - UniValue delta(UniValue::VOBJ); - - CSpentIndexValue spentInfo; - CSpentIndexKey spentKey(input.prevout.hash, input.prevout.n); - - if (GetSpentIndex(spentKey, spentInfo)) { - if (spentInfo.addressType == 1) { - delta.push_back(Pair("address", CBitcoinAddress(CKeyID(spentInfo.addressHash)).ToString())); - } - else if (spentInfo.addressType == 2) { - delta.push_back(Pair("address", CBitcoinAddress(CScriptID(spentInfo.addressHash)).ToString())); - } - else { - continue; - } - delta.push_back(Pair("satoshis", -1 * spentInfo.satoshis)); - delta.push_back(Pair("index", (int)j)); - delta.push_back(Pair("prevtxid", input.prevout.hash.GetHex())); - delta.push_back(Pair("prevout", (int)input.prevout.n)); - - inputs.push_back(delta); - } else { - throw JSONRPCError(RPC_INTERNAL_ERROR, "Spent information not available"); - } - - } - } - - entry.push_back(Pair("inputs", inputs)); - - UniValue outputs(UniValue::VARR); - - for (unsigned int k = 0; k < tx.vout.size(); k++) { - const CTxOut &out = tx.vout[k]; - - UniValue delta(UniValue::VOBJ); - - if (out.scriptPubKey.IsPayToScriptHash()) { - vector hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22); - delta.push_back(Pair("address", CBitcoinAddress(CScriptID(uint160(hashBytes))).ToString())); - - } - else if (out.scriptPubKey.IsPayToPublicKeyHash()) { - vector hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23); - delta.push_back(Pair("address", CBitcoinAddress(CKeyID(uint160(hashBytes))).ToString())); - } - else if (out.scriptPubKey.IsPayToPublicKey() || out.scriptPubKey.IsPayToCryptoCondition()) { - CTxDestination address; - if (ExtractDestination(out.scriptPubKey, address)) - { - //vector hashBytes(out.scriptPubKey.begin()+1, out.scriptPubKey.begin()+34); - //xxx delta.push_back(Pair("address", CBitcoinAddress(CKeyID(uint160(hashBytes))).ToString())); - delta.push_back(Pair("address", CBitcoinAddress(address).ToString())); - } - } - else { - continue; - } - - delta.push_back(Pair("satoshis", out.nValue)); - delta.push_back(Pair("index", (int)k)); - - outputs.push_back(delta); - } - - entry.push_back(Pair("outputs", outputs)); - deltas.push_back(entry); - - } - result.push_back(Pair("deltas", deltas)); - result.push_back(Pair("time", block.GetBlockTime())); - result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast())); - result.push_back(Pair("nonce", block.nNonce.GetHex())); - result.push_back(Pair("bits", strprintf("%08x", block.nBits))); - result.push_back(Pair("difficulty", GetDifficulty(blockindex))); - result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); - - if (blockindex->pprev) - result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); - CBlockIndex *pnext = chainActive.Next(blockindex); - if (pnext) - result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex())); - return result; -} - -UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false) -{ - UniValue result(UniValue::VOBJ); - result.push_back(Pair("hash", block.GetHash().GetHex())); - int confirmations = -1; - // Only report confirmations if the block is on the main chain - if (chainActive.Contains(blockindex)) - confirmations = chainActive.Height() - blockindex->nHeight + 1; - result.push_back(Pair("confirmations", komodo_dpowconfs(blockindex->nHeight,confirmations))); - result.push_back(Pair("rawconfirmations", confirmations)); - result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); - result.push_back(Pair("height", blockindex->nHeight)); - result.push_back(Pair("version", block.nVersion)); - result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); - result.push_back(Pair("segid", (int64_t)blockindex->segid)); - UniValue txs(UniValue::VARR); - BOOST_FOREACH(const CTransaction&tx, block.vtx) - { - if(txDetails) - { - UniValue objTx(UniValue::VOBJ); - TxToJSON(tx, uint256(), objTx); - txs.push_back(objTx); - } - else - txs.push_back(tx.GetHash().GetHex()); - } - result.push_back(Pair("tx", txs)); - result.push_back(Pair("time", block.GetBlockTime())); - result.push_back(Pair("nonce", block.nNonce.GetHex())); - result.push_back(Pair("solution", HexStr(block.nSolution))); - result.push_back(Pair("bits", strprintf("%08x", block.nBits))); - result.push_back(Pair("difficulty", GetDifficulty(blockindex))); - result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); - result.push_back(Pair("anchor", blockindex->hashAnchorEnd.GetHex())); - - UniValue valuePools(UniValue::VARR); - valuePools.push_back(ValuePoolDesc("sprout", blockindex->nChainSproutValue, blockindex->nSproutValue)); - result.push_back(Pair("valuePools", valuePools)); - - if (blockindex->pprev) - result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); - CBlockIndex *pnext = chainActive.Next(blockindex); - if (pnext) - result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex())); - return result; -} - -UniValue getblockcount(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getblockcount\n" - "\nReturns the number of blocks in the best valid block chain.\n" - "\nResult:\n" - "n (numeric) The current block count\n" - "\nExamples:\n" - + HelpExampleCli("getblockcount", "") - + HelpExampleRpc("getblockcount", "") - ); - - LOCK(cs_main); - return chainActive.Height(); -} - -UniValue getbestblockhash(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getbestblockhash\n" - "\nReturns the hash of the best (tip) block in the longest block chain.\n" - "\nResult\n" - "\"hex\" (string) the block hash hex encoded\n" - "\nExamples\n" - + HelpExampleCli("getbestblockhash", "") - + HelpExampleRpc("getbestblockhash", "") - ); - - LOCK(cs_main); - return chainActive.LastTip()->GetBlockHash().GetHex(); -} - -UniValue getdifficulty(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getdifficulty\n" - "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n" - "\nResult:\n" - "n.nnn (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n" - "\nExamples:\n" - + HelpExampleCli("getdifficulty", "") - + HelpExampleRpc("getdifficulty", "") - ); - - LOCK(cs_main); - return GetNetworkDifficulty(); -} - -bool myIsutxo_spentinmempool(uint256 txid,int32_t vout) -{ - //char *uint256_str(char *str,uint256); char str[65]; - //LOCK(mempool.cs); - BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) - { - const CTransaction &tx = e.GetTx(); - const uint256 &hash = tx.GetHash(); - BOOST_FOREACH(const CTxIn &txin,tx.vin) - { - //fprintf(stderr,"%s/v%d ",uint256_str(str,txin.prevout.hash),txin.prevout.n); - if ( txin.prevout.n == vout && txin.prevout.hash == txid ) - return(true); - } - //fprintf(stderr,"are vins for %s\n",uint256_str(str,hash)); - } - return(false); -} - -bool mytxid_inmempool(uint256 txid) -{ - BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) - { - const CTransaction &tx = e.GetTx(); - const uint256 &hash = tx.GetHash(); - if ( txid == hash ) - return(true); - } - return(false); -} - -UniValue mempoolToJSON(bool fVerbose = false) -{ - if (fVerbose) - { - LOCK(mempool.cs); - UniValue o(UniValue::VOBJ); - BOOST_FOREACH(const CTxMemPoolEntry& e, mempool.mapTx) - { - const uint256& hash = e.GetTx().GetHash(); - UniValue info(UniValue::VOBJ); - info.push_back(Pair("size", (int)e.GetTxSize())); - info.push_back(Pair("fee", ValueFromAmount(e.GetFee()))); - info.push_back(Pair("time", e.GetTime())); - info.push_back(Pair("height", (int)e.GetHeight())); - info.push_back(Pair("startingpriority", e.GetPriority(e.GetHeight()))); - info.push_back(Pair("currentpriority", e.GetPriority(chainActive.Height()))); - const CTransaction& tx = e.GetTx(); - set setDepends; - BOOST_FOREACH(const CTxIn& txin, tx.vin) - { - if (mempool.exists(txin.prevout.hash)) - setDepends.insert(txin.prevout.hash.ToString()); - } - - UniValue depends(UniValue::VARR); - BOOST_FOREACH(const string& dep, setDepends) - { - depends.push_back(dep); - } - - info.push_back(Pair("depends", depends)); - o.push_back(Pair(hash.ToString(), info)); - } - return o; - } - else - { - vector vtxid; - mempool.queryHashes(vtxid); - - UniValue a(UniValue::VARR); - BOOST_FOREACH(const uint256& hash, vtxid) - a.push_back(hash.ToString()); - - return a; - } -} - -UniValue getrawmempool(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() > 1) - throw runtime_error( - "getrawmempool ( verbose )\n" - "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n" - "\nArguments:\n" - "1. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n" - "\nResult: (for verbose = false):\n" - "[ (json array of string)\n" - " \"transactionid\" (string) The transaction id\n" - " ,...\n" - "]\n" - "\nResult: (for verbose = true):\n" - "{ (json object)\n" - " \"transactionid\" : { (json object)\n" - " \"size\" : n, (numeric) transaction size in bytes\n" - " \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\n" - " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n" - " \"height\" : n, (numeric) block height when transaction entered pool\n" - " \"startingpriority\" : n, (numeric) priority when transaction entered pool\n" - " \"currentpriority\" : n, (numeric) transaction priority now\n" - " \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n" - " \"transactionid\", (string) parent transaction id\n" - " ... ]\n" - " }, ...\n" - "}\n" - "\nExamples\n" - + HelpExampleCli("getrawmempool", "true") - + HelpExampleRpc("getrawmempool", "true") - ); - - LOCK(cs_main); - - bool fVerbose = false; - if (params.size() > 0) - fVerbose = params[0].get_bool(); - - return mempoolToJSON(fVerbose); -} - -UniValue getblockdeltas(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error(""); - - std::string strHash = params[0].get_str(); - uint256 hash(uint256S(strHash)); - - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlock block; - CBlockIndex* pblockindex = mapBlockIndex[hash]; - - if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); - - if(!ReadBlockFromDisk(block, pblockindex,1)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); - - return blockToDeltasJSON(block, pblockindex); -} - -UniValue getblockhashes(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() < 2) - throw runtime_error( - "getblockhashes timestamp\n" - "\nReturns array of hashes of blocks within the timestamp range provided.\n" - "\nArguments:\n" - "1. high (numeric, required) The newer block timestamp\n" - "2. low (numeric, required) The older block timestamp\n" - "3. options (string, required) A json object\n" - " {\n" - " \"noOrphans\":true (boolean) will only include blocks on the main chain\n" - " \"logicalTimes\":true (boolean) will include logical timestamps with hashes\n" - " }\n" - "\nResult:\n" - "[\n" - " \"hash\" (string) The block hash\n" - "]\n" - "[\n" - " {\n" - " \"blockhash\": (string) The block hash\n" - " \"logicalts\": (numeric) The logical timestamp\n" - " }\n" - "]\n" - "\nExamples:\n" - + HelpExampleCli("getblockhashes", "1231614698 1231024505") - + HelpExampleRpc("getblockhashes", "1231614698, 1231024505") - + HelpExampleCli("getblockhashes", "1231614698 1231024505 '{\"noOrphans\":false, \"logicalTimes\":true}'") - ); - - unsigned int high = params[0].get_int(); - unsigned int low = params[1].get_int(); - bool fActiveOnly = false; - bool fLogicalTS = false; - - if (params.size() > 2) { - if (params[2].isObject()) { - UniValue noOrphans = find_value(params[2].get_obj(), "noOrphans"); - UniValue returnLogical = find_value(params[2].get_obj(), "logicalTimes"); - - if (noOrphans.isBool()) - fActiveOnly = noOrphans.get_bool(); - - if (returnLogical.isBool()) - fLogicalTS = returnLogical.get_bool(); - } - } - - std::vector > blockHashes; - - if (fActiveOnly) - LOCK(cs_main); - - if (!GetTimestampIndex(high, low, fActiveOnly, blockHashes)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for block hashes"); - } - - UniValue result(UniValue::VARR); - - for (std::vector >::const_iterator it=blockHashes.begin(); it!=blockHashes.end(); it++) { - if (fLogicalTS) { - UniValue item(UniValue::VOBJ); - item.push_back(Pair("blockhash", it->first.GetHex())); - item.push_back(Pair("logicalts", (int)it->second)); - result.push_back(item); - } else { - result.push_back(it->first.GetHex()); - } - } - - return result; -} - -UniValue getblockhash(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "getblockhash index\n" - "\nReturns hash of block in best-block-chain at index provided.\n" - "\nArguments:\n" - "1. index (numeric, required) The block index\n" - "\nResult:\n" - "\"hash\" (string) The block hash\n" - "\nExamples:\n" - + HelpExampleCli("getblockhash", "1000") - + HelpExampleRpc("getblockhash", "1000") - ); - - LOCK(cs_main); - - int nHeight = params[0].get_int(); - if (nHeight < 0 || nHeight > chainActive.Height()) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); - - CBlockIndex* pblockindex = chainActive[nHeight]; - return pblockindex->GetBlockHash().GetHex(); -} - -/*uint256 _komodo_getblockhash(int32_t nHeight) -{ - uint256 hash; - LOCK(cs_main); - if ( nHeight >= 0 && nHeight <= chainActive.Height() ) - { - CBlockIndex* pblockindex = chainActive[nHeight]; - hash = pblockindex->GetBlockHash(); - int32_t i; - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&hash)[i]); - printf(" blockhash.%d\n",nHeight); - } else memset(&hash,0,sizeof(hash)); - return(hash); -}*/ - -UniValue getblockheader(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() < 1 || params.size() > 2) - throw runtime_error( - "getblockheader \"hash\" ( verbose )\n" - "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n" - "If verbose is true, returns an Object with information about blockheader .\n" - "\nArguments:\n" - "1. \"hash\" (string, required) The block hash\n" - "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n" - "\nResult (for verbose = true):\n" - "{\n" - " \"hash\" : \"hash\", (string) the block hash (same as provided)\n" - " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" - " \"height\" : n, (numeric) The block height or index\n" - " \"version\" : n, (numeric) The block version\n" - " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" - " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"nonce\" : n, (numeric) The nonce\n" - " \"bits\" : \"1d00ffff\", (string) The bits\n" - " \"difficulty\" : x.xxx, (numeric) The difficulty\n" - " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" - " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n" - "}\n" - "\nResult (for verbose=false):\n" - "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n" - "\nExamples:\n" - + HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - ); - - LOCK(cs_main); - - std::string strHash = params[0].get_str(); - uint256 hash(uint256S(strHash)); - - bool fVerbose = true; - if (params.size() > 1) - fVerbose = params[1].get_bool(); - - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlockIndex* pblockindex = mapBlockIndex[hash]; - - if (!fVerbose) - { - CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); - ssBlock << pblockindex->GetBlockHeader(); - std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()); - return strHex; - } - - return blockheaderToJSON(pblockindex); -} - -UniValue getblock(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() < 1 || params.size() > 2) - throw runtime_error( - "getblock \"hash|height\" ( verbose )\n" - "\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash|height'.\n" - "If verbose is true, returns an Object with information about block .\n" - "\nArguments:\n" - "1. \"hash|height\" (string, required) The block hash or height\n" - "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n" - "\nResult (for verbose = true):\n" - "{\n" - " \"hash\" : \"hash\", (string) the block hash (same as provided hash)\n" - " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" - " \"size\" : n, (numeric) The block size\n" - " \"height\" : n, (numeric) The block height or index (same as provided height)\n" - " \"version\" : n, (numeric) The block version\n" - " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" - " \"tx\" : [ (array of string) The transaction ids\n" - " \"transactionid\" (string) The transaction id\n" - " ,...\n" - " ],\n" - " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"nonce\" : n, (numeric) The nonce\n" - " \"bits\" : \"1d00ffff\", (string) The bits\n" - " \"difficulty\" : x.xxx, (numeric) The difficulty\n" - " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" - " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n" - "}\n" - "\nResult (for verbose=false):\n" - "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n" - "\nExamples:\n" - + HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - + HelpExampleCli("getblock", "12800") - + HelpExampleRpc("getblock", "12800") - ); - - LOCK(cs_main); - - std::string strHash = params[0].get_str(); - - // If height is supplied, find the hash - if (strHash.size() < (2 * sizeof(uint256))) { - // std::stoi allows characters, whereas we want to be strict - regex r("[[:digit:]]+"); - if (!regex_match(strHash, r)) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter"); - } - - int nHeight = -1; - try { - nHeight = std::stoi(strHash); - } - catch (const std::exception &e) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter"); - } - - if (nHeight < 0 || nHeight > chainActive.Height()) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); - } - strHash = chainActive[nHeight]->GetBlockHash().GetHex(); - } - - uint256 hash(uint256S(strHash)); - - bool fVerbose = true; - if (params.size() > 1) - fVerbose = params[1].get_bool(); - - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlock block; - CBlockIndex* pblockindex = mapBlockIndex[hash]; - - if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); - - if(!ReadBlockFromDisk(block, pblockindex,1)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); - - if (!fVerbose) - { - CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); - ssBlock << block; - std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()); - return strHex; - } - - return blockToJSON(block, pblockindex); -} - -UniValue gettxoutsetinfo(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "gettxoutsetinfo\n" - "\nReturns statistics about the unspent transaction output set.\n" - "Note this call may take some time.\n" - "\nResult:\n" - "{\n" - " \"height\":n, (numeric) The current block height (index)\n" - " \"bestblock\": \"hex\", (string) the best block hash hex\n" - " \"transactions\": n, (numeric) The number of transactions\n" - " \"txouts\": n, (numeric) The number of output transactions\n" - " \"bytes_serialized\": n, (numeric) The serialized size\n" - " \"hash_serialized\": \"hash\", (string) The serialized hash\n" - " \"total_amount\": x.xxx (numeric) The total amount\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("gettxoutsetinfo", "") - + HelpExampleRpc("gettxoutsetinfo", "") - ); - - UniValue ret(UniValue::VOBJ); - - CCoinsStats stats; - FlushStateToDisk(); - if (pcoinsTip->GetStats(stats)) { - ret.push_back(Pair("height", (int64_t)stats.nHeight)); - ret.push_back(Pair("bestblock", stats.hashBlock.GetHex())); - ret.push_back(Pair("transactions", (int64_t)stats.nTransactions)); - ret.push_back(Pair("txouts", (int64_t)stats.nTransactionOutputs)); - ret.push_back(Pair("bytes_serialized", (int64_t)stats.nSerializedSize)); - ret.push_back(Pair("hash_serialized", stats.hashSerialized.GetHex())); - ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount))); - } - return ret; -} - -#include "komodo_defs.h" -#include "komodo_structs.h" - -#define IGUANA_MAXSCRIPTSIZE 10001 -#define KOMODO_KVDURATION 1440 -#define KOMODO_KVBINARY 2 -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume); -int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel); -int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); -char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len); -int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width); -int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); - -UniValue kvsearch(const UniValue& params, bool fHelp) -{ - UniValue ret(UniValue::VOBJ); uint32_t flags; uint8_t value[IGUANA_MAXSCRIPTSIZE*8],key[IGUANA_MAXSCRIPTSIZE*8]; int32_t duration,j,height,valuesize,keylen; uint256 refpubkey; static uint256 zeroes; - if (fHelp || params.size() != 1 ) - throw runtime_error( - "kvsearch key\n" - "\nSearch for a key stored via the kvupdate command. This feature is only available for asset chains.\n" - "\nArguments:\n" - "1. key (string, required) search the chain for this key\n" - "\nResult:\n" - "{\n" - " \"coin\": \"xxxxx\", (string) chain the key is stored on\n" - " \"currentheight\": xxxxx, (numeric) current height of the chain\n" - " \"key\": \"xxxxx\", (string) key\n" - " \"keylen\": xxxxx, (string) length of the key \n" - " \"owner\": \"xxxxx\" (string) hex string representing the owner of the key \n" - " \"height\": xxxxx, (numeric) height the key was stored at\n" - " \"expiration\": xxxxx, (numeric) height the key will expire\n" - " \"flags\": x (numeric) 1 if the key was created with a password; 0 otherwise.\n" - " \"value\": \"xxxxx\", (string) stored value\n" - " \"valuesize\": xxxxx (string) amount of characters stored\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("kvsearch", "examplekey") - + HelpExampleRpc("kvsearch", "\"examplekey\"") - ); - LOCK(cs_main); - if ( (keylen= (int32_t)strlen(params[0].get_str().c_str())) > 0 ) - { - ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL))); - ret.push_back(Pair("currentheight", (int64_t)chainActive.LastTip()->nHeight)); - ret.push_back(Pair("key",params[0].get_str())); - ret.push_back(Pair("keylen",keylen)); - if ( keylen < sizeof(key) ) - { - memcpy(key,params[0].get_str().c_str(),keylen); - if ( (valuesize= komodo_kvsearch(&refpubkey,chainActive.LastTip()->nHeight,&flags,&height,value,key,keylen)) >= 0 ) - { - std::string val; char *valuestr; - val.resize(valuesize); - valuestr = (char *)val.data(); - memcpy(valuestr,value,valuesize); - if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 ) - ret.push_back(Pair("owner",refpubkey.GetHex())); - ret.push_back(Pair("height",height)); - duration = ((flags >> 2) + 1) * KOMODO_KVDURATION; - ret.push_back(Pair("expiration", (int64_t)(height+duration))); - ret.push_back(Pair("flags",(int64_t)flags)); - ret.push_back(Pair("value",val)); - ret.push_back(Pair("valuesize",valuesize)); - } else ret.push_back(Pair("error",(char *)"cant find key")); - } else ret.push_back(Pair("error",(char *)"key too big")); - } else ret.push_back(Pair("error",(char *)"null key")); - return ret; -} - -UniValue minerids(const UniValue& params, bool fHelp) -{ - uint32_t timestamp = 0; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR); uint8_t minerids[2000],pubkeys[65][33]; int32_t i,j,n,numnotaries,tally[129]; - if ( fHelp || params.size() != 1 ) - throw runtime_error("minerids needs height\n"); - LOCK(cs_main); - int32_t height = atoi(params[0].get_str().c_str()); - if ( height <= 0 ) - height = chainActive.LastTip()->nHeight; - else - { - CBlockIndex *pblockindex = chainActive[height]; - if ( pblockindex != 0 ) - timestamp = pblockindex->GetBlockTime(); - } - if ( (n= komodo_minerids(minerids,height,(int32_t)(sizeof(minerids)/sizeof(*minerids)))) > 0 ) - { - memset(tally,0,sizeof(tally)); - numnotaries = komodo_notaries(pubkeys,height,timestamp); - if ( numnotaries > 0 ) - { - for (i=0; i= numnotaries ) - tally[128]++; - else tally[minerids[i]]++; - } - for (i=0; i<64; i++) - { - UniValue item(UniValue::VOBJ); std::string hex,kmdaddress; char *hexstr,kmdaddr[64],*ptr; int32_t m; - hex.resize(66); - hexstr = (char *)hex.data(); - for (j=0; j<33; j++) - sprintf(&hexstr[j*2],"%02x",pubkeys[i][j]); - item.push_back(Pair("notaryid", i)); - - bitcoin_address(kmdaddr,60,pubkeys[i],33); - m = (int32_t)strlen(kmdaddr); - kmdaddress.resize(m); - ptr = (char *)kmdaddress.data(); - memcpy(ptr,kmdaddr,m); - item.push_back(Pair("KMDaddress", kmdaddress)); - - item.push_back(Pair("pubkey", hex)); - item.push_back(Pair("blocks", tally[i])); - a.push_back(item); - } - UniValue item(UniValue::VOBJ); - item.push_back(Pair("pubkey", (char *)"external miners")); - item.push_back(Pair("blocks", tally[128])); - a.push_back(item); - } - ret.push_back(Pair("mined", a)); - ret.push_back(Pair("numnotaries", numnotaries)); - } else ret.push_back(Pair("error", (char *)"couldnt extract minerids")); - return ret; -} - -UniValue notaries(const UniValue& params, bool fHelp) -{ - UniValue a(UniValue::VARR); uint32_t timestamp=0; UniValue ret(UniValue::VOBJ); int32_t i,j,n,m; char *hexstr; uint8_t pubkeys[64][33]; char btcaddr[64],kmdaddr[64],*ptr; - if ( fHelp || (params.size() != 1 && params.size() != 2) ) - throw runtime_error("notaries height timestamp\n"); - LOCK(cs_main); - int32_t height = atoi(params[0].get_str().c_str()); - if ( params.size() == 2 ) - timestamp = (uint32_t)atol(params[1].get_str().c_str()); - else timestamp = (uint32_t)time(NULL); - if ( height < 0 ) - { - height = chainActive.LastTip()->nHeight; - timestamp = chainActive.LastTip()->GetBlockTime(); - } - else if ( params.size() < 2 ) - { - CBlockIndex *pblockindex = chainActive[height]; - if ( pblockindex != 0 ) - timestamp = pblockindex->GetBlockTime(); - } - if ( (n= komodo_notaries(pubkeys,height,timestamp)) > 0 ) - { - for (i=0; i 0 ) - ret.push_back(Pair("withdraws", opretbuf)); - else ret.push_back(Pair("withdraws", (char *)"")); - for (baseid=0; baseid<32; baseid++) - { - UniValue item(UniValue::VOBJ); UniValue obj(UniValue::VOBJ); - if ( pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,CURRENCIES[baseid]) == 0 ) - { - if ( deposited != 0 || issued != 0 || withdrawn != 0 || approved != 0 || redeemed != 0 ) - { - item.push_back(Pair("available", ValueFromAmount(available))); - item.push_back(Pair("deposited", ValueFromAmount(deposited))); - item.push_back(Pair("issued", ValueFromAmount(issued))); - item.push_back(Pair("withdrawn", ValueFromAmount(withdrawn))); - item.push_back(Pair("approved", ValueFromAmount(approved))); - item.push_back(Pair("redeemed", ValueFromAmount(redeemed))); - obj.push_back(Pair(CURRENCIES[baseid],item)); - a.push_back(obj); - } - } - } - ret.push_back(Pair("fiatstatus", a)); - return ret; -} - -UniValue paxprice(const UniValue& params, bool fHelp) -{ - if ( fHelp || params.size() > 4 || params.size() < 2 ) - throw runtime_error("paxprice \"base\" \"rel\" height\n"); - LOCK(cs_main); - UniValue ret(UniValue::VOBJ); uint64_t basevolume=0,relvolume,seed; - std::string base = params[0].get_str(); - std::string rel = params[1].get_str(); - int32_t height; - if ( params.size() == 2 ) - height = chainActive.LastTip()->nHeight; - else height = atoi(params[2].get_str().c_str()); - //if ( params.size() == 3 || (basevolume= COIN * atof(params[3].get_str().c_str())) == 0 ) - basevolume = 100000; - relvolume = komodo_paxprice(&seed,height,(char *)base.c_str(),(char *)rel.c_str(),basevolume); - ret.push_back(Pair("base", base)); - ret.push_back(Pair("rel", rel)); - ret.push_back(Pair("height", height)); - char seedstr[32]; - sprintf(seedstr,"%llu",(long long)seed); - ret.push_back(Pair("seed", seedstr)); - if ( height < 0 || height > chainActive.Height() ) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); - else - { - CBlockIndex *pblockindex = chainActive[height]; - if ( pblockindex != 0 ) - ret.push_back(Pair("timestamp", (int64_t)pblockindex->nTime)); - if ( basevolume != 0 && relvolume != 0 ) - { - ret.push_back(Pair("price",((double)relvolume / (double)basevolume))); - ret.push_back(Pair("invprice",((double)basevolume / (double)relvolume))); - ret.push_back(Pair("basevolume",ValueFromAmount(basevolume))); - ret.push_back(Pair("relvolume",ValueFromAmount(relvolume))); - } else ret.push_back(Pair("error", "overflow or error in one or more of parameters")); - } - return ret; -} - -UniValue paxprices(const UniValue& params, bool fHelp) -{ - if ( fHelp || params.size() != 3 ) - throw runtime_error("paxprices \"base\" \"rel\" maxsamples\n"); - LOCK(cs_main); - UniValue ret(UniValue::VOBJ); uint64_t relvolume,prices[4096]; uint32_t i,n; int32_t heights[sizeof(prices)/sizeof(*prices)]; - std::string base = params[0].get_str(); - std::string rel = params[1].get_str(); - int32_t maxsamples = atoi(params[2].get_str().c_str()); - if ( maxsamples < 1 ) - maxsamples = 1; - else if ( maxsamples > sizeof(heights)/sizeof(*heights) ) - maxsamples = sizeof(heights)/sizeof(*heights); - ret.push_back(Pair("base", base)); - ret.push_back(Pair("rel", rel)); - n = komodo_paxprices(heights,prices,maxsamples,(char *)base.c_str(),(char *)rel.c_str()); - UniValue a(UniValue::VARR); - for (i=0; i chainActive.Height() ) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); - else - { - CBlockIndex *pblockindex = chainActive[heights[i]]; - - item.push_back(Pair("t", (int64_t)pblockindex->nTime)); - item.push_back(Pair("p", (double)prices[i] / COIN)); - a.push_back(item); - } - } - ret.push_back(Pair("array", a)); - return ret; -} - -uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); - -UniValue gettxout(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() < 2 || params.size() > 3) - throw runtime_error( - "gettxout \"txid\" n ( includemempool )\n" - "\nReturns details about an unspent transaction output.\n" - "\nArguments:\n" - "1. \"txid\" (string, required) The transaction id\n" - "2. n (numeric, required) vout value\n" - "3. includemempool (boolean, optional) Whether to include the mempool\n" - "\nResult:\n" - "{\n" - " \"bestblock\" : \"hash\", (string) the block hash\n" - " \"confirmations\" : n, (numeric) The number of confirmations\n" - " \"value\" : x.xxx, (numeric) The transaction value in " + CURRENCY_UNIT + "\n" - " \"scriptPubKey\" : { (json object)\n" - " \"asm\" : \"code\", (string) \n" - " \"hex\" : \"hex\", (string) \n" - " \"reqSigs\" : n, (numeric) Number of required signatures\n" - " \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n" - " \"addresses\" : [ (array of string) array of Komodo addresses\n" - " \"komodoaddress\" (string) Komodo address\n" - " ,...\n" - " ]\n" - " },\n" - " \"version\" : n, (numeric) The version\n" - " \"coinbase\" : true|false (boolean) Coinbase or not\n" - "}\n" - - "\nExamples:\n" - "\nGet unspent transactions\n" - + HelpExampleCli("listunspent", "") + - "\nView the details\n" - + HelpExampleCli("gettxout", "\"txid\" 1") + - "\nAs a json rpc call\n" - + HelpExampleRpc("gettxout", "\"txid\", 1") - ); - - LOCK(cs_main); - - UniValue ret(UniValue::VOBJ); - - std::string strHash = params[0].get_str(); - uint256 hash(uint256S(strHash)); - int n = params[1].get_int(); - bool fMempool = true; - if (params.size() > 2) - fMempool = params[2].get_bool(); - - CCoins coins; - if (fMempool) { - LOCK(mempool.cs); - CCoinsViewMemPool view(pcoinsTip, mempool); - if (!view.GetCoins(hash, coins)) - return NullUniValue; - mempool.pruneSpent(hash, coins); // TODO: this should be done by the CCoinsViewMemPool - } else { - if (!pcoinsTip->GetCoins(hash, coins)) - return NullUniValue; - } - if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull()) - return NullUniValue; - - BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); - CBlockIndex *pindex = it->second; - ret.push_back(Pair("bestblock", pindex->GetBlockHash().GetHex())); - if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT) - ret.push_back(Pair("confirmations", 0)); - else - { - ret.push_back(Pair("confirmations", komodo_dpowconfs(coins.nHeight,pindex->nHeight - coins.nHeight + 1))); - ret.push_back(Pair("rawconfirmations", pindex->nHeight - coins.nHeight + 1)); - } - ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue))); - uint64_t interest; int32_t txheight; uint32_t locktime; - if ( (interest= komodo_accrued_interest(&txheight,&locktime,hash,n,coins.nHeight,coins.vout[n].nValue,(int32_t)pindex->nHeight)) != 0 ) - ret.push_back(Pair("interest", ValueFromAmount(interest))); - UniValue o(UniValue::VOBJ); - ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true); - ret.push_back(Pair("scriptPubKey", o)); - ret.push_back(Pair("version", coins.nVersion)); - ret.push_back(Pair("coinbase", coins.fCoinBase)); - - return ret; -} - -UniValue verifychain(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() > 2) - throw runtime_error( - "verifychain ( checklevel numblocks )\n" - "\nVerifies blockchain database.\n" - "\nArguments:\n" - "1. checklevel (numeric, optional, 0-4, default=3) How thorough the block verification is.\n" - "2. numblocks (numeric, optional, default=288, 0=all) The number of blocks to check.\n" - "\nResult:\n" - "true|false (boolean) Verified or not\n" - "\nExamples:\n" - + HelpExampleCli("verifychain", "") - + HelpExampleRpc("verifychain", "") - ); - - LOCK(cs_main); - - int nCheckLevel = GetArg("-checklevel", 3); - int nCheckDepth = GetArg("-checkblocks", 288); - if (params.size() > 0) - nCheckLevel = params[0].get_int(); - if (params.size() > 1) - nCheckDepth = params[1].get_int(); - - return CVerifyDB().VerifyDB(pcoinsTip, nCheckLevel, nCheckDepth); -} - -/** Implementation of IsSuperMajority with better feedback */ -static UniValue SoftForkMajorityDesc(int minVersion, CBlockIndex* pindex, int nRequired, const Consensus::Params& consensusParams) -{ - int nFound = 0; - CBlockIndex* pstart = pindex; - for (int i = 0; i < consensusParams.nMajorityWindow && pstart != NULL; i++) - { - if (pstart->nVersion >= minVersion) - ++nFound; - pstart = pstart->pprev; - } - - UniValue rv(UniValue::VOBJ); - rv.push_back(Pair("status", nFound >= nRequired)); - rv.push_back(Pair("found", nFound)); - rv.push_back(Pair("required", nRequired)); - rv.push_back(Pair("window", consensusParams.nMajorityWindow)); - return rv; -} - -static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, const Consensus::Params& consensusParams) -{ - UniValue rv(UniValue::VOBJ); - rv.push_back(Pair("id", name)); - rv.push_back(Pair("version", version)); - rv.push_back(Pair("enforce", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams))); - rv.push_back(Pair("reject", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityRejectBlockOutdated, consensusParams))); - return rv; -} - -static UniValue NetworkUpgradeDesc(const Consensus::Params& consensusParams, Consensus::UpgradeIndex idx, int height) -{ - UniValue rv(UniValue::VOBJ); - auto upgrade = NetworkUpgradeInfo[idx]; - rv.push_back(Pair("name", upgrade.strName)); - rv.push_back(Pair("activationheight", consensusParams.vUpgrades[idx].nActivationHeight)); - switch (NetworkUpgradeState(height, consensusParams, idx)) { - case UPGRADE_DISABLED: rv.push_back(Pair("status", "disabled")); break; - case UPGRADE_PENDING: rv.push_back(Pair("status", "pending")); break; - case UPGRADE_ACTIVE: rv.push_back(Pair("status", "active")); break; - } - rv.push_back(Pair("info", upgrade.strInfo)); - return rv; -} - -void NetworkUpgradeDescPushBack( - UniValue& networkUpgrades, - const Consensus::Params& consensusParams, - Consensus::UpgradeIndex idx, - int height) -{ - // Network upgrades with an activation height of NO_ACTIVATION_HEIGHT are - // hidden. This is used when network upgrade implementations are merged - // without specifying the activation height. - if (consensusParams.vUpgrades[idx].nActivationHeight != Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT) { - networkUpgrades.push_back(Pair( - HexInt(NetworkUpgradeInfo[idx].nBranchId), - NetworkUpgradeDesc(consensusParams, idx, height))); - } -} - - -UniValue getblockchaininfo(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getblockchaininfo\n" - "Returns an object containing various state info regarding block chain processing.\n" - "\nNote that when the chain tip is at the last block before a network upgrade activation,\n" - "consensus.chaintip != consensus.nextblock.\n" - "\nResult:\n" - "{\n" - " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" - " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n" - " \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n" - " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n" - " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" - " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n" - " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" - " \"size_on_disk\": xxxxxx, (numeric) the estimated size of the block and undo files on disk\n" - " \"commitments\": xxxxxx, (numeric) the current number of note commitments in the commitment tree\n" - " \"softforks\": [ (array) status of softforks in progress\n" - " {\n" - " \"id\": \"xxxx\", (string) name of softfork\n" - " \"version\": xx, (numeric) block version\n" - " \"enforce\": { (object) progress toward enforcing the softfork rules for new-version blocks\n" - " \"status\": xx, (boolean) true if threshold reached\n" - " \"found\": xx, (numeric) number of blocks with the new version found\n" - " \"required\": xx, (numeric) number of blocks required to trigger\n" - " \"window\": xx, (numeric) maximum size of examined window of recent blocks\n" - " },\n" - " \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n" - " }, ...\n" - " ],\n" - " \"upgrades\": { (object) status of network upgrades\n" - " \"xxxx\" : { (string) branch ID of the upgrade\n" - " \"name\": \"xxxx\", (string) name of upgrade\n" - " \"activationheight\": xxxxxx, (numeric) block height of activation\n" - " \"status\": \"xxxx\", (string) status of upgrade\n" - " \"info\": \"xxxx\", (string) additional information about upgrade\n" - " }, ...\n" - " },\n" - " \"consensus\": { (object) branch IDs of the current and upcoming consensus rules\n" - " \"chaintip\": \"xxxxxxxx\", (string) branch ID used to validate the current chain tip\n" - " \"nextblock\": \"xxxxxxxx\" (string) branch ID that the next block will be validated under\n" - " }\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("getblockchaininfo", "") - + HelpExampleRpc("getblockchaininfo", "") - ); - - LOCK(cs_main); - double progress; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) { - progress = Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.LastTip()); - } else { - int32_t longestchain = KOMODO_LONGESTCHAIN;//komodo_longestchain(); - progress = (longestchain > 0 ) ? (double) chainActive.Height() / longestchain : 1.0; - } - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("chain", Params().NetworkIDString())); - obj.push_back(Pair("blocks", (int)chainActive.Height())); - obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1)); - obj.push_back(Pair("bestblockhash", chainActive.LastTip()->GetBlockHash().GetHex())); - obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty())); - obj.push_back(Pair("verificationprogress", progress)); - obj.push_back(Pair("chainwork", chainActive.LastTip()->nChainWork.GetHex())); - obj.push_back(Pair("pruned", fPruneMode)); - obj.push_back(Pair("size_on_disk", CalculateCurrentUsage())); - - ZCIncrementalMerkleTree tree; - pcoinsTip->GetAnchorAt(pcoinsTip->GetBestAnchor(), tree); - #ifdef __APPLE__ - obj.push_back(Pair("commitments", (uint64_t)tree.size())); - #else - obj.push_back(Pair("commitments", tree.size())); - #endif - - CBlockIndex* tip = chainActive.LastTip(); - UniValue valuePools(UniValue::VARR); - valuePools.push_back(ValuePoolDesc("sprout", tip->nChainSproutValue, boost::none)); - obj.push_back(Pair("valuePools", valuePools)); - - const Consensus::Params& consensusParams = Params().GetConsensus(); - UniValue softforks(UniValue::VARR); - softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams)); - softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams)); - softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams)); - obj.push_back(Pair("softforks", softforks)); - - UniValue upgrades(UniValue::VOBJ); - for (int i = Consensus::UPGRADE_OVERWINTER; i < Consensus::MAX_NETWORK_UPGRADES; i++) { - NetworkUpgradeDescPushBack(upgrades, consensusParams, Consensus::UpgradeIndex(i), tip->nHeight); - } - obj.push_back(Pair("upgrades", upgrades)); - - UniValue consensus(UniValue::VOBJ); - consensus.push_back(Pair("chaintip", HexInt(CurrentEpochBranchId(tip->nHeight, consensusParams)))); - consensus.push_back(Pair("nextblock", HexInt(CurrentEpochBranchId(tip->nHeight + 1, consensusParams)))); - obj.push_back(Pair("consensus", consensus)); - - if (fPruneMode) - { - CBlockIndex *block = chainActive.LastTip(); - while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) - block = block->pprev; - - obj.push_back(Pair("pruneheight", block->nHeight)); - } - return obj; -} - -/** Comparison function for sorting the getchaintips heads. */ -struct CompareBlocksByHeight -{ - bool operator()(const CBlockIndex* a, const CBlockIndex* b) const - { - /* Make sure that unequal blocks with the same height do not compare - equal. Use the pointers themselves to make a distinction. */ - - if (a->nHeight != b->nHeight) - return (a->nHeight > b->nHeight); - - return a < b; - } -}; - -#include - -UniValue getchaintips(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getchaintips\n" - "Return information about all known tips in the block tree," - " including the main chain as well as orphaned branches.\n" - "\nResult:\n" - "[\n" - " {\n" - " \"height\": xxxx, (numeric) height of the chain tip\n" - " \"hash\": \"xxxx\", (string) block hash of the tip\n" - " \"branchlen\": 0 (numeric) zero for main chain\n" - " \"status\": \"active\" (string) \"active\" for the main chain\n" - " },\n" - " {\n" - " \"height\": xxxx,\n" - " \"hash\": \"xxxx\",\n" - " \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n" - " \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n" - " }\n" - "]\n" - "Possible values for status:\n" - "1. \"invalid\" This branch contains at least one invalid block\n" - "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n" - "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n" - "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n" - "5. \"active\" This is the tip of the active main chain, which is certainly valid\n" - "\nExamples:\n" - + HelpExampleCli("getchaintips", "") - + HelpExampleRpc("getchaintips", "") - ); - - LOCK(cs_main); - - /* Build up a list of chain tips. We start with the list of all - known blocks, and successively remove blocks that appear as pprev - of another block. */ - /*static pthread_mutex_t mutex; static int32_t didinit; - if ( didinit == 0 ) - { - pthread_mutex_init(&mutex,NULL); - didinit = 1; - } - pthread_mutex_lock(&mutex);*/ - std::set setTips; - int32_t n = 0; - BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex) - { - n++; - setTips.insert(item.second); - } - fprintf(stderr,"iterations getchaintips %d\n",n); - n = 0; - BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex) - { - const CBlockIndex* pprev=0; - n++; - if ( item.second != 0 ) - pprev = item.second->pprev; - if (pprev) - setTips.erase(pprev); - } - fprintf(stderr,"iterations getchaintips %d\n",n); - //pthread_mutex_unlock(&mutex); - - // Always report the currently active tip. - setTips.insert(chainActive.LastTip()); - - /* Construct the output array. */ - UniValue res(UniValue::VARR); const CBlockIndex *forked; - BOOST_FOREACH(const CBlockIndex* block, setTips) - BOOST_FOREACH(const CBlockIndex* block, setTips) - { - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("height", block->nHeight)); - obj.push_back(Pair("hash", block->phashBlock->GetHex())); - forked = chainActive.FindFork(block); - if ( forked != 0 ) - { - const int branchLen = block->nHeight - forked->nHeight; - obj.push_back(Pair("branchlen", branchLen)); - - string status; - if (chainActive.Contains(block)) { - // This block is part of the currently active chain. - status = "active"; - } else if (block->nStatus & BLOCK_FAILED_MASK) { - // This block or one of its ancestors is invalid. - status = "invalid"; - } else if (block->nChainTx == 0) { - // This block cannot be connected because full block data for it or one of its parents is missing. - status = "headers-only"; - } else if (block->IsValid(BLOCK_VALID_SCRIPTS)) { - // This block is fully validated, but no longer part of the active chain. It was probably the active block once, but was reorganized. - status = "valid-fork"; - } else if (block->IsValid(BLOCK_VALID_TREE)) { - // The headers for this block are valid, but it has not been validated. It was probably never part of the most-work chain. - status = "valid-headers"; - } else { - // No clue. - status = "unknown"; - } - obj.push_back(Pair("status", status)); - } - res.push_back(obj); - } - - return res; -} - -UniValue mempoolInfoToJSON() -{ - UniValue ret(UniValue::VOBJ); - ret.push_back(Pair("size", (int64_t) mempool.size())); - ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize())); - ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage())); - - return ret; -} - -UniValue getmempoolinfo(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getmempoolinfo\n" - "\nReturns details on the active state of the TX memory pool.\n" - "\nResult:\n" - "{\n" - " \"size\": xxxxx (numeric) Current tx count\n" - " \"bytes\": xxxxx (numeric) Sum of all tx sizes\n" - " \"usage\": xxxxx (numeric) Total memory usage for the mempool\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("getmempoolinfo", "") - + HelpExampleRpc("getmempoolinfo", "") - ); - - return mempoolInfoToJSON(); -} - -UniValue invalidateblock(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "invalidateblock \"hash\"\n" - "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n" - "\nArguments:\n" - "1. hash (string, required) the hash of the block to mark as invalid\n" - "\nResult:\n" - "\nExamples:\n" - + HelpExampleCli("invalidateblock", "\"blockhash\"") - + HelpExampleRpc("invalidateblock", "\"blockhash\"") - ); - - std::string strHash = params[0].get_str(); - uint256 hash(uint256S(strHash)); - CValidationState state; - - { - LOCK(cs_main); - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlockIndex* pblockindex = mapBlockIndex[hash]; - InvalidateBlock(state, pblockindex); - } - - if (state.IsValid()) { - ActivateBestChain(state); - } - - if (!state.IsValid()) { - throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); - } - - return NullUniValue; -} - -UniValue reconsiderblock(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "reconsiderblock \"hash\"\n" - "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n" - "This can be used to undo the effects of invalidateblock.\n" - "\nArguments:\n" - "1. hash (string, required) the hash of the block to reconsider\n" - "\nResult:\n" - "\nExamples:\n" - + HelpExampleCli("reconsiderblock", "\"blockhash\"") - + HelpExampleRpc("reconsiderblock", "\"blockhash\"") - ); - - std::string strHash = params[0].get_str(); - uint256 hash(uint256S(strHash)); - CValidationState state; - - { - LOCK(cs_main); - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlockIndex* pblockindex = mapBlockIndex[hash]; - ReconsiderBlock(state, pblockindex); - } - - if (state.IsValid()) { - ActivateBestChain(state); - } - - if (!state.IsValid()) { - throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); - } - - return NullUniValue; -} diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 64d98d78376..22a5f98d800 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1204,6 +1204,17 @@ SigVersion SignatureHashVersion(const CTransaction& txTo) } } +/***** + * Generate a signature hash + * @param scriptCode the scriptPubKey + * @param txTo the transaction we are trying to create + * @param nIn the index of the vIn that has the data to sign + * @param nHashType the hash type (i.e. SIGHASH_ALL) + * @param amount the amount (for hidden txs) + * @param consensusBranchId the branch id + * @param cache additional data + * @returns the signature + */ uint256 SignatureHash( const CScript& scriptCode, const CTransaction& txTo, diff --git a/src/script/sign.cpp b/src/script/sign.cpp index e964609df7d..37276700f92 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -36,13 +36,6 @@ using namespace std; typedef vector valtype; extern uint8_t ASSETCHAINS_TXPOW; extern char NSPV_wifstr[],NSPV_pubkeystr[]; -extern int32_t KOMODO_NSPV; -#ifndef KOMODO_NSPV_FULLNODE -#define KOMODO_NSPV_FULLNODE (KOMODO_NSPV <= 0) -#endif // !KOMODO_NSPV_FULLNODE -#ifndef KOMODO_NSPV_SUPERLITE -#define KOMODO_NSPV_SUPERLITE (KOMODO_NSPV > 0) -#endif // !KOMODO_NSPV_SUPERLITE uint256 SIG_TXHASH; diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 4c57388adc9..2e547d9234b 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -204,7 +204,13 @@ static bool MatchMultisig(const CScript& script, unsigned int& required, std::ve return (it + 1 == script.end()); } - +/**** + * @brief interrogate a script + * @param[in] scriptPubKey what to examine + * @param[out] typeRet the type of transaction + * @param[out] vSolutionsRet results + * @returns true on success + */ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector >& vSolutionsRet) { vSolutionsRet.clear(); diff --git a/src/secp256k1/Makefile.am b/src/secp256k1/Makefile.am index c5fa00fc575..bf4d448bd03 100644 --- a/src/secp256k1/Makefile.am +++ b/src/secp256k1/Makefile.am @@ -153,10 +153,10 @@ CFLAGS_FOR_BUILD += -Wall -Wextra -Wno-unused-function gen_context_OBJECTS = gen_context.o gen_context_BIN = gen_context$(BUILD_EXEEXT) gen_%.o: src/gen_%.c - $(CC_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@ + $(AM_V_at)$(CC_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@ $(gen_context_BIN): $(gen_context_OBJECTS) - $(CC_FOR_BUILD) $^ -o $@ + $(AM_V_at)$(CC_FOR_BUILD) $^ -o $@ $(libsecp256k1_la_OBJECTS): src/ecmult_static_context.h $(tests_OBJECTS): src/ecmult_static_context.h diff --git a/src/secp256k1/src/ecmult_impl.h b/src/secp256k1/src/ecmult_impl.h index b761304cfd8..14a0622b260 100644 --- a/src/secp256k1/src/ecmult_impl.h +++ b/src/secp256k1/src/ecmult_impl.h @@ -1503,8 +1503,9 @@ static size_t secp256k1_pippenger_max_points(secp256k1_scratch *scratch) { secp256k1_gej tmpj; secp256k1_scalar_set_int(&szero, 0); - /* r = inp_g_sc*G */ secp256k1_gej_set_infinity(r); + secp256k1_gej_set_infinity(&tmpj); + /* r = inp_g_sc*G */ secp256k1_ecmult(ctx, r, &tmpj, &szero, inp_g_sc); for (point_idx = 0; point_idx < n_points; point_idx++) { secp256k1_ge point; diff --git a/src/sendalert.cpp b/src/sendalert.cpp index 6525cb3567d..dd21078fe16 100644 --- a/src/sendalert.cpp +++ b/src/sendalert.cpp @@ -53,7 +53,6 @@ the bad alert. */ -#include "main.h" #include "net.h" #include "alert.h" #include "init.h" diff --git a/src/snark/Makefile b/src/snark/Makefile index 3ef82ab878a..26fd3ec356c 100644 --- a/src/snark/Makefile +++ b/src/snark/Makefile @@ -195,7 +195,7 @@ $(DEPINST_EXISTS): -include $(patsubst %.o,%.d, $(LIB_OBJS) $(GTEST_OBJS) $(EXEC_OBJS) ) $(LIB_OBJS) $(if $(NO_GTEST),,$(GTEST_OBJS)) $(EXEC_OBJS): %.o: %.cpp - $(CXX) -o $@ $< -c -MMD $(CXXFLAGS) + @$(CXX) -o $@ $< -c -MMD $(CXXFLAGS) LIBGTEST_A = $(DEPINST)/lib/libgtest.a @@ -205,12 +205,12 @@ $(LIBGTEST_A): $(GTESTDIR)/libsnark/gtest-all.cc $(DEPINST_EXISTS) # libsnark.a will contains all of our relevant object files, and we also mash in the .a files of relevant dependencies built by ./prepare-depends.sh $(LIBSNARK_A): $(LIB_OBJS) $(AR_LIBS) - $(AR) q $(LIBSNARK_A) $(LIB_OBJS) - if [ -n "$(AR_LIBS)" ]; then mkdir -p tmp-ar; cd tmp-ar; for AR_LIB in $(AR_LIBS); do $(AR) x $$AR_LIB; done; $(AR) qc $(LIBSNARK_A) tmp-ar/*; cd ..; rm -r tmp-ar; fi; - $(AR) s $(LIBSNARK_A) + @$(AR) q $(LIBSNARK_A) $(LIB_OBJS) + @if [ -n "$(AR_LIBS)" ]; then mkdir -p tmp-ar; cd tmp-ar; for AR_LIB in $(AR_LIBS); do $(AR) x $$AR_LIB; done; $(AR) qc $(LIBSNARK_A) tmp-ar/*; cd ..; rm -r tmp-ar; fi; + @$(AR) s $(LIBSNARK_A) libsnark.so: $(LIBSNARK_A) $(DEPINST_EXISTS) - $(CXX) -o $@ --shared -Wl,--whole-archive $(LIBSNARK_A) $(CXXFLAGS) $(LDFLAGS) -Wl,--no-whole-archive $(LDLIBS) + @$(CXX) -o $@ --shared -Wl,--whole-archive $(LIBSNARK_A) $(CXXFLAGS) $(LDFLAGS) -Wl,--no-whole-archive $(LDLIBS) libsnark/gadgetlib2/tests/gadgetlib2_test: \ libsnark/gadgetlib2/tests/adapters_UTEST.cpp \ diff --git a/src/sync.cpp b/src/sync.cpp index 31c3301bd25..01d5946a9bb 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -181,7 +181,13 @@ std::string LocksHeld() void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) { - BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, *lockstack) + if ( lockstack.get() == nullptr) + { + fprintf(stderr, "Assertion failed: Thread does not have a lockstack. Method: %s in file %s Line %d\n", + pszName, pszFile, nLine); + abort(); + } + for (const auto &i : *lockstack) if (i.first == cs) return; fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str()); diff --git a/src/sync.h b/src/sync.h index a8f29eb6613..922f48b1d5d 100644 --- a/src/sync.h +++ b/src/sync.h @@ -68,20 +68,20 @@ LEAVE_CRITICAL_SECTION(mutex); // no RAII * annotations to a subset of the mutex API. */ template -class LOCKABLE AnnotatedMixin : public PARENT +class CAPABILITY("mutex") AnnotatedMixin : public PARENT { public: - void lock() EXCLUSIVE_LOCK_FUNCTION() + void lock() ACQUIRE() { PARENT::lock(); } - void unlock() UNLOCK_FUNCTION() + void unlock() RELEASE() { PARENT::unlock(); } - bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true) + bool try_lock() TRY_ACQUIRE(true) { return PARENT::try_lock(); } @@ -117,7 +117,7 @@ void PrintLockContention(const char* pszName, const char* pszFile, int nLine); /** Wrapper around boost::unique_lock */ template -class SCOPED_LOCKABLE CMutexLock +class SCOPED_CAPABILITY CMutexLock { private: boost::unique_lock lock; @@ -145,7 +145,7 @@ class SCOPED_LOCKABLE CMutexLock } public: - CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : lock(mutexIn, boost::defer_lock) + CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) ACQUIRE(mutexIn) : lock(mutexIn, boost::defer_lock) { if (fTry) TryEnter(pszName, pszFile, nLine); @@ -153,7 +153,7 @@ class SCOPED_LOCKABLE CMutexLock Enter(pszName, pszFile, nLine); } - CMutexLock(Mutex* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn) + CMutexLock(Mutex* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) ACQUIRE(pmutexIn) { if (!pmutexIn) return; @@ -164,7 +164,7 @@ class SCOPED_LOCKABLE CMutexLock Enter(pszName, pszFile, nLine); } - ~CMutexLock() UNLOCK_FUNCTION() + ~CMutexLock() RELEASE() { if (lock.owns_lock()) LeaveCritical(); diff --git a/src/test-komodo/komodo-test-res.rc b/src/test-komodo/komodo-test-res.rc new file mode 100644 index 00000000000..132612416be --- /dev/null +++ b/src/test-komodo/komodo-test-res.rc @@ -0,0 +1,35 @@ +#include // needed for VERSIONINFO +#include "../clientversion.h" // holds the needed client version information + +#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD +#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD) +#define VER_FILEVERSION VER_PRODUCTVERSION +#define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VER_FILEVERSION +PRODUCTVERSION VER_PRODUCTVERSION +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_APP +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" // U.S. English - multilingual (hex) + BEGIN + VALUE "CompanyName", "Komodo" + VALUE "FileDescription", "komodo-test (Komodo features test utility)" + VALUE "FileVersion", VER_FILEVERSION_STR + VALUE "InternalName", "komodo-test" + VALUE "LegalCopyright", COPYRIGHT_STR + VALUE "LegalTrademarks1", "Distributed under the MIT software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php." + VALUE "OriginalFilename", "komodo-test.exe" + VALUE "ProductName", "komodo-test" + VALUE "ProductVersion", VER_PRODUCTVERSION_STR + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1252 // language neutral - multilingual (decimal) + END +END diff --git a/src/test-komodo/main.cpp b/src/test-komodo/main.cpp index 1adb729b4a2..73119e3cb66 100644 --- a/src/test-komodo/main.cpp +++ b/src/test-komodo/main.cpp @@ -10,7 +10,9 @@ int main(int argc, char **argv) { assert(init_and_check_sodium() != -1); ECC_Start(); ECCVerifyHandle handle; // Inits secp256k1 verify context + SetupNetworking(); SelectParams(CBaseChainParams::REGTEST); + chainName = assetchain(); // KMD by default CBitcoinSecret vchSecret; // this returns false due to network prefix mismatch but works anyway @@ -18,5 +20,7 @@ int main(int argc, char **argv) { notaryKey = vchSecret.GetKey(); testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); + auto retval = RUN_ALL_TESTS(); + ECC_Stop(); + return retval; } diff --git a/src/test-komodo/test_alerts.cpp b/src/test-komodo/test_alerts.cpp new file mode 100644 index 00000000000..a1f9cbe50fe --- /dev/null +++ b/src/test-komodo/test_alerts.cpp @@ -0,0 +1,427 @@ +// Copyright (c) 2013 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +// +// Unit tests for alert system +// + +#include "alert.h" +#include "chain.h" +#include "chainparams.h" +#include "clientversion.h" + +#include "main.h" +#include "rpc/protocol.h" +#include "rpc/server.h" +#include "serialize.h" +#include "streams.h" +#include "util.h" +#include "utilstrencodings.h" + +#include "test/test_bitcoin.h" + +#include + +#include +#include +#include + +#include "key.h" +#include +#include // for ::remove +#include + +namespace TestAlerts +{ + +// macro to assist with log messages +#define GTEST_COUT std::cerr << "[ ] [ INFO ] " + +// Code to output a C-style array of values +template +std::string HexStrArray(const T itbegin, const T itend, int lineLength) +{ + std::string rv; + static const char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + rv.reserve((itend-itbegin)*3); + int i = 0; + for(T it = itbegin; it < itend; ++it) + { + unsigned char val = (unsigned char)(*it); + if(it != itbegin) + { + if (i % lineLength == 0) + rv.push_back('\n'); + else + rv.push_back(' '); + } + rv.push_back('0'); + rv.push_back('x'); + rv.push_back(hexmap[val>>4]); + rv.push_back(hexmap[val&15]); + rv.push_back(','); + i++; + } + + return rv; +} + +template +inline std::string HexStrArray(const T& vch, int lineLength) +{ + return HexStrArray(vch.begin(), vch.end(), lineLength); +} + +// Stuff used by several tests, and set up by TestAlerts::SetupTestCase() +boost::filesystem::path alertnotify_file; +CKey key; +CPubKey pubKey; +std::vector alerts; +boost::filesystem::path temp_directory = boost::filesystem::temp_directory_path(); +boost::filesystem::path binary_file; + +class TestAlerts : public ::testing::Test +{ +public: + TestAlerts() + { + } + ~TestAlerts() + { + } + static void SetUpTestCase() + { + // generate a key that will sign alerts + key.MakeNewKey(false); + pubKey = key.GetPubKey(); + // a place to store the binary file + binary_file = temp_directory / "testAlerts.raw"; + // generate the alerts + GenerateAlertTests(); + // Now read it into the alerts collection + ReadAlerts(binary_file); + alertnotify_file = GetTempPath() / + boost::filesystem::unique_path("alertnotify-%%%%.txt"); + mapArgs["-alertnotify"] = std::string("echo %s >> ") + alertnotify_file.string(); + } + static void TearDownTestCase() + { + if (!boost::filesystem::remove( alertnotify_file) ) + GTEST_COUT << "Boost says it was unable to remove file " << alertnotify_file.string() + << std::endl; + if (!boost::filesystem::remove(binary_file)) + GTEST_COUT << "Unable to remove file " << binary_file.string() << std::endl; + } + + virtual void SetUp() {} + + virtual void TearDown() {} + + /****** + * @brief reads the alerts that were generated by GenerateAlertTests + */ + static std::vector ReadLines(boost::filesystem::path filepath) + { + std::vector result; + + std::ifstream f(filepath.string().c_str()); + std::string line; + while (std::getline(f,line)) + result.push_back(line); + f.close(); + return result; + } + + static bool ReadAlerts(boost::filesystem::path infile) + { + // read the file into a vector + std::ifstream filestream(binary_file.string().c_str(), std::ios::in | std::ios::binary); + std::vector vch( (std::istreambuf_iterator(filestream)), std::istreambuf_iterator()); + + CDataStream stream(vch, SER_DISK, CLIENT_VERSION); + try { + while (!stream.eof()) + { + CAlert alert; + stream >> alert; + alerts.push_back(alert); + } + } + catch (const std::exception&) { return false; } + return true; + } + + static void GenerateAlertTests() + { + CDataStream sBuffer(SER_DISK, CLIENT_VERSION); + + CAlert alert; + alert.nRelayUntil = 60; + alert.nExpiration = 24 * 60 * 60; + alert.nID = 1; + alert.nCancel = 0; // cancels previous messages up to this ID number + alert.nMinVer = 0; // These versions are protocol versions + alert.nMaxVer = 999001; + alert.nPriority = 1; + alert.strComment = "Alert comment"; + alert.strStatusBar = "Alert 1"; + + // Replace SignAndSave with SignAndSerialize + SignAndSerialize(alert, sBuffer); + + // More tests go here ... + alert.setSubVer.insert(std::string("/MagicBean:0.1.0/")); + alert.strStatusBar = "Alert 1 for MagicBean 0.1.0"; + SignAndSerialize(alert, sBuffer); + + alert.setSubVer.insert(std::string("/MagicBean:0.2.0/")); + alert.strStatusBar = "Alert 1 for MagicBean 0.1.0, 0.2.0"; + SignAndSerialize(alert, sBuffer); + + alert.setSubVer.clear(); + ++alert.nID; + alert.nCancel = 1; + alert.nPriority = 100; + alert.strStatusBar = "Alert 2, cancels 1"; + SignAndSerialize(alert, sBuffer); + + alert.nExpiration += 60; + ++alert.nID; + SignAndSerialize(alert, sBuffer); + + ++alert.nID; + alert.nPriority = 5000; + alert.strStatusBar = "Alert 3, disables RPC"; + alert.strRPCError = "RPC disabled"; + SignAndSerialize(alert, sBuffer); + + ++alert.nID; + alert.nPriority = 5000; + alert.strStatusBar = "Alert 4, re-enables RPC"; + alert.strRPCError = ""; + SignAndSerialize(alert, sBuffer); + + ++alert.nID; + alert.nMinVer = 11; + alert.nMaxVer = 22; + alert.nPriority = 100; + SignAndSerialize(alert, sBuffer); + + ++alert.nID; + alert.strStatusBar = "Alert 2 for MagicBean 0.1.0"; + alert.setSubVer.insert(std::string("/MagicBean:0.1.0/")); + SignAndSerialize(alert, sBuffer); + + ++alert.nID; + alert.nMinVer = 0; + alert.nMaxVer = 999999; + alert.strStatusBar = "Evil Alert'; /bin/ls; echo '"; + alert.setSubVer.clear(); + bool b = SignAndSerialize(alert, sBuffer); + + if (b) { + // write alerts to a file + std::vector vch = std::vector(sBuffer.begin(), sBuffer.end()); + std::ofstream outfile(binary_file.string().c_str(), std::ios::out | std::ios::binary); + outfile.write((const char*)&vch[0], vch.size()); + outfile.close(); + } + } + + // Sign CAlert with alert private key + static bool SignAlert(CAlert &alert) + { + // serialize alert data + CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION); + sMsg << *(CUnsignedAlert*)&alert; + alert.vchMsg = std::vector(sMsg.begin(), sMsg.end()); + + // sign alert + if (!key.Sign(Hash(alert.vchMsg.begin(), alert.vchMsg.end()), alert.vchSig)) + { + printf("SignAlert() : key.Sign failed\n"); + return false; + } + return true; + } + + // Sign a CAlert and serialize it + static bool SignAndSerialize(CAlert &alert, CDataStream &buffer) + { + // Sign + if(!SignAlert(alert)) + { + printf("SignAndSerialize() : could not sign alert\n"); + return false; + } + // ...and save! + buffer << alert; + return true; + } +}; + +TEST_F(TestAlerts, AlertApplies) +{ + SetMockTime(11); + std::vector alertKey{pubKey.begin(), pubKey.end()}; + + for(const CAlert& alert : alerts) + { + EXPECT_TRUE(alert.CheckSignature(alertKey)); + } + + EXPECT_GE(alerts.size(), 3); + + // Matches: + EXPECT_TRUE(alerts[0].AppliesTo(1, "")); + EXPECT_TRUE(alerts[0].AppliesTo(999001, "")); + EXPECT_TRUE(alerts[0].AppliesTo(1, "/MagicBean:11.11.11/")); + + EXPECT_TRUE(alerts[1].AppliesTo(1, "/MagicBean:0.1.0/")); + EXPECT_TRUE(alerts[1].AppliesTo(999001, "/MagicBean:0.1.0/")); + + EXPECT_TRUE(alerts[2].AppliesTo(1, "/MagicBean:0.1.0/")); + EXPECT_TRUE(alerts[2].AppliesTo(1, "/MagicBean:0.2.0/")); + + // Don't match: + EXPECT_TRUE(!alerts[0].AppliesTo(-1, "")); + EXPECT_TRUE(!alerts[0].AppliesTo(999002, "")); + + EXPECT_TRUE(!alerts[1].AppliesTo(1, "")); + EXPECT_TRUE(!alerts[1].AppliesTo(1, "MagicBean:0.1.0")); + EXPECT_TRUE(!alerts[1].AppliesTo(1, "/MagicBean:0.1.0")); + EXPECT_TRUE(!alerts[1].AppliesTo(1, "MagicBean:0.1.0/")); + EXPECT_TRUE(!alerts[1].AppliesTo(-1, "/MagicBean:0.1.0/")); + EXPECT_TRUE(!alerts[1].AppliesTo(999002, "/MagicBean:0.1.0/")); + EXPECT_TRUE(!alerts[1].AppliesTo(1, "/MagicBean:0.2.0/")); + + EXPECT_TRUE(!alerts[2].AppliesTo(1, "/MagicBean:0.3.0/")); + + SetMockTime(0); +} + + +TEST_F(TestAlerts, AlertNotify) +{ + SetMockTime(11); + const std::vector& alertKey{pubKey.begin(), pubKey.end()}; + + for(CAlert alert : alerts) + alert.ProcessAlert(alertKey, false); + + std::vector r = ReadLines( alertnotify_file); + EXPECT_EQ(r.size(), 6u); + +// Windows built-in echo semantics are different than posixy shells. Quotes and +// whitespace are printed literally. + +#ifndef WIN32 + EXPECT_EQ(r[0], "Alert 1"); + EXPECT_EQ(r[1], "Alert 2, cancels 1"); + EXPECT_EQ(r[2], "Alert 2, cancels 1"); + EXPECT_EQ(r[3], "Alert 3, disables RPC"); + EXPECT_EQ(r[4], "Alert 4, reenables RPC"); // dashes should be removed + EXPECT_EQ(r[5], "Evil Alert; /bin/ls; echo "); // single-quotes should be removed +#else + EXPECT_EQ(r[0], "'Alert 1' "); + EXPECT_EQ(r[1], "'Alert 2, cancels 1' "); + EXPECT_EQ(r[2], "'Alert 2, cancels 1' "); + EXPECT_EQ(r[3], "'Alert 3, disables RPC' "); + EXPECT_EQ(r[4], "'Alert 4, reenables RPC' "); // dashes should be removed + EXPECT_EQ(r[5], "'Evil Alert; /bin/ls; echo ' "); +#endif + + SetMockTime(0); + mapAlerts.clear(); +} + +TEST_F(TestAlerts, AlertDisablesRPC) +{ + SetMockTime(11); + const std::vector& alertKey{pubKey.begin(), pubKey.end()}; + + // Command should work before alerts + EXPECT_EQ(GetWarnings("rpc"), ""); + + // First alert should disable RPC + alerts[5].ProcessAlert(alertKey, false); + EXPECT_EQ(alerts[5].strRPCError, "RPC disabled"); + EXPECT_EQ(GetWarnings("rpc"), "RPC disabled"); + + // Second alert should re-enable RPC + alerts[6].ProcessAlert(alertKey, false); + EXPECT_EQ(alerts[6].strRPCError, ""); + EXPECT_EQ(GetWarnings("rpc"), ""); + + SetMockTime(0); + mapAlerts.clear(); +} + +static bool falseFunc() { return false; } + +TEST_F(TestAlerts, PartitionAlert) +{ + // Test PartitionCheck + CCriticalSection csDummy; + CChainParams& params = Params(CBaseChainParams::MAIN); + int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing; // for komodo mainnet, currently 60 + int64_t normalBlocksPerDay = 86400 / nPowTargetSpacing; + CBlockIndex indexDummy[86400 / 60]; // hard coded to avoid compiler warnings about variable length buffer + + // Generate fake blockchain timestamps relative to + // an arbitrary time: + int64_t now = 1427379054; + SetMockTime(now); + for (int i = 0; i < normalBlocksPerDay; i++) + { + indexDummy[i].phashBlock = nullptr; + if (i == 0) + indexDummy[i].pprev = nullptr; + else + indexDummy[i].pprev = &indexDummy[i-1]; + indexDummy[i].nHeight = i; + indexDummy[i].nTime = now - (normalBlocksPerDay-i)*nPowTargetSpacing; + // Other members don't matter, the partition check code doesn't + // use them + } + + // Test 1: chain with blocks every nPowTargetSpacing seconds, + // as normal, no worries: + PartitionCheck(falseFunc, csDummy, &indexDummy[normalBlocksPerDay - 1], nPowTargetSpacing); + EXPECT_TRUE(strMiscWarning.empty()); + + // Test 2: go 3.5 hours without a block, expect a warning: + now += 3*60*60+30*60; + SetMockTime(now); + PartitionCheck(falseFunc, csDummy, &indexDummy[normalBlocksPerDay - 1], nPowTargetSpacing); + EXPECT_TRUE(!strMiscWarning.empty()); + GTEST_COUT << "Got alert text: " << strMiscWarning << std::endl; + strMiscWarning = ""; + + // Test 3: test the "partition alerts only go off once per day" + // code: + now += 60*10; + SetMockTime(now); + PartitionCheck(falseFunc, csDummy, &indexDummy[normalBlocksPerDay - 1], nPowTargetSpacing); + EXPECT_TRUE(strMiscWarning.empty()); + + // Test 4: get 2.5 times as many blocks as expected: + now += 60*60*24; // Pretend it is a day later + SetMockTime(now); + int64_t quickSpacing = nPowTargetSpacing*2/5; + for (int i = 0; i < normalBlocksPerDay; i++) // Tweak chain timestamps: + indexDummy[i].nTime = now - (normalBlocksPerDay-i)*quickSpacing; + PartitionCheck(falseFunc, csDummy, &indexDummy[normalBlocksPerDay - 1], nPowTargetSpacing); + EXPECT_TRUE(!strMiscWarning.empty()); + GTEST_COUT << "Got alert text: " << strMiscWarning << std::endl; + strMiscWarning = ""; + + SetMockTime(0); + // PartitionCheck adds records to the alertnotify file asynchronously. + // To remove the file, we need to wait briefly for it to be closed. + std::this_thread::sleep_for(std::chrono::milliseconds(100)); +} + +} // namespace TestAlerts diff --git a/src/test-komodo/test_block.cpp b/src/test-komodo/test_block.cpp new file mode 100644 index 00000000000..1098a231800 --- /dev/null +++ b/src/test-komodo/test_block.cpp @@ -0,0 +1,239 @@ +#include "primitives/block.h" +#include "testutils.h" +#include "komodo_extern_globals.h" +#include "consensus/validation.h" +#include "coincontrol.h" +#include "miner.h" + +#include +#include + + +TEST(test_block, header_size_is_expected) { + // Header with an empty Equihash solution. + CBlockHeader header; + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << header; + + auto stream_size = CBlockHeader::HEADER_SIZE + 1; + // ss.size is +1 due to data stream header of 1 byte + EXPECT_EQ(ss.size(), stream_size); +} + +TEST(test_block, TestStopAt) +{ + TestChain chain; + auto notary = std::make_shared(chain.getNotaryKey(), "notary"); + std::shared_ptr lastBlock = chain.generateBlock(notary); // genesis block + ASSERT_GT( chain.GetIndex()->nHeight, 0 ); + lastBlock = chain.generateBlock(notary); // now we should be above 1 + ASSERT_GT( chain.GetIndex()->nHeight, 1); + CBlock block; + CValidationState state; + KOMODO_STOPAT = 1; + EXPECT_FALSE( chain.ConnectBlock(block, state, chain.GetIndex(), false, true) ); + KOMODO_STOPAT = 0; // to not stop other tests +} + +TEST(test_block, TestConnectWithoutChecks) +{ + TestChain chain; + auto notary = std::make_shared(chain.getNotaryKey(), "notary"); + auto alice = std::make_shared("alice"); + std::shared_ptr lastBlock = chain.generateBlock(notary); // genesis block + ASSERT_GT( chain.GetIndex()->nHeight, 0 ); + // Add some transaction to a block + int32_t newHeight = chain.GetIndex()->nHeight + 1; + TransactionInProcess fundAlice = notary->CreateSpendTransaction(alice, 100000); + // construct the block + CBlock block; + // first a coinbase tx + auto consensusParams = Params().GetConsensus(); + CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, newHeight); + txNew.vin.resize(1); + txNew.vin[0].prevout.SetNull(); + txNew.vin[0].scriptSig = (CScript() << newHeight << CScriptNum(1)) + COINBASE_FLAGS; + txNew.vout.resize(1); + txNew.vout[0].nValue = GetBlockSubsidy(newHeight,consensusParams); + txNew.nExpiryHeight = 0; + block.vtx.push_back(CTransaction(txNew)); + // then the actual tx + block.vtx.push_back(fundAlice.transaction); + CValidationState state; + // create a new CBlockIndex to forward to ConnectBlock + auto index = chain.GetIndex(); + CBlockIndex newIndex; + newIndex.pprev = index; + EXPECT_TRUE( chain.ConnectBlock(block, state, &newIndex, true, false) ); + if (!state.IsValid() ) + FAIL() << state.GetRejectReason(); +} + +TEST(test_block, TestSpendInSameBlock) +{ + //setConsoleDebugging(true); + TestChain chain; + chainName = assetchain("TST"); // use not KMD to ensure komodo_hardfork_active() is true for tx nLockTime to be handled: both tx nLocktime and nBlockTime are set to the MTP + auto notary = std::make_shared(chain.getNotaryKey(), "notary"); + notary->SetBroadcastTransactions(true); + auto alice = std::make_shared("alice"); + alice->SetBroadcastTransactions(true); + auto bob = std::make_shared("bob"); + auto miner = std::make_shared("miner"); + std::shared_ptr lastBlock = chain.generateBlock(notary); // genesis block + ASSERT_GT( chain.GetIndex()->nHeight, 0 ); + CAmount notaryBalance = notary->GetBalance(); + // delay just a second to help with locktime + std::this_thread::sleep_for(std::chrono::seconds(1)); + // Start to build a block + int32_t newHeight = chain.GetIndex()->nHeight + 1; + TransactionInProcess fundAlice = notary->CreateSpendTransaction(alice, 100000, 5000, true); + notaryBalance -= 105000; // transfer + fee + // now have Alice move some funds to Bob in the same block + CCoinControl useThisTransaction; + COutPoint tx(fundAlice.transaction.GetHash(), 1); + useThisTransaction.Select(tx); + TransactionInProcess aliceToBob = alice->CreateSpendTransaction(bob, 50000, 5000, useThisTransaction); + EXPECT_TRUE( alice->CommitTransaction(aliceToBob.transaction, aliceToBob.reserveKey) ); + // std::this_thread::sleep_for(std::chrono::seconds(1)); + // see if everything worked + lastBlock = chain.generateBlock(miner); + EXPECT_TRUE( lastBlock != nullptr); + // balances should be correct + EXPECT_EQ( bob->GetBalance() + bob->GetUnconfirmedBalance() + bob->GetImmatureBalance(), CAmount(50000)); + EXPECT_EQ( notary->GetBalance(), notaryBalance); + EXPECT_EQ( alice->GetBalance() + alice->GetUnconfirmedBalance() + alice->GetImmatureBalance(), CAmount(45000)); +} + +// Note: long delays during this test occur in reservekey.GetReservedKey(vchPubKey) call +TEST(test_block, TestDoubleSpendInSameBlock) +{ + TestChain chain; + auto notary = std::make_shared(chain.getNotaryKey(), "notary"); + notary->SetBroadcastTransactions(true); + auto alice = std::make_shared("alice"); + alice->SetBroadcastTransactions(true); + auto bob = std::make_shared("bob"); + auto charlie = std::make_shared("charlie"); + std::shared_ptr lastBlock = chain.generateBlock(notary); // genesis block + CAmount notaryBalance = notary->GetBalance(); + ASSERT_GT( chain.GetIndex()->nHeight, 0 ); + // Start to build a block + int32_t newHeight = chain.GetIndex()->nHeight + 1; + TransactionInProcess fundAlice = notary->CreateSpendTransaction(alice, 100000, 5000, true); + EXPECT_EQ(mempool.size(), 1); + // now have Alice move some funds to Bob in the same block + { + CCoinControl useThisTransaction; + COutPoint tx(fundAlice.transaction.GetHash(), 1); + useThisTransaction.Select(tx); + TransactionInProcess aliceToBob = alice->CreateSpendTransaction(bob, 10000, 5000, useThisTransaction); + EXPECT_TRUE(alice->CommitTransaction(aliceToBob.transaction, aliceToBob.reserveKey)); + } + // alice attempts to double spend the vout and send something to charlie + { + CCoinControl useThisTransaction; + COutPoint tx(fundAlice.transaction.GetHash(), 1); + useThisTransaction.Select(tx); + TransactionInProcess aliceToCharlie = alice->CreateSpendTransaction(charlie, 10000, 5000, useThisTransaction); + CValidationState state; + EXPECT_FALSE(alice->CommitTransaction(aliceToCharlie.transaction, aliceToCharlie.reserveKey, state)); + EXPECT_EQ(state.GetRejectReason(), "mempool conflict"); + } + /* + EXPECT_EQ(mempool.size(), 3); + CValidationState validationState; + std::shared_ptr block = chain.generateBlock(notary, &validationState); + EXPECT_EQ( block, nullptr ); + EXPECT_EQ( validationState.GetRejectReason(), "bad-txns-inputs-missingorspent"); + */ +} + +bool CalcPoW(CBlock *pblock); + +TEST(test_block, TestProcessBlock) +{ + TestChain chain; + EXPECT_EQ(chain.GetIndex()->nHeight, 0); + auto notary = std::make_shared(chain.getNotaryKey(), "notary"); + auto alice = std::make_shared("alice"); + auto bob = std::make_shared("bob"); + auto charlie = std::make_shared("charlie"); + std::shared_ptr lastBlock = chain.generateBlock(notary); // gives notary everything + EXPECT_EQ(chain.GetIndex()->nHeight, 1); + chain.IncrementChainTime(); + // add a transaction to the mempool + TransactionInProcess fundAlice = notary->CreateSpendTransaction(alice, 100000); + EXPECT_TRUE( chain.acceptTx(fundAlice.transaction).IsValid() ); + // construct the block + CBlock block; + int32_t newHeight = chain.GetIndex()->nHeight + 1; + CValidationState state; + // no transactions + EXPECT_FALSE( ProcessNewBlock(false, newHeight, state, nullptr, &block, false, nullptr) ); + EXPECT_EQ(state.GetRejectReason(), "bad-blk-length"); + EXPECT_EQ(chain.GetIndex()->nHeight, 1); + // add first a coinbase tx + auto consensusParams = Params().GetConsensus(); + CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, newHeight); + txNew.vin.resize(1); + txNew.vin[0].prevout.SetNull(); + txNew.vin[0].scriptSig = (CScript() << newHeight << CScriptNum(1)) + COINBASE_FLAGS; + txNew.vout.resize(1); + txNew.vout[0].nValue = GetBlockSubsidy(newHeight,consensusParams); + txNew.nExpiryHeight = 0; + block.vtx.push_back(CTransaction(txNew)); + // no PoW, no merkle root should fail on merkle error + EXPECT_FALSE( ProcessNewBlock(false, newHeight, state, nullptr, &block, false, nullptr) ); + EXPECT_EQ(state.GetRejectReason(), "bad-txnmrklroot"); + // Verify transaction is still in mempool + EXPECT_EQ(mempool.size(), 1); + // finish constructing the block + block.nBits = GetNextWorkRequired( chain.GetIndex(), &block, Params().GetConsensus()); + block.nTime = GetTime(); + block.hashPrevBlock = lastBlock->GetHash(); + block.hashMerkleRoot = block.BuildMerkleTree(); + // Add the PoW + EXPECT_TRUE(CalcPoW(&block)); + state = CValidationState(); + EXPECT_TRUE( ProcessNewBlock(false, newHeight, state, nullptr, &block, false, nullptr) ); + if (!state.IsValid()) + FAIL() << state.GetRejectReason(); + // Verify transaction is still in mempool + EXPECT_EQ(mempool.size(), 1); +} + +TEST(test_block, TestProcessBadBlock) +{ + TestChain chain; + auto notary = std::make_shared(chain.getNotaryKey(), "notary"); + auto alice = std::make_shared("alice"); + auto bob = std::make_shared("bob"); + auto charlie = std::make_shared("charlie"); + std::shared_ptr lastBlock = chain.generateBlock(notary); // genesis block + // add a transaction to the mempool + TransactionInProcess fundAlice = notary->CreateSpendTransaction(alice, 100000); + EXPECT_TRUE( chain.acceptTx(fundAlice.transaction).IsValid() ); + // construct the block + CBlock block; + int32_t newHeight = chain.GetIndex()->nHeight + 1; + CValidationState state; + // no transactions + EXPECT_FALSE( ProcessNewBlock(false, newHeight, state, nullptr, &block, false, nullptr) ); + EXPECT_EQ(state.GetRejectReason(), "bad-blk-length"); + // add first a coinbase tx + auto consensusParams = Params().GetConsensus(); + CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, newHeight); + txNew.vin.resize(1); + txNew.vin[0].prevout.SetNull(); + txNew.vin[0].scriptSig = (CScript() << newHeight << CScriptNum(1)) + COINBASE_FLAGS; + txNew.vout.resize(1); + txNew.vout[0].nValue = GetBlockSubsidy(newHeight,consensusParams); + txNew.nExpiryHeight = 0; + block.vtx.push_back(CTransaction(txNew)); + // Add no PoW, should fail on merkle error + EXPECT_FALSE( ProcessNewBlock(false, newHeight, state, nullptr, &block, false, nullptr) ); + EXPECT_EQ(state.GetRejectReason(), "bad-txnmrklroot"); + // Verify transaction is still in mempool + EXPECT_EQ(mempool.size(), 1); +} \ No newline at end of file diff --git a/src/test-komodo/test_coinimport.cpp b/src/test-komodo/test_coinimport.cpp index 05c709eb309..717c517406c 100644 --- a/src/test-komodo/test_coinimport.cpp +++ b/src/test-komodo/test_coinimport.cpp @@ -19,6 +19,8 @@ extern Eval* EVAL_TEST; +std::shared_ptr testChain; + namespace TestCoinImport { @@ -54,7 +56,9 @@ class TestCoinImport : public ::testing::Test, public Eval { protected: - static void SetUpTestCase() { setupChain(); } + static void SetUpTestCase() { testChain = std::make_shared(); } + static void TearDownTestCase() { testChain = nullptr; }; + virtual void SetUp() { ASSETCHAINS_CC = 1; EVAL_TEST = this; diff --git a/src/test/coins_tests.cpp b/src/test-komodo/test_coins.cpp similarity index 79% rename from src/test/coins_tests.cpp rename to src/test-komodo/test_coins.cpp index dc795ad7a7b..3c74de8488e 100644 --- a/src/test/coins_tests.cpp +++ b/src/test-komodo/test_coins.cpp @@ -17,11 +17,12 @@ #include #include -#include +#include #include "zcash/IncrementalMerkleTree.hpp" -namespace +namespace TestCoins { + class CCoinsViewTest : public CCoinsView { uint256 hashBestBlock_; @@ -208,7 +209,7 @@ class CCoinsViewCacheTest : public CCoinsViewCache for (CCoinsMap::iterator it = cacheCoins.begin(); it != cacheCoins.end(); it++) { ret += it->second.coins.DynamicMemoryUsage(); } - BOOST_CHECK_EQUAL(DynamicMemoryUsage(), ret); + EXPECT_EQ(DynamicMemoryUsage(), ret); } }; @@ -238,7 +239,6 @@ class TxWithNullifiers } }; -} uint256 appendRandomSproutCommitment(SproutMerkleTree &tree) { @@ -256,20 +256,20 @@ template bool GetAnchorAt(const CCoinsViewCacheTest &cache, const template<> bool GetAnchorAt(const CCoinsViewCacheTest &cache, const uint256 &rt, SproutMerkleTree &tree) { return cache.GetSproutAnchorAt(rt, tree); } template<> bool GetAnchorAt(const CCoinsViewCacheTest &cache, const uint256 &rt, SaplingMerkleTree &tree) { return cache.GetSaplingAnchorAt(rt, tree); } -BOOST_FIXTURE_TEST_SUITE(coins_tests, BasicTestingSetup) -void checkNullifierCache(const CCoinsViewCacheTest &cache, const TxWithNullifiers &txWithNullifiers, bool shouldBeInCache) { +void checkNullifierCache(const CCoinsViewCacheTest &cache, const TxWithNullifiers &txWithNullifiers, bool shouldBeInCache) +{ // Make sure the nullifiers have not gotten mixed up - BOOST_CHECK(!cache.GetNullifier(txWithNullifiers.sproutNullifier, SAPLING)); - BOOST_CHECK(!cache.GetNullifier(txWithNullifiers.saplingNullifier, SPROUT)); + EXPECT_TRUE(!cache.GetNullifier(txWithNullifiers.sproutNullifier, SAPLING)); + EXPECT_TRUE(!cache.GetNullifier(txWithNullifiers.saplingNullifier, SPROUT)); // Check if the nullifiers either are or are not in the cache bool containsSproutNullifier = cache.GetNullifier(txWithNullifiers.sproutNullifier, SPROUT); bool containsSaplingNullifier = cache.GetNullifier(txWithNullifiers.saplingNullifier, SAPLING); - BOOST_CHECK(containsSproutNullifier == shouldBeInCache); - BOOST_CHECK(containsSaplingNullifier == shouldBeInCache); + EXPECT_TRUE(containsSproutNullifier == shouldBeInCache); + EXPECT_TRUE(containsSaplingNullifier == shouldBeInCache); } -BOOST_AUTO_TEST_CASE(nullifier_regression_test) +TEST(TestCoins, nullifier_regression_test) { // Correct behavior: { @@ -357,7 +357,8 @@ BOOST_AUTO_TEST_CASE(nullifier_regression_test) } } -template void anchorPopRegressionTestImpl(ShieldedType type) +template +void anchorPopRegressionTestImpl(ShieldedType type) { // Correct behavior: { @@ -383,8 +384,8 @@ template void anchorPopRegressionTestImpl(ShieldedType type) // The base contains the anchor, of course! { Tree checkTree; - BOOST_CHECK(GetAnchorAt(cache1, tree.root(), checkTree)); - BOOST_CHECK(checkTree.root() == tree.root()); + EXPECT_TRUE(GetAnchorAt(cache1, tree.root(), checkTree)); + EXPECT_TRUE(checkTree.root() == tree.root()); } } @@ -415,8 +416,8 @@ template void anchorPopRegressionTestImpl(ShieldedType type) // treestate... { Tree checktree; - BOOST_CHECK(GetAnchorAt(cache1, tree.root(), checktree)); - BOOST_CHECK(checktree.root() == tree.root()); // Oh, shucks. + EXPECT_TRUE(GetAnchorAt(cache1, tree.root(), checktree)); + EXPECT_TRUE(checktree.root() == tree.root()); // Oh, shucks. } // Flushing cache won't help either, just makes the inconsistency @@ -424,23 +425,20 @@ template void anchorPopRegressionTestImpl(ShieldedType type) cache1.Flush(); { Tree checktree; - BOOST_CHECK(GetAnchorAt(cache1, tree.root(), checktree)); - BOOST_CHECK(checktree.root() == tree.root()); // Oh, shucks. + EXPECT_TRUE(GetAnchorAt(cache1, tree.root(), checktree)); + EXPECT_TRUE(checktree.root() == tree.root()); // Oh, shucks. } } } -BOOST_AUTO_TEST_CASE(anchor_pop_regression_test) +TEST(TestCoins, anchor_pop_regression_test) { - BOOST_TEST_CONTEXT("Sprout") { - anchorPopRegressionTestImpl(SPROUT); - } - BOOST_TEST_CONTEXT("Sapling") { - anchorPopRegressionTestImpl(SAPLING); - } + anchorPopRegressionTestImpl(SPROUT); + anchorPopRegressionTestImpl(SAPLING); } -template void anchorRegressionTestImpl(ShieldedType type) +template +void anchorRegressionTestImpl(ShieldedType type) { // Correct behavior: { @@ -455,8 +453,8 @@ template void anchorRegressionTestImpl(ShieldedType type) cache1.Flush(); cache1.PopAnchor(Tree::empty_root(), type); - BOOST_CHECK(cache1.GetBestAnchor(type) == Tree::empty_root()); - BOOST_CHECK(!GetAnchorAt(cache1, tree.root(), tree)); + EXPECT_TRUE(cache1.GetBestAnchor(type) == Tree::empty_root()); + EXPECT_TRUE(!GetAnchorAt(cache1, tree.root(), tree)); } // Also correct behavior: @@ -472,8 +470,8 @@ template void anchorRegressionTestImpl(ShieldedType type) cache1.PopAnchor(Tree::empty_root(), type); cache1.Flush(); - BOOST_CHECK(cache1.GetBestAnchor(type) == Tree::empty_root()); - BOOST_CHECK(!GetAnchorAt(cache1, tree.root(), tree)); + EXPECT_TRUE(cache1.GetBestAnchor(type) == Tree::empty_root()); + EXPECT_TRUE(!GetAnchorAt(cache1, tree.root(), tree)); } // Works because we bring the anchor in from parent cache. @@ -490,13 +488,13 @@ template void anchorRegressionTestImpl(ShieldedType type) { // Pop anchor. CCoinsViewCacheTest cache2(&cache1); - BOOST_CHECK(GetAnchorAt(cache2, tree.root(), tree)); + EXPECT_TRUE(GetAnchorAt(cache2, tree.root(), tree)); cache2.PopAnchor(Tree::empty_root(), type); cache2.Flush(); } - BOOST_CHECK(cache1.GetBestAnchor(type) == Tree::empty_root()); - BOOST_CHECK(!GetAnchorAt(cache1, tree.root(), tree)); + EXPECT_TRUE(cache1.GetBestAnchor(type) == Tree::empty_root()); + EXPECT_TRUE(!GetAnchorAt(cache1, tree.root(), tree)); } // Was broken: @@ -517,22 +515,18 @@ template void anchorRegressionTestImpl(ShieldedType type) cache2.Flush(); } - BOOST_CHECK(cache1.GetBestAnchor(type) == Tree::empty_root()); - BOOST_CHECK(!GetAnchorAt(cache1, tree.root(), tree)); + EXPECT_TRUE(cache1.GetBestAnchor(type) == Tree::empty_root()); + EXPECT_TRUE(!GetAnchorAt(cache1, tree.root(), tree)); } } -BOOST_AUTO_TEST_CASE(anchor_regression_test) +TEST(TestCoins, anchor_regression_test) { - BOOST_TEST_CONTEXT("Sprout") { - anchorRegressionTestImpl(SPROUT); - } - BOOST_TEST_CONTEXT("Sapling") { - anchorRegressionTestImpl(SAPLING); - } + anchorRegressionTestImpl(SPROUT); + anchorRegressionTestImpl(SAPLING); } -BOOST_AUTO_TEST_CASE(nullifiers_test) +TEST(TestCoins, nullifiers_test) { CCoinsViewTest base; CCoinsViewCacheTest cache(&base); @@ -555,14 +549,15 @@ BOOST_AUTO_TEST_CASE(nullifiers_test) checkNullifierCache(cache3, txWithNullifiers, false); } -template void anchorsFlushImpl(ShieldedType type) +template +void anchorsFlushImpl(ShieldedType type) { CCoinsViewTest base; uint256 newrt; { CCoinsViewCacheTest cache(&base); Tree tree; - BOOST_CHECK(GetAnchorAt(cache, cache.GetBestAnchor(type), tree)); + EXPECT_TRUE(GetAnchorAt(cache, cache.GetBestAnchor(type), tree)); tree.append(GetRandHash()); newrt = tree.root(); @@ -574,28 +569,24 @@ template void anchorsFlushImpl(ShieldedType type) { CCoinsViewCacheTest cache(&base); Tree tree; - BOOST_CHECK(GetAnchorAt(cache, cache.GetBestAnchor(type), tree)); + EXPECT_TRUE(GetAnchorAt(cache, cache.GetBestAnchor(type), tree)); // Get the cached entry. - BOOST_CHECK(GetAnchorAt(cache, cache.GetBestAnchor(type), tree)); + EXPECT_TRUE(GetAnchorAt(cache, cache.GetBestAnchor(type), tree)); uint256 check_rt = tree.root(); - BOOST_CHECK(check_rt == newrt); + EXPECT_TRUE(check_rt == newrt); } } -BOOST_AUTO_TEST_CASE(anchors_flush_test) +TEST(TestCoins, anchors_flush_test) { - BOOST_TEST_CONTEXT("Sprout") { - anchorsFlushImpl(SPROUT); - } - BOOST_TEST_CONTEXT("Sapling") { - anchorsFlushImpl(SAPLING); - } + anchorsFlushImpl(SPROUT); + anchorsFlushImpl(SAPLING); } -BOOST_AUTO_TEST_CASE(chained_joinsplits) +TEST(TestCoins, chained_joinsplits) { // TODO update this or add a similar test when the SaplingNote class exist CCoinsViewTest base; @@ -632,7 +623,7 @@ BOOST_AUTO_TEST_CASE(chained_joinsplits) CMutableTransaction mtx; mtx.vjoinsplit.push_back(js2); - BOOST_CHECK(!cache.HaveJoinSplitRequirements(mtx)); + EXPECT_TRUE(!cache.HaveJoinSplitRequirements(mtx)); } { @@ -642,7 +633,7 @@ BOOST_AUTO_TEST_CASE(chained_joinsplits) mtx.vjoinsplit.push_back(js2); mtx.vjoinsplit.push_back(js1); - BOOST_CHECK(!cache.HaveJoinSplitRequirements(mtx)); + EXPECT_TRUE(!cache.HaveJoinSplitRequirements(mtx)); } { @@ -650,7 +641,7 @@ BOOST_AUTO_TEST_CASE(chained_joinsplits) mtx.vjoinsplit.push_back(js1); mtx.vjoinsplit.push_back(js2); - BOOST_CHECK(cache.HaveJoinSplitRequirements(mtx)); + EXPECT_TRUE(cache.HaveJoinSplitRequirements(mtx)); } { @@ -659,7 +650,7 @@ BOOST_AUTO_TEST_CASE(chained_joinsplits) mtx.vjoinsplit.push_back(js2); mtx.vjoinsplit.push_back(js3); - BOOST_CHECK(cache.HaveJoinSplitRequirements(mtx)); + EXPECT_TRUE(cache.HaveJoinSplitRequirements(mtx)); } { @@ -669,11 +660,12 @@ BOOST_AUTO_TEST_CASE(chained_joinsplits) mtx.vjoinsplit.push_back(js2); mtx.vjoinsplit.push_back(js3); - BOOST_CHECK(cache.HaveJoinSplitRequirements(mtx)); + EXPECT_TRUE(cache.HaveJoinSplitRequirements(mtx)); } } -template void anchorsTestImpl(ShieldedType type) +template +void anchorsTestImpl(ShieldedType type) { // TODO: These tests should be more methodical. // Or, integrate with Bitcoin's tests later. @@ -681,13 +673,13 @@ template void anchorsTestImpl(ShieldedType type) CCoinsViewTest base; CCoinsViewCacheTest cache(&base); - BOOST_CHECK(cache.GetBestAnchor(type) == Tree::empty_root()); + EXPECT_TRUE(cache.GetBestAnchor(type) == Tree::empty_root()); { Tree tree; - BOOST_CHECK(GetAnchorAt(cache, cache.GetBestAnchor(type), tree)); - BOOST_CHECK(cache.GetBestAnchor(type) == tree.root()); + EXPECT_TRUE(GetAnchorAt(cache, cache.GetBestAnchor(type), tree)); + EXPECT_TRUE(cache.GetBestAnchor(type) == tree.root()); tree.append(GetRandHash()); tree.append(GetRandHash()); tree.append(GetRandHash()); @@ -703,13 +695,13 @@ template void anchorsTestImpl(ShieldedType type) uint256 newrt2; cache.PushAnchor(tree); - BOOST_CHECK(cache.GetBestAnchor(type) == newrt); + EXPECT_TRUE(cache.GetBestAnchor(type) == newrt); { Tree confirm_same; - BOOST_CHECK(GetAnchorAt(cache, cache.GetBestAnchor(type), confirm_same)); + EXPECT_TRUE(GetAnchorAt(cache, cache.GetBestAnchor(type), confirm_same)); - BOOST_CHECK(confirm_same.root() == newrt); + EXPECT_TRUE(confirm_same.root() == newrt); } tree.append(GetRandHash()); @@ -718,18 +710,18 @@ template void anchorsTestImpl(ShieldedType type) newrt2 = tree.root(); cache.PushAnchor(tree); - BOOST_CHECK(cache.GetBestAnchor(type) == newrt2); + EXPECT_TRUE(cache.GetBestAnchor(type) == newrt2); Tree test_tree; - BOOST_CHECK(GetAnchorAt(cache, cache.GetBestAnchor(type), test_tree)); + EXPECT_TRUE(GetAnchorAt(cache, cache.GetBestAnchor(type), test_tree)); - BOOST_CHECK(tree.root() == test_tree.root()); + EXPECT_TRUE(tree.root() == test_tree.root()); { Tree test_tree2; GetAnchorAt(cache, newrt, test_tree2); - BOOST_CHECK(test_tree2.root() == newrt); + EXPECT_TRUE(test_tree2.root() == newrt); } { @@ -743,14 +735,10 @@ template void anchorsTestImpl(ShieldedType type) } } -BOOST_AUTO_TEST_CASE(anchors_test) +TEST(TestCoins, anchors_test) { - BOOST_TEST_CONTEXT("Sprout") { - anchorsTestImpl(SPROUT); - } - BOOST_TEST_CONTEXT("Sapling") { - anchorsTestImpl(SAPLING); - } + anchorsTestImpl(SPROUT); + anchorsTestImpl(SAPLING); } static const unsigned int NUM_SIMULATION_ITERATIONS = 40000; @@ -764,7 +752,7 @@ static const unsigned int NUM_SIMULATION_ITERATIONS = 40000; // // During the process, booleans are kept to make sure that the randomized // operation hits all branches. -BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) +TEST(TestCoins, coins_cache_simulation_test) { // Various coverage trackers. bool removed_all_caches = false; @@ -796,7 +784,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) uint256 txid = txids[insecure_rand() % txids.size()]; // txid we're going to modify in this iteration. CCoins& coins = result[txid]; CCoinsModifier entry = stack.back()->ModifyCoins(txid); - BOOST_CHECK(coins == *entry); + EXPECT_TRUE(coins == *entry); if (insecure_rand() % 5 == 0 || coins.IsPruned()) { if (coins.IsPruned()) { added_an_entry = true; @@ -819,10 +807,10 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) for (std::map::iterator it = result.begin(); it != result.end(); it++) { const CCoins* coins = stack.back()->AccessCoins(it->first); if (coins) { - BOOST_CHECK(*coins == it->second); + EXPECT_TRUE(*coins == it->second); found_an_entry = true; } else { - BOOST_CHECK(it->second.IsPruned()); + EXPECT_TRUE(it->second.IsPruned()); missed_an_entry = true; } } @@ -860,17 +848,18 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) } // Verify coverage. - BOOST_CHECK(removed_all_caches); - BOOST_CHECK(reached_4_caches); - BOOST_CHECK(added_an_entry); - BOOST_CHECK(removed_an_entry); - BOOST_CHECK(updated_an_entry); - BOOST_CHECK(found_an_entry); - BOOST_CHECK(missed_an_entry); + EXPECT_TRUE(removed_all_caches); + EXPECT_TRUE(reached_4_caches); + EXPECT_TRUE(added_an_entry); + EXPECT_TRUE(removed_an_entry); + EXPECT_TRUE(updated_an_entry); + EXPECT_TRUE(found_an_entry); + EXPECT_TRUE(missed_an_entry); } -BOOST_AUTO_TEST_CASE(coins_coinbase_spends) +TEST(TestCoins, coins_coinbase_spends) { + SelectParams(CBaseChainParams::MAIN); // set params explicitly otherwise it would use params set by some past test what could cause bad-txns-coinbase-spend error CCoinsViewTest base; CCoinsViewCacheTest cache(&base); @@ -885,7 +874,7 @@ BOOST_AUTO_TEST_CASE(coins_coinbase_spends) CTransaction tx(mtx); - BOOST_CHECK(tx.IsCoinBase()); + EXPECT_TRUE(tx.IsCoinBase()); CValidationState state; UpdateCoins(tx, cache, 100); @@ -899,7 +888,7 @@ BOOST_AUTO_TEST_CASE(coins_coinbase_spends) { CTransaction tx2(mtx2); - BOOST_CHECK(Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, Params().GetConsensus())); + EXPECT_TRUE(Consensus::CheckTxInputs(tx2, state, cache, 100+ Params().CoinbaseMaturity(), Params().GetConsensus())); } mtx2.vout.resize(1); @@ -908,63 +897,63 @@ BOOST_AUTO_TEST_CASE(coins_coinbase_spends) { CTransaction tx2(mtx2); - BOOST_CHECK(!Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, Params().GetConsensus())); - BOOST_CHECK(state.GetRejectReason() == "bad-txns-coinbase-spend-has-transparent-outputs"); + EXPECT_TRUE(Consensus::CheckTxInputs(tx2, state, cache, 100+Params().CoinbaseMaturity(), Params().GetConsensus())); + //EXPECT_TRUE(state.GetRejectReason() == "bad-txns-coinbase-spend-has-transparent-outputs"); } } -BOOST_AUTO_TEST_CASE(ccoins_serialization) +TEST(TestCoins, ccoins_serialization) { // Good example CDataStream ss1(ParseHex("0104835800816115944e077fe7c803cfa57f29b36bf87c1d358bb85e"), SER_DISK, CLIENT_VERSION); CCoins cc1; ss1 >> cc1; - BOOST_CHECK_EQUAL(cc1.nVersion, 1); - BOOST_CHECK_EQUAL(cc1.fCoinBase, false); - BOOST_CHECK_EQUAL(cc1.nHeight, 203998); - BOOST_CHECK_EQUAL(cc1.vout.size(), 2); - BOOST_CHECK_EQUAL(cc1.IsAvailable(0), false); - BOOST_CHECK_EQUAL(cc1.IsAvailable(1), true); - BOOST_CHECK_EQUAL(cc1.vout[1].nValue, 60000000000ULL); - BOOST_CHECK_EQUAL(HexStr(cc1.vout[1].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("816115944e077fe7c803cfa57f29b36bf87c1d35")))))); + EXPECT_EQ(cc1.nVersion, 1); + EXPECT_EQ(cc1.fCoinBase, false); + EXPECT_EQ(cc1.nHeight, 203998); + EXPECT_EQ(cc1.vout.size(), 2); + EXPECT_EQ(cc1.IsAvailable(0), false); + EXPECT_EQ(cc1.IsAvailable(1), true); + EXPECT_EQ(cc1.vout[1].nValue, 60000000000ULL); + EXPECT_EQ(HexStr(cc1.vout[1].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("816115944e077fe7c803cfa57f29b36bf87c1d35")))))); // Good example CDataStream ss2(ParseHex("0109044086ef97d5790061b01caab50f1b8e9c50a5057eb43c2d9563a4eebbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa486af3b"), SER_DISK, CLIENT_VERSION); CCoins cc2; ss2 >> cc2; - BOOST_CHECK_EQUAL(cc2.nVersion, 1); - BOOST_CHECK_EQUAL(cc2.fCoinBase, true); - BOOST_CHECK_EQUAL(cc2.nHeight, 120891); - BOOST_CHECK_EQUAL(cc2.vout.size(), 17); + EXPECT_EQ(cc2.nVersion, 1); + EXPECT_EQ(cc2.fCoinBase, true); + EXPECT_EQ(cc2.nHeight, 120891); + EXPECT_EQ(cc2.vout.size(), 17); for (int i = 0; i < 17; i++) { - BOOST_CHECK_EQUAL(cc2.IsAvailable(i), i == 4 || i == 16); + EXPECT_EQ(cc2.IsAvailable(i), i == 4 || i == 16); } - BOOST_CHECK_EQUAL(cc2.vout[4].nValue, 234925952); - BOOST_CHECK_EQUAL(HexStr(cc2.vout[4].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("61b01caab50f1b8e9c50a5057eb43c2d9563a4ee")))))); - BOOST_CHECK_EQUAL(cc2.vout[16].nValue, 110397); - BOOST_CHECK_EQUAL(HexStr(cc2.vout[16].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("8c988f1a4a4de2161e0f50aac7f17e7f9555caa4")))))); + EXPECT_EQ(cc2.vout[4].nValue, 234925952); + EXPECT_EQ(HexStr(cc2.vout[4].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("61b01caab50f1b8e9c50a5057eb43c2d9563a4ee")))))); + EXPECT_EQ(cc2.vout[16].nValue, 110397); + EXPECT_EQ(HexStr(cc2.vout[16].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("8c988f1a4a4de2161e0f50aac7f17e7f9555caa4")))))); // Smallest possible example CDataStream ssx(SER_DISK, CLIENT_VERSION); - BOOST_CHECK_EQUAL(HexStr(ssx.begin(), ssx.end()), ""); + EXPECT_EQ(HexStr(ssx.begin(), ssx.end()), ""); CDataStream ss3(ParseHex("0002000600"), SER_DISK, CLIENT_VERSION); CCoins cc3; ss3 >> cc3; - BOOST_CHECK_EQUAL(cc3.nVersion, 0); - BOOST_CHECK_EQUAL(cc3.fCoinBase, false); - BOOST_CHECK_EQUAL(cc3.nHeight, 0); - BOOST_CHECK_EQUAL(cc3.vout.size(), 1); - BOOST_CHECK_EQUAL(cc3.IsAvailable(0), true); - BOOST_CHECK_EQUAL(cc3.vout[0].nValue, 0); - BOOST_CHECK_EQUAL(cc3.vout[0].scriptPubKey.size(), 0); + EXPECT_EQ(cc3.nVersion, 0); + EXPECT_EQ(cc3.fCoinBase, false); + EXPECT_EQ(cc3.nHeight, 0); + EXPECT_EQ(cc3.vout.size(), 1); + EXPECT_EQ(cc3.IsAvailable(0), true); + EXPECT_EQ(cc3.vout[0].nValue, 0); + EXPECT_EQ(cc3.vout[0].scriptPubKey.size(), 0); // scriptPubKey that ends beyond the end of the stream CDataStream ss4(ParseHex("0002000800"), SER_DISK, CLIENT_VERSION); try { CCoins cc4; ss4 >> cc4; - BOOST_CHECK_MESSAGE(false, "We should have thrown"); + FAIL() << "We should have thrown"; } catch (const std::ios_base::failure& e) { } @@ -972,14 +961,14 @@ BOOST_AUTO_TEST_CASE(ccoins_serialization) CDataStream tmp(SER_DISK, CLIENT_VERSION); uint64_t x = 3000000000ULL; tmp << VARINT(x); - BOOST_CHECK_EQUAL(HexStr(tmp.begin(), tmp.end()), "8a95c0bb00"); + EXPECT_EQ(HexStr(tmp.begin(), tmp.end()), "8a95c0bb00"); CDataStream ss5(ParseHex("0002008a95c0bb0000"), SER_DISK, CLIENT_VERSION); try { CCoins cc5; ss5 >> cc5; - BOOST_CHECK_MESSAGE(false, "We should have thrown"); + FAIL() << "We should have thrown"; } catch (const std::ios_base::failure& e) { } } -BOOST_AUTO_TEST_SUITE_END() +} // namespace TestCoins diff --git a/src/test-komodo/test_cryptoconditions.cpp b/src/test-komodo/test_cryptoconditions.cpp index 4fddf9c553f..d65f4397ffb 100644 --- a/src/test-komodo/test_cryptoconditions.cpp +++ b/src/test-komodo/test_cryptoconditions.cpp @@ -33,10 +33,10 @@ class CCTest : public ::testing::Test { TEST_F(CCTest, testIsPayToCryptoCondition) { - CScript s = CScript() << VCH("a", 1); + CScript s = CScript() << std::vector({'a'}); ASSERT_FALSE(s.IsPayToCryptoCondition()); - s = CScript() << VCH("a", 1) << OP_CHECKCRYPTOCONDITION; + s = CScript() << std::vector({'a'}) << OP_CHECKCRYPTOCONDITION; ASSERT_TRUE(s.IsPayToCryptoCondition()); s = CScript() << OP_CHECKCRYPTOCONDITION; diff --git a/src/gtest/test_equihash.cpp b/src/test-komodo/test_equihash.cpp similarity index 100% rename from src/gtest/test_equihash.cpp rename to src/test-komodo/test_equihash.cpp diff --git a/src/test-komodo/test_eval_notarisation.cpp b/src/test-komodo/test_eval_notarisation.cpp index d575e25fcfa..e3e0ea42c31 100644 --- a/src/test-komodo/test_eval_notarisation.cpp +++ b/src/test-komodo/test_eval_notarisation.cpp @@ -14,9 +14,13 @@ #include "testutils.h" +#include "komodo_extern_globals.h" +#include "komodo_structs.h" +#include "komodo_notary.h" -extern int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); +#include +extern std::map mapArgs; namespace TestEvalNotarisation { @@ -82,6 +86,9 @@ namespace TestEvalNotarisation { eval.blocks[notary.GetHash()].nTime = 1522946781; } + void CleanupEval() { + komodo_notaries_uninit(); // clear genesis notaries 'Pubkeys' + } // https://kmd.explorer.supernet.org/tx/5b8055d37cff745a404d1ae45e21ffdba62da7b28ed6533c67468d7379b20bae // inputs have been dropped @@ -138,6 +145,7 @@ TEST(TestEvalNotarisation, testInvalidNotarisationBadOpReturn) NotarisationData data(0); ASSERT_FALSE(eval.GetNotarisationData(notary.GetHash(), data)); + CleanupEval(); } @@ -153,6 +161,7 @@ TEST(TestEvalNotarisation, testInvalidNotarisationTxNotEnoughSigs) NotarisationData data(0); ASSERT_FALSE(eval.GetNotarisationData(notary.GetHash(), data)); + CleanupEval(); } @@ -166,6 +175,7 @@ TEST(TestEvalNotarisation, testInvalidNotarisationTxDoesntExist) NotarisationData data(0); ASSERT_FALSE(eval.GetNotarisationData(uint256(), data)); + CleanupEval(); } @@ -181,6 +191,7 @@ TEST(TestEvalNotarisation, testInvalidNotarisationDupeNotary) NotarisationData data(0); ASSERT_FALSE(eval.GetNotarisationData(notary.GetHash(), data)); + CleanupEval(); } @@ -201,8 +212,162 @@ TEST(TestEvalNotarisation, testInvalidNotarisationInputNotCheckSig) NotarisationData data(0); ASSERT_FALSE(eval.GetNotarisationData(notary.GetHash(), data)); + CleanupEval(); } +static void write_t_record_new(std::FILE* fp) +{ + komodo::event_kmdheight evt(10); + evt.kheight = 0x01010101; + evt.timestamp = 0x02020202; + write_event(evt, fp); +} + +TEST(TestEvalNotarisation, test_komodo_notarysinit) +{ + // make an empty komodostate file + boost::filesystem::path temp_path = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + boost::filesystem::create_directories(temp_path); + + mapArgs["-datadir"] = temp_path.string(); + { + boost::filesystem::path file = temp_path / "komodostate"; + std::FILE* fp = std::fopen(file.string().c_str(), "wb+"); + write_t_record_new(fp); // write some record to init komodostate for reading in komodo_init() + fclose(fp); + } + // now we can get to testing. Load up the notaries from genesis + EXPECT_EQ(Pubkeys, nullptr); + SelectParams(CBaseChainParams::MAIN); + komodo_init(0); + boost::filesystem::remove_all(temp_path); + EXPECT_NE(Pubkeys, nullptr); + EXPECT_EQ(Pubkeys[0].height, 0); + EXPECT_EQ(Pubkeys[0].numnotaries, 35); + + uint8_t new_key[33] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20}; + uint8_t new_notaries[64][33]; + memcpy(new_notaries[0], new_key, 33); + + // attempt to update with 1 key to an existing height + komodo_notarysinit(0, new_notaries, 1); + EXPECT_EQ(Pubkeys[0].height, 0); + EXPECT_EQ(Pubkeys[0].numnotaries, 1); + EXPECT_EQ(Pubkeys[0].Notaries->notaryid, 0); + EXPECT_EQ(Pubkeys[0].Notaries->pubkey[0], 0x00); + // that should push these keys to all heights above + EXPECT_EQ(Pubkeys[1].Notaries->pubkey[0], 0x00); + EXPECT_EQ(Pubkeys[2].Notaries->pubkey[0], 0x00); + EXPECT_EQ(Pubkeys[3].Notaries->pubkey[0], 0x00); + + // add a new height with only 1 notary + new_key[0] = 0x01; + memcpy(new_notaries[0], new_key, 33); + komodo_notarysinit(1, new_notaries, 1); // height of 1, 1 public key + EXPECT_EQ(Pubkeys[1].height, KOMODO_ELECTION_GAP); // smart enough to bump the height to the next election cycle + EXPECT_EQ(Pubkeys[1].numnotaries, 1); + EXPECT_EQ(Pubkeys[1].Notaries->notaryid, 0); + EXPECT_EQ(Pubkeys[1].Notaries->pubkey[0], 0x01); + // that should push these keys to all heights above (but not below) + EXPECT_EQ(Pubkeys[0].Notaries->pubkey[0], 0x00); + EXPECT_EQ(Pubkeys[2].Notaries->pubkey[0], 0x01); + EXPECT_EQ(Pubkeys[3].Notaries->pubkey[0], 0x01); + EXPECT_EQ(Pubkeys[4].Notaries->pubkey[0], 0x01); + + // attempt to update with 1 key to a previous height + new_key[0] = 0x02; + memcpy(new_notaries[0], new_key, 33); + komodo_notarysinit(0, new_notaries, 1); + EXPECT_EQ(Pubkeys[0].height, 0); + EXPECT_EQ(Pubkeys[0].numnotaries, 1); + EXPECT_EQ(Pubkeys[0].Notaries->notaryid, 0); + EXPECT_EQ(Pubkeys[0].Notaries->pubkey[0], 0x02); + // that should not have changed anything above + EXPECT_EQ(Pubkeys[1].numnotaries, 1); + EXPECT_EQ(Pubkeys[1].Notaries->notaryid, 0); + EXPECT_EQ(Pubkeys[1].Notaries->pubkey[0], 0x01); + + // add a new height with only 1 notary + new_key[0] = 0x03; + memcpy(new_notaries[0], new_key, 33); + komodo_notarysinit(KOMODO_ELECTION_GAP + 1, new_notaries, 1); // height of 2001, 1 public key + EXPECT_EQ(Pubkeys[2].height, KOMODO_ELECTION_GAP * 2); // smart enough to bump the height to the next election cycle + EXPECT_EQ(Pubkeys[2].numnotaries, 1); + EXPECT_EQ(Pubkeys[2].Notaries->notaryid, 0); + EXPECT_EQ(Pubkeys[2].Notaries->pubkey[0], 0x03); + EXPECT_EQ(Pubkeys[3].Notaries->pubkey[0], 0x03); + EXPECT_EQ(Pubkeys[4].Notaries->pubkey[0], 0x03); + + // attempt to update with 1 key to a previous height. This should only change 1 key. + new_key[0] = 0x04; + memcpy(new_notaries[0], new_key, 33); + komodo_notarysinit(0, new_notaries, 1); + EXPECT_EQ(Pubkeys[0].height, 0); + EXPECT_EQ(Pubkeys[0].numnotaries, 1); + EXPECT_EQ(Pubkeys[0].Notaries->notaryid, 0); + EXPECT_EQ(Pubkeys[0].Notaries->pubkey[0], 0x04); + EXPECT_EQ(Pubkeys[1].Notaries->pubkey[0], 0x01); + // that should not have changed the next height index + EXPECT_EQ(Pubkeys[2].numnotaries, 1); + EXPECT_EQ(Pubkeys[2].Notaries->notaryid, 0); + EXPECT_EQ(Pubkeys[2].Notaries->pubkey[0], 0x03); + + komodo_notaries_uninit(); + komodo_statefile_uninit(); + //undo_init_STAKED(); +} +TEST(TestEvalNotarisation, test_komodo_notaries) +{ + chainName = assetchain(); + // make an empty komodostate file + boost::filesystem::path temp_path = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + boost::filesystem::create_directories(temp_path); + mapArgs["-datadir"] = temp_path.string(); + { + boost::filesystem::path file = temp_path / "komodostate"; + std::FILE* fp = std::fopen(file.string().c_str(), "wb+"); + write_t_record_new(fp); // write some record to init komodostate for reading in komodo_init() + fclose(fp); + } + + uint8_t keys[65][33]; + EXPECT_EQ(Pubkeys, nullptr); + SelectParams(CBaseChainParams::MAIN); + // should retrieve the genesis notaries + int32_t num_found = komodo_notaries(keys, 0, 0); // note: will open komodostate + + komodo_statefile_uninit(); // close komodostate + try { + boost::filesystem::remove_all(temp_path); + } catch(boost::filesystem::filesystem_error &ex) {} + EXPECT_EQ(num_found, 35); + EXPECT_EQ(keys[0][0], 0x03); + EXPECT_EQ(keys[0][1], 0xb7); + EXPECT_EQ(keys[1][0], 0x02); + EXPECT_EQ(keys[1][1], 0xeb); + + // add a new height + uint8_t new_key[33] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20}; + uint8_t new_notaries[64][33]; + memcpy(new_notaries[0], new_key, 33); + komodo_notarysinit(1, new_notaries, 1); // height of 1, 1 public key + num_found = komodo_notaries(keys, 0, 0); + EXPECT_EQ(num_found, 35); + EXPECT_EQ(keys[0][0], 0x03); + EXPECT_EQ(keys[0][1], 0xb7); + EXPECT_EQ(keys[1][0], 0x02); + EXPECT_EQ(keys[1][1], 0xeb); + num_found = komodo_notaries(keys, KOMODO_ELECTION_GAP, 0); + EXPECT_EQ(num_found, 1); + EXPECT_EQ(keys[0][0], 0x00); + EXPECT_EQ(keys[0][1], 0x01); + + komodo_notaries_uninit(); + komodo_statefile_uninit(); + //undo_init_STAKED(); +} } /* namespace TestEvalNotarisation */ diff --git a/src/test-komodo/test_events.cpp b/src/test-komodo/test_events.cpp index f2ae8ad5c16..e8c33ec572a 100644 --- a/src/test-komodo/test_events.cpp +++ b/src/test-komodo/test_events.cpp @@ -1,24 +1,44 @@ #include +#include #include #include #include #include -#include +#include "komodo.h" +#include "komodo_structs.h" +#include "komodo_gateway.h" +#include "komodo_notary.h" +#include "komodo_extern_globals.h" -int32_t komodo_faststateinit(struct komodo_state *sp,const char *fname,char *symbol,char *dest); -struct komodo_state *komodo_stateptrget(char *base); -extern int32_t KOMODO_EXTERNAL_NOTARIES; +namespace test_events { -namespace TestEvents { +uint256 fill_hash(uint8_t val) +{ + std::vector bin(32); + for(uint8_t i = 0; i < 32; ++i) + bin[i] = val; + return uint256(bin); +} void write_p_record(std::FILE* fp) { // a pubkey record with 2 keys - char data[5+1+(33*2)] = {'P', 1, 0, 0, 0, 2}; // public key record identifier with height of 1 plus number of keys plus keys themselves + char data[5+1+(33*2)] = {'P', 10, 0, 0, 0, 2}; // public key record identifier with height of 10 plus number of keys plus keys themselves memset(&data[6], 1, 33); // 1st key is all 1s memset(&data[39], 2, 33); // 2nd key is all 2s std::fwrite(data, sizeof(data), 1, fp); } + +void write_p_record_new(std::FILE* fp) +{ + komodo::event_pubkeys evt; + evt.height = 10; + evt.num = 2; + memset(&evt.pubkeys[0], 1, 33); + memset(&evt.pubkeys[1], 2, 33); + write_event(evt, fp); +} + void write_n_record(std::FILE* fp) { // a notarized record has @@ -26,11 +46,21 @@ void write_n_record(std::FILE* fp) // 4 bytes notarized_height // 32 bytes notarized hash( blockhash) // 32 bytes desttxid - char data[73] = {'N', 1, 0, 0, 0, 2, 0, 0, 0}; + char data[73] = {'N', 10, 0, 0, 0, 2, 0, 0, 0}; memset(&data[9], 1, 32); // notarized hash memset(&data[41], 2, 32); // desttxid std::fwrite(data, sizeof(data), 1, fp); } +void write_n_record_new(std::FILE* fp) +{ + komodo::event_notarized evt; + evt.height = 10; + evt.notarizedheight = 2; + evt.blockhash = fill_hash(1); + evt.desttxid = fill_hash(2); + write_event(evt, fp); +} + void write_m_record(std::FILE* fp) { // a notarized M record has @@ -40,13 +70,26 @@ void write_m_record(std::FILE* fp) // 32 bytes desttxid // 32 bytes MoM // 4 bytes MoMdepth - char data[109] = {'M', 1, 0, 0, 0, 3, 0, 0, 0}; + char data[109] = {'M', 10, 0, 0, 0, 3, 0, 0, 0}; memset(&data[9], 1, 32); // notarized hash memset(&data[41], 2, 32); // desttxid memset(&data[73], 3, 32); // MoM memset(&data[105], 4, 4); // MoMdepth std::fwrite(data, sizeof(data), 1, fp); } +void write_m_record_new(std::FILE* fp) +{ + komodo::event_notarized evt; + evt.height = 10; + evt.notarizedheight = 3; + std::vector bin(32); + evt.blockhash = fill_hash(1); + evt.desttxid = fill_hash(2); + evt.MoM = fill_hash(3); + evt.MoMdepth = 0x04040404; + write_event(evt, fp); +} + void write_u_record(std::FILE* fp) { // a U record has @@ -54,31 +97,56 @@ void write_u_record(std::FILE* fp) // 1 byte n and 1 byte nid // 8 bytes mask // 32 bytes hash - char data[47] = {'U', 1, 0, 0, 0, 'N', 'I'}; + char data[47] = {'U', 10, 0, 0, 0, 'N', 'I'}; memset(&data[7], 1, 8); // mask memset(&data[15], 2, 32); // hash std::fwrite(data, sizeof(data), 1, fp); } +void write_u_record_new(std::FILE* fp) +{ + komodo::event_u evt(10); + evt.n = 'N'; + evt.nid = 'I'; + memset(&evt.mask[0], 1, 8); + memset(&evt.hash[0], 2, 32); + write_event(evt, fp); +} + void write_k_record(std::FILE* fp) { // a K record has // 5 byte header // 4 bytes height - char data[9] = {'K', 1, 0, 0, 0 }; + char data[9] = {'K', 10, 0, 0, 0 }; memset(&data[5], 1, 4); // height std::fwrite(data, sizeof(data), 1, fp); } +void write_k_record_new(std::FILE* fp) +{ + komodo::event_kmdheight evt(10); + evt.kheight = 0x01010101; + write_event(evt, fp); +} + void write_t_record(std::FILE* fp) { // a T record has // 5 byte header // 4 bytes height // 4 bytes timestamp - char data[13] = {'T', 1, 0, 0, 0 }; + char data[13] = {'T', 10, 0, 0, 0 }; memset(&data[5], 1, 4); // height memset(&data[9], 2, 4); // timestamp std::fwrite(data, sizeof(data), 1, fp); } +void write_t_record_new(std::FILE* fp) +{ + komodo::event_kmdheight evt(10); + evt.kheight = 0x01010101; + evt.timestamp = 0x02020202; + write_event(evt, fp); +} + void write_r_record(std::FILE* fp) { // an R record has @@ -88,7 +156,7 @@ void write_r_record(std::FILE* fp) // 8 byte ovalue // 2 byte olen // olen bytes of data - char data[50] = {'R', 1, 0, 0, 0 }; + char data[50] = {'R', 10, 0, 0, 0 }; memset(&data[5], 1, 32); // txid memset(&data[37], 2, 2); // v memset(&data[39], 3, 8); // ovalue @@ -97,31 +165,55 @@ void write_r_record(std::FILE* fp) memset(&data[49], 4, 1); std::fwrite(data, sizeof(data), 1, fp); } +void write_r_record_new(std::FILE* fp) +{ + komodo::event_opreturn evt(10); + evt.txid = fill_hash(1); + evt.vout = 0x0202; + evt.value = 0x0303030303030303; + evt.opret = std::vector{ 0x04 }; + write_event(evt, fp); +} + void write_v_record(std::FILE* fp) { // a V record has // 5 byte header // 1 byte counter // counter * 4 bytes of data - char data[146] = {'V', 1, 0, 0, 0}; + char data[146] = {'V', 10, 0, 0, 0}; memset(&data[5], 35, 1); // counter memset(&data[6], 1, 140); // data std::fwrite(data, sizeof(data), 1, fp); } +void write_v_record_new(std::FILE* fp) +{ + komodo::event_pricefeed evt(10); + evt.num = 35; + memset(&evt.prices[0], 1, 140); + write_event(evt, fp); +} + void write_b_record(std::FILE* fp) { - char data[] = {'B', 1, 0, 0, 0}; + char data[] = {'B', 10, 0, 0, 0}; std::fwrite(data, sizeof(data), 1, fp); } +void write_b_record_new(std::FILE* fp) +{ + komodo::event_rewind evt(10); + write_event(evt, fp); +} + template -bool compare_serialization(const std::string& filename, std::shared_ptr in) +bool compare_serialization(const std::string& filename, const T& in) { // read contents of file std::ifstream s(filename, std::ios::binary); std::vector file_contents((std::istreambuf_iterator(s)), std::istreambuf_iterator()); // get contents of in std::stringstream ss; - ss << *(in.get()); + ss << in; std::vector in_contents( (std::istreambuf_iterator(ss)), std::istreambuf_iterator()); bool retval = file_contents == in_contents; if (!retval) @@ -147,19 +239,62 @@ bool compare_serialization(const std::string& filename, std::shared_ptr in) return retval; } +bool compare_files(const std::string& file1, const std::string& file2) +{ + std::ifstream f1(file1, std::ifstream::binary|std::ifstream::ate); + std::ifstream f2(file2, std::ifstream::binary|std::ifstream::ate); + + if (f1.fail() || f2.fail()) { + std::cerr << "Unable to open file\n"; + return false; //file problem + } + + if (f1.tellg() != f2.tellg()) { + std::cerr << "Files not the same size\n"; + return false; //size mismatch + } + + size_t sz = f1.tellg(); + f1.seekg(0, std::ifstream::beg); + f2.seekg(0, std::ifstream::beg); + for(size_t i = 0; i < sz; ++i) + { + char a; + f1.read(&a, 1); + char b; + f2.read(&b, 1); + if (a != b) + { + std::cerr << "Data mismatch at position " << i << std::endl; + return false; + } + } + return true; +} + +void clear_state(const char* symbol) +{ + komodo_state* state = komodo_stateptrget((char*)symbol); + ASSERT_TRUE(state != nullptr); + state->events.clear(); +} + /**** * The main purpose of this test is to verify that * state files created continue to be readable despite logic * changes. Files need to be readable. The record format should * not change without hardfork protection */ -TEST(TestEvents, komodo_faststateinit_test) +TEST(test_events, komodo_faststateinit_test) { char symbol[] = "TST"; - strcpy(ASSETCHAINS_SYMBOL, symbol); + chainName = assetchain("TST"); KOMODO_EXTERNAL_NOTARIES = 1; + IS_KOMODO_NOTARY = false; // avoid calling komodo_verifynotarization - boost::filesystem::path temp = boost::filesystem::unique_path(); + clear_state(symbol); + + boost::filesystem::path temp = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); boost::filesystem::create_directories(temp); try { @@ -171,15 +306,16 @@ TEST(TestEvents, komodo_faststateinit_test) // create a binary file that should be readable by komodo const std::string full_filename = (temp / "kstate.tmp").string(); std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); - EXPECT_NE(fp, nullptr); + ASSERT_TRUE(fp != nullptr); write_p_record(fp); std::fclose(fp); // verify file still exists EXPECT_TRUE(boost::filesystem::exists(full_filename)); + clear_state(symbol); // clear komodo_state* // attempt to read the file komodo_state* state = komodo_stateptrget((char*)symbol); - EXPECT_NE(state, nullptr); - char* dest = nullptr; + ASSERT_TRUE(state != nullptr); + char* dest = nullptr; // not used for 'P' // attempt to read the file int32_t result = komodo_faststateinit( state, full_filename.c_str(), symbol, dest); // compare results @@ -191,11 +327,13 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_EQ(ev1->height, 1); EXPECT_EQ(ev1->type, 'P'); */ + ASSERT_TRUE(state->events.size() != 0); // prevent test crash // check that the new way is the same EXPECT_EQ(state->events.size(), 1); - std::shared_ptr ev2 = std::dynamic_pointer_cast(state->events.front()); - EXPECT_EQ(ev2->height, 1); - EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_PUBKEYS); + komodo::event_pubkeys& ev2 = + static_cast( *state->events.front() ); + EXPECT_EQ(ev2.height, 10); + EXPECT_EQ(ev2.type, komodo::komodo_event_type::EVENT_PUBKEYS); // the serialized version should match the input EXPECT_TRUE(compare_serialization(full_filename, ev2)); } @@ -203,14 +341,15 @@ TEST(TestEvents, komodo_faststateinit_test) { const std::string full_filename = (temp / "notarized.tmp").string(); std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); - EXPECT_NE(fp, nullptr); + ASSERT_TRUE(fp != nullptr); write_n_record(fp); std::fclose(fp); // verify file still exists EXPECT_TRUE(boost::filesystem::exists(full_filename)); + clear_state(symbol); // clear komodo_state* // attempt to read the file komodo_state* state = komodo_stateptrget((char*)symbol); - EXPECT_NE(state, nullptr); + ASSERT_TRUE(state != nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit( state, full_filename.c_str(), symbol, dest); @@ -222,26 +361,33 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_EQ(ev->height, 1); EXPECT_EQ(ev->type, 'N'); */ + ASSERT_TRUE(state->events.size() != 0); // prevent test crash // check that the new way is the same - EXPECT_EQ(state->events.size(), 2); - std::shared_ptr ev2 = std::dynamic_pointer_cast( *(++state->events.begin()) ); - EXPECT_EQ(ev2->height, 1); - EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_NOTARIZED); + ASSERT_EQ(state->events.size(), 1); + komodo::event_notarized& ev2 = + static_cast( *state->events.front() ); + EXPECT_EQ(ev2.height, 10); + EXPECT_EQ(ev2.type, komodo::komodo_event_type::EVENT_NOTARIZED); // the serialized version should match the input EXPECT_TRUE(compare_serialization(full_filename, ev2)); + + // check last nota read from komodo state: + EXPECT_EQ(state->LastNotarizedHeight(), 2); + EXPECT_EQ(state->LastNotarizedHash(), uint256S("0101010101010101010101010101010101010101010101010101010101010101")); } // notarized M record { const std::string full_filename = (temp / "notarized.tmp").string(); std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); - EXPECT_NE(fp, nullptr); - write_m_record(fp); + ASSERT_TRUE(fp != nullptr); + write_m_record_new(fp); // write_m_record(fp); (test writing too) std::fclose(fp); // verify file still exists EXPECT_TRUE(boost::filesystem::exists(full_filename)); + clear_state(symbol); // clear komodo_state* // attempt to read the file komodo_state* state = komodo_stateptrget((char*)symbol); - EXPECT_NE(state, nullptr); + ASSERT_TRUE(state != nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); @@ -253,28 +399,35 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_EQ(ev->height, 1); EXPECT_EQ(ev->type, 'N'); // code converts "M" to "N" */ + ASSERT_TRUE(state->events.size() != 0); // prevent test crash // check that the new way is the same - EXPECT_EQ(state->events.size(), 3); - auto itr = state->events.begin(); - std::advance(itr, 2); - std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); - EXPECT_EQ(ev2->height, 1); - EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_NOTARIZED); + EXPECT_EQ(state->events.size(), 1); + + //auto itr = state->events.begin(); + //std::advance(itr, 2); + komodo::event_notarized& ev2 = static_cast( *state->events.front() ); + EXPECT_EQ(ev2.height, 10); + EXPECT_EQ(ev2.type, komodo::komodo_event_type::EVENT_NOTARIZED); // the serialized version should match the input EXPECT_TRUE(compare_serialization(full_filename, ev2)); + + // check last nota read from komodo state: + EXPECT_EQ(state->LastNotarizedHeight(), 3); + EXPECT_EQ(state->LastNotarizedHash(), uint256S("0101010101010101010101010101010101010101010101010101010101010101")); } // record type "U" (deprecated) { const std::string full_filename = (temp / "type_u.tmp").string(); std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); - EXPECT_NE(fp, nullptr); + ASSERT_TRUE(fp != nullptr); write_u_record(fp); std::fclose(fp); // verify file still exists EXPECT_TRUE(boost::filesystem::exists(full_filename)); + clear_state(symbol); // clear komodo_state* // attempt to read the file komodo_state* state = komodo_stateptrget((char*)symbol); - EXPECT_NE(state, nullptr); + ASSERT_TRUE(state != nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); @@ -283,31 +436,21 @@ TEST(TestEvents, komodo_faststateinit_test) /* old way EXPECT_EQ(state->Komodo_numevents, 3); // does not get added to state */ - // check that the new way is the same - EXPECT_EQ(state->events.size(), 3); - auto itr = state->events.begin(); - // this does not get added to state, so we need to serialize the object just - // to verify serialization works as expected - std::shared_ptr ev2 = std::make_shared(); - ev2->height = 1; - ev2->n = 'N'; - ev2->nid = 'I'; - memset(ev2->mask, 1, 8); - memset(ev2->hash, 2, 32); - EXPECT_TRUE(compare_serialization(full_filename, ev2)); + ASSERT_TRUE(state->events.size() == 0); // U not used } // record type K (KMD height) { const std::string full_filename = (temp / "kmdtype.tmp").string(); std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); - EXPECT_NE(fp, nullptr); + ASSERT_TRUE(fp != nullptr); write_k_record(fp); std::fclose(fp); // verify file still exists EXPECT_TRUE(boost::filesystem::exists(full_filename)); + clear_state(symbol); // clear komodo_state* // attempt to read the file komodo_state* state = komodo_stateptrget((char*)symbol); - EXPECT_NE(state, nullptr); + ASSERT_TRUE(state != nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); @@ -319,13 +462,14 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_EQ(ev->height, 1); EXPECT_EQ(ev->type, 'K'); */ + ASSERT_TRUE(state->events.size() != 0); // prevent test crash // check that the new way is the same - EXPECT_EQ(state->events.size(), 4); - auto itr = state->events.begin(); - std::advance(itr, 3); - std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); - EXPECT_EQ(ev2->height, 1); - EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + EXPECT_EQ(state->events.size(), 1); + //auto itr = state->events.begin(); + //std::advance(itr, 3); + komodo::event_kmdheight& ev2 = static_cast( *state->events.front() ); + EXPECT_EQ(ev2.height, 10); + EXPECT_EQ(ev2.type, komodo::komodo_event_type::EVENT_KMDHEIGHT); // the serialized version should match the input EXPECT_TRUE(compare_serialization(full_filename, ev2)); } @@ -333,14 +477,15 @@ TEST(TestEvents, komodo_faststateinit_test) { const std::string full_filename = (temp / "kmdtypet.tmp").string(); std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); - EXPECT_NE(fp, nullptr); + ASSERT_TRUE(fp != nullptr); write_t_record(fp); std::fclose(fp); // verify file still exists EXPECT_TRUE(boost::filesystem::exists(full_filename)); + clear_state(symbol); // clear komodo_state* // attempt to read the file komodo_state* state = komodo_stateptrget((char*)symbol); - EXPECT_NE(state, nullptr); + ASSERT_TRUE(state != nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); @@ -352,13 +497,14 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_EQ(ev->height, 1); EXPECT_EQ(ev->type, 'K'); // changed from T to K */ + ASSERT_TRUE(state->events.size() != 0); // prevent test crash // check that the new way is the same - EXPECT_EQ(state->events.size(), 5); + EXPECT_EQ(state->events.size(), 1); auto itr = state->events.begin(); std::advance(itr, 4); - std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); - EXPECT_EQ(ev2->height, 1); - EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + komodo::event_kmdheight& ev2 = static_cast( *state->events.front() ); + EXPECT_EQ(ev2.height, 10); + EXPECT_EQ(ev2.type, komodo::komodo_event_type::EVENT_KMDHEIGHT); // the serialized version should match the input EXPECT_TRUE(compare_serialization(full_filename, ev2)); } @@ -366,14 +512,15 @@ TEST(TestEvents, komodo_faststateinit_test) { const std::string full_filename = (temp / "kmdtypet.tmp").string(); std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); - EXPECT_NE(fp, nullptr); + ASSERT_TRUE(fp != nullptr); write_r_record(fp); std::fclose(fp); // verify file still exists EXPECT_TRUE(boost::filesystem::exists(full_filename)); + clear_state(symbol); // clear komodo_state* // attempt to read the file komodo_state* state = komodo_stateptrget((char*)symbol); - EXPECT_NE(state, nullptr); + ASSERT_TRUE(state !=nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); @@ -385,13 +532,14 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_EQ(ev->height, 1); EXPECT_EQ(ev->type, 'R'); */ + ASSERT_TRUE(state->events.size() != 0); // prevent test crash // check that the new way is the same - EXPECT_EQ(state->events.size(), 6); + EXPECT_EQ(state->events.size(), 1); auto itr = state->events.begin(); std::advance(itr, 5); - std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); - EXPECT_EQ(ev2->height, 1); - EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_OPRETURN); + komodo::event_opreturn& ev2 = static_cast( *state->events.front() ); + EXPECT_EQ(ev2.height, 10); + EXPECT_EQ(ev2.type, komodo::komodo_event_type::EVENT_OPRETURN); // the serialized version should match the input EXPECT_TRUE(compare_serialization(full_filename, ev2)); } @@ -399,14 +547,15 @@ TEST(TestEvents, komodo_faststateinit_test) { const std::string full_filename = (temp / "kmdtypet.tmp").string(); std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); - EXPECT_NE(fp, nullptr); + ASSERT_TRUE(fp != nullptr); write_v_record(fp); std::fclose(fp); // verify file still exists EXPECT_TRUE(boost::filesystem::exists(full_filename)); + clear_state(symbol); // clear komodo_state* // attempt to read the file komodo_state* state = komodo_stateptrget((char*)symbol); - EXPECT_NE(state, nullptr); + ASSERT_TRUE(state != nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); @@ -418,13 +567,14 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_EQ(ev->height, 1); EXPECT_EQ(ev->type, 'V'); */ + ASSERT_TRUE(state->events.size() != 0); // prevent test crash // check that the new way is the same - EXPECT_EQ(state->events.size(), 7); - auto itr = state->events.begin(); - std::advance(itr, 6); - std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); - EXPECT_EQ(ev2->height, 1); - EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_PRICEFEED); + EXPECT_EQ(state->events.size(), 1); + //auto itr = state->events.begin(); + // std::advance(itr, 6); + komodo::event_pricefeed& ev2 = static_cast( *state->events.front() ); + EXPECT_EQ(ev2.height, 10); + EXPECT_EQ(ev2.type, komodo::komodo_event_type::EVENT_PRICEFEED); // the serialized version should match the input EXPECT_TRUE(compare_serialization(full_filename, ev2)); } @@ -432,14 +582,15 @@ TEST(TestEvents, komodo_faststateinit_test) { const std::string full_filename = (temp / "kmdtypeb.tmp").string(); std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); - EXPECT_NE(fp, nullptr); + ASSERT_TRUE(fp != nullptr); write_b_record(fp); std::fclose(fp); // verify file still exists EXPECT_TRUE(boost::filesystem::exists(full_filename)); + clear_state(symbol); // clear komodo_state* // attempt to read the file komodo_state* state = komodo_stateptrget((char*)symbol); - EXPECT_NE(state, nullptr); + ASSERT_TRUE(state != nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file // NOTE: B records are not read in. Unsure if this is on purpose or an oversight @@ -452,24 +603,14 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_EQ(ev->height, 1); EXPECT_EQ(ev->type, 'B'); */ + ASSERT_TRUE(state->events.size() == 0); // 'B' not read // check that the new way is the same - EXPECT_EQ(state->events.size(), 7); - /* - auto itr = state->events.begin(); - std::advance(itr, 6); - std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); - EXPECT_NE(ev2, nullptr); - EXPECT_EQ(ev2->height, 1); - EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_REWIND); - // the serialized version should match the input - EXPECT_TRUE(compare_serialization(full_filename, ev2)); - */ } // all together in 1 file { const std::string full_filename = (temp / "combined_state.tmp").string(); std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); - EXPECT_NE(fp, nullptr); + ASSERT_TRUE(fp != nullptr); write_p_record(fp); write_n_record(fp); write_m_record(fp); @@ -479,9 +620,10 @@ TEST(TestEvents, komodo_faststateinit_test) write_r_record(fp); write_v_record(fp); std::fclose(fp); + clear_state(symbol); // clear komodo_state* // attempt to read the file komodo_state* state = komodo_stateptrget((char*)symbol); - EXPECT_NE(state, nullptr); + ASSERT_TRUE(state != nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit( state, full_filename.c_str(), symbol, dest); @@ -493,43 +635,45 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_EQ(ev1->height, 1); EXPECT_EQ(ev1->type, 'P'); */ + ASSERT_TRUE(state->events.size() != 0); // prevent test crash + // check that the new way is the same - EXPECT_EQ(state->events.size(), 14); + EXPECT_EQ(state->events.size(), 7); // 7 is because u-record is not read auto itr = state->events.begin(); - std::advance(itr, 7); + std::advance(itr, 0); { - EXPECT_EQ( (*itr)->height, 1); - EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_PUBKEYS); + EXPECT_EQ( (**itr).height, 10); + EXPECT_EQ( (**itr).type, komodo::komodo_event_type::EVENT_PUBKEYS); itr++; } { - EXPECT_EQ( (*itr)->height, 1); - EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_NOTARIZED); + EXPECT_EQ( (**itr).height, 10); + EXPECT_EQ( (**itr).type, komodo::komodo_event_type::EVENT_NOTARIZED); itr++; } { - EXPECT_EQ( (*itr)->height, 1); - EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_NOTARIZED); + EXPECT_EQ( (**itr).height, 10); + EXPECT_EQ( (**itr).type, komodo::komodo_event_type::EVENT_NOTARIZED); itr++; } { - EXPECT_EQ( (*itr)->height, 1); - EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + EXPECT_EQ( (**itr).height, 10); + EXPECT_EQ( (**itr).type, komodo::komodo_event_type::EVENT_KMDHEIGHT); itr++; } { - EXPECT_EQ( (*itr)->height, 1); - EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + EXPECT_EQ( (**itr).height, 10); + EXPECT_EQ( (**itr).type, komodo::komodo_event_type::EVENT_KMDHEIGHT); itr++; } { - EXPECT_EQ( (*itr)->height, 1); - EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_OPRETURN); + EXPECT_EQ( (**itr).height, 10); + EXPECT_EQ( (**itr).type, komodo::komodo_event_type::EVENT_OPRETURN); itr++; } { - EXPECT_EQ( (*itr)->height, 1); - EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_PRICEFEED); + EXPECT_EQ( (**itr).height, 10); + EXPECT_EQ( (**itr).type, komodo::komodo_event_type::EVENT_PRICEFEED); itr++; } } @@ -541,15 +685,19 @@ TEST(TestEvents, komodo_faststateinit_test) boost::filesystem::remove_all(temp); } -TEST(TestEvents, komodo_faststateinit_test_kmd) +// same test for KMD +TEST(test_events, komodo_faststateinit_test_kmd) { // Nothing should be added to events if this is the komodo chain char symbol[] = "KMD"; - ASSETCHAINS_SYMBOL[0] = 0; + chainName = assetchain(); KOMODO_EXTERNAL_NOTARIES = 0; + IS_KOMODO_NOTARY = false; // avoid calling komodo_verifynotarization + + clear_state(symbol); - boost::filesystem::path temp = boost::filesystem::unique_path(); + boost::filesystem::path temp = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); boost::filesystem::create_directories(temp); try { @@ -561,15 +709,16 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) // create a binary file that should be readable by komodo const std::string full_filename = (temp / "kstate.tmp").string(); std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); - EXPECT_NE(fp, nullptr); + ASSERT_TRUE(fp != nullptr); write_p_record(fp); std::fclose(fp); // verify file still exists EXPECT_TRUE(boost::filesystem::exists(full_filename)); + clear_state(symbol); // clear komodo_state* // attempt to read the file komodo_state* state = komodo_stateptrget((char*)symbol); - EXPECT_NE(state, nullptr); - char* dest = nullptr; + ASSERT_TRUE(state != nullptr); + char* dest = nullptr; // not used for 'P' // attempt to read the file int32_t result = komodo_faststateinit( state, full_filename.c_str(), symbol, dest); // compare results @@ -580,52 +729,61 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) { const std::string full_filename = (temp / "notarized.tmp").string(); std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); - EXPECT_NE(fp, nullptr); + ASSERT_TRUE(fp != nullptr); write_n_record(fp); std::fclose(fp); // verify file still exists EXPECT_TRUE(boost::filesystem::exists(full_filename)); + clear_state(symbol); // clear komodo_state* // attempt to read the file komodo_state* state = komodo_stateptrget((char*)symbol); - EXPECT_NE(state, nullptr); + ASSERT_TRUE(state != nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit( state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); - EXPECT_EQ(state->events.size(), 0); + EXPECT_EQ(state->events.size(), 0); // events is empty for KMD + EXPECT_EQ(state->LastNotarizedHeight(), 2); + EXPECT_EQ(state->LastNotarizedHash(), uint256S("0101010101010101010101010101010101010101010101010101010101010101")); } // notarized M record { const std::string full_filename = (temp / "notarized.tmp").string(); std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); - EXPECT_NE(fp, nullptr); + ASSERT_TRUE(fp != nullptr); write_m_record(fp); std::fclose(fp); // verify file still exists EXPECT_TRUE(boost::filesystem::exists(full_filename)); + clear_state(symbol); // clear komodo_state* // attempt to read the file komodo_state* state = komodo_stateptrget((char*)symbol); - EXPECT_NE(state, nullptr); + ASSERT_TRUE(state != nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); EXPECT_EQ(state->events.size(), 0); + + // check last nota: + EXPECT_EQ(state->LastNotarizedHeight(), 3); + EXPECT_EQ(state->LastNotarizedHash(), uint256S("0101010101010101010101010101010101010101010101010101010101010101")); } // record type "U" (deprecated) { const std::string full_filename = (temp / "type_u.tmp").string(); std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); - EXPECT_NE(fp, nullptr); + ASSERT_TRUE(fp != nullptr); write_u_record(fp); std::fclose(fp); // verify file still exists EXPECT_TRUE(boost::filesystem::exists(full_filename)); + clear_state(symbol); // clear komodo_state* // attempt to read the file komodo_state* state = komodo_stateptrget((char*)symbol); - EXPECT_NE(state, nullptr); + ASSERT_TRUE(state != nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); @@ -637,14 +795,15 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) { const std::string full_filename = (temp / "kmdtype.tmp").string(); std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); - EXPECT_NE(fp, nullptr); + ASSERT_TRUE(fp != nullptr); write_k_record(fp); std::fclose(fp); // verify file still exists EXPECT_TRUE(boost::filesystem::exists(full_filename)); + clear_state(symbol); // clear komodo_state* // attempt to read the file komodo_state* state = komodo_stateptrget((char*)symbol); - EXPECT_NE(state, nullptr); + ASSERT_TRUE(state != nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); @@ -656,14 +815,15 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) { const std::string full_filename = (temp / "kmdtypet.tmp").string(); std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); - EXPECT_NE(fp, nullptr); + ASSERT_TRUE(fp != nullptr); write_t_record(fp); std::fclose(fp); // verify file still exists EXPECT_TRUE(boost::filesystem::exists(full_filename)); + clear_state(symbol); // clear komodo_state* // attempt to read the file komodo_state* state = komodo_stateptrget((char*)symbol); - EXPECT_NE(state, nullptr); + ASSERT_TRUE(state != nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); @@ -675,14 +835,15 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) { const std::string full_filename = (temp / "kmdtypet.tmp").string(); std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); - EXPECT_NE(fp, nullptr); + ASSERT_TRUE(fp != nullptr); write_r_record(fp); std::fclose(fp); // verify file still exists EXPECT_TRUE(boost::filesystem::exists(full_filename)); + clear_state(symbol); // clear komodo_state* // attempt to read the file komodo_state* state = komodo_stateptrget((char*)symbol); - EXPECT_NE(state, nullptr); + ASSERT_TRUE(state != nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); @@ -694,14 +855,15 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) { const std::string full_filename = (temp / "kmdtypet.tmp").string(); std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); - EXPECT_NE(fp, nullptr); + ASSERT_TRUE(fp != nullptr); write_v_record(fp); std::fclose(fp); // verify file still exists EXPECT_TRUE(boost::filesystem::exists(full_filename)); + clear_state(symbol); // clear komodo_state* // attempt to read the file komodo_state* state = komodo_stateptrget((char*)symbol); - EXPECT_NE(state, nullptr); + ASSERT_TRUE(state != nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); @@ -713,14 +875,15 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) { const std::string full_filename = (temp / "kmdtypeb.tmp").string(); std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); - EXPECT_NE(fp, nullptr); + ASSERT_TRUE(fp != nullptr); write_b_record(fp); std::fclose(fp); // verify file still exists EXPECT_TRUE(boost::filesystem::exists(full_filename)); + clear_state(symbol); // clear komodo_state* // attempt to read the file komodo_state* state = komodo_stateptrget((char*)symbol); - EXPECT_NE(state, nullptr); + ASSERT_TRUE(state != nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file // NOTE: B records are not read in. Unsure if this is on purpose or an oversight @@ -733,7 +896,7 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) { const std::string full_filename = (temp / "combined_state.tmp").string(); std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); - EXPECT_NE(fp, nullptr); + ASSERT_TRUE(fp != nullptr); write_p_record(fp); write_n_record(fp); write_m_record(fp); @@ -743,9 +906,10 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) write_r_record(fp); write_v_record(fp); std::fclose(fp); + clear_state(symbol); // clear komodo_state* // attempt to read the file komodo_state* state = komodo_stateptrget((char*)symbol); - EXPECT_NE(state, nullptr); + ASSERT_TRUE(state != nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit( state, full_filename.c_str(), symbol, dest); @@ -761,4 +925,139 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) boost::filesystem::remove_all(temp); } -} // namespace TestEvents \ No newline at end of file +TEST(test_events, DISABLED_write_test) // test from dev branch from S6 season +{ + char symbol[] = "TST"; + chainName = assetchain(symbol); + KOMODO_EXTERNAL_NOTARIES = 1; + + clear_state(symbol); + + boost::filesystem::path temp = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + boost::filesystem::create_directories(temp); + + const std::string full_filename = (temp / "kstate.tmp").string(); + const std::string full_filename2 = (temp / "kstate2.tmp").string(); + try + { + { + // old way + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + ASSERT_TRUE(fp != nullptr); + write_p_record(fp); + std::fclose(fp); + // verify files still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + clear_state(symbol); // clear komodo_state* + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + ASSERT_TRUE(state != nullptr); + char* dest = nullptr; + int32_t result = komodo_faststateinit( state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + ASSERT_TRUE(state->events.size() != 0); // prevent test crash + // check that the new way is the same + EXPECT_EQ(state->events.size(), 1); + komodo::event_pubkeys& ev = static_cast( *state->events.front() ); + EXPECT_EQ(ev.height, 10); + EXPECT_EQ(ev.type, komodo::komodo_event_type::EVENT_PUBKEYS); + std::fclose(fp); + // verify files still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + } + } + catch(...) + { + FAIL() << "Exception thrown"; + } + boost::filesystem::remove_all(temp); +} + +TEST(test_events, write_test_event_fix3) // same test from jmj_event_fix3 +{ + // test serialization of the different event records + char symbol[] = "TST"; + chainName = assetchain(symbol); + KOMODO_EXTERNAL_NOTARIES = 1; + + clear_state(symbol); + + boost::filesystem::path temp = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + boost::filesystem::create_directories(temp); + + const std::string full_filename = (temp / "kstate.tmp").string(); + const std::string full_filename2 = (temp / "kstate2.tmp").string(); + try + { + { + // old way + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + ASSERT_TRUE(fp != nullptr); + write_b_record(fp); + write_k_record(fp); + write_m_record(fp); + write_n_record(fp); + write_p_record(fp); + write_r_record(fp); + write_t_record(fp); + write_u_record(fp); + write_v_record(fp); + std::fclose(fp); + // verify files still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + } + { + // new way + std::FILE* fp = std::fopen(full_filename2.c_str(), "wb+"); + ASSERT_TRUE(fp != nullptr); + write_b_record_new(fp); + write_k_record_new(fp); + write_m_record_new(fp); + write_n_record_new(fp); + write_p_record_new(fp); + write_r_record_new(fp); + write_t_record_new(fp); + write_u_record_new(fp); + write_v_record_new(fp); + std::fclose(fp); + EXPECT_TRUE(boost::filesystem::exists(full_filename2)); + // the two files should be binarily equal + EXPECT_TRUE( compare_files(full_filename, full_filename2) ); + } + } + catch(...) + { + FAIL() << "Exception thrown"; + } + boost::filesystem::remove_all(temp); + //std::cout << full_filename << " " << full_filename2 << "\n"; +} + + +TEST(test_events, event_copy) +{ + // make an object + komodo::event_pubkeys pk1(1); + pk1.num = 2; + memset(pk1.pubkeys[0], 1, 33); + memset(pk1.pubkeys[1], 2, 33); + // make a copy + std::vector> events; + events.push_back( std::make_shared(pk1) ); + komodo::event_pubkeys& pk2 = static_cast(*events.front()); + // are they equal? + EXPECT_EQ(pk1.height, pk2.height); + EXPECT_EQ(pk1.num, pk2.num); + for(uint8_t i = 0; i < pk1.num; ++i) + { + for(uint8_t j = 0; j < 33; ++j) + { + if (pk1.pubkeys[i][j] != pk2.pubkeys[i][j]) + FAIL() << "Error at " << (int)i << " " << (int)j; + } + } + +} + +} // namespace test_events \ No newline at end of file diff --git a/src/test-komodo/test_haraka_removal.cpp b/src/test-komodo/test_haraka_removal.cpp index f4eda4239d0..701637f1ffc 100644 --- a/src/test-komodo/test_haraka_removal.cpp +++ b/src/test-komodo/test_haraka_removal.cpp @@ -10,7 +10,10 @@ #include "main.h" #include "komodo_utils.h" -#include "komodo_extern_globals.h" +#include "komodo_globals.h" + +extern uint64_t ASSETCHAINS_TIMEUNLOCKFROM; +extern uint64_t ASSETCHAINS_TIMEUNLOCKTO; // ./komodo-test --gtest_filter=TestHarakaRemoval.* namespace TestHarakaRemoval { @@ -19,7 +22,7 @@ namespace TestHarakaRemoval { CChain chainActive; CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - TEST(TestHarakaRemoval, test_block_ser) + TEST(TestHarakaRemoval, DISABLED_test_block_ser) // disabled due to changed protocol version. We do not want to update it each time { // this test should cover genesis block (de)serialization before // and after applying haraka removal PR @@ -52,18 +55,18 @@ namespace TestHarakaRemoval { EXPECT_TRUE(chainActive.Contains(&fakeIndex)); EXPECT_EQ(0, chainActive.Height()); - CDiskBlockIndex diskindex {&fakeIndex}; + CDiskBlockIndex diskindex(&fakeIndex, [](){ return std::vector(); }); ss.clear(); ss << diskindex; - // VARINT(PROTOCOL_VERSION) - 89af1a - static constexpr const char* stream_genesis_block_diskindex_hex = "89af1a00000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2"; + // VARINT(PROTOCOL_VERSION==170010) - 89af1b + static constexpr const char* stream_genesis_block_diskindex_hex = "89af1b00000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2"; EXPECT_EQ(HexStr(ss), stream_genesis_block_diskindex_hex); } //#define PRG_VALUES_BEFORE_PR 1 TEST(TestHarakaRemoval, test_block_prg) { - EXPECT_EQ(ASSETCHAINS_SYMBOL[0], 0); + chainName = assetchain(); //EXPECT_EQ(ASSETCHAINS_SYMBOL[0], 0); // ASSETCHAINS_TIMEUNLOCKFROM = GetArg("-ac_timeunlockfrom", 0) -> 129600 ASSETCHAINS_TIMEUNLOCKFROM = 129600; diff --git a/src/test-komodo/test_kmd_feat.cpp b/src/test-komodo/test_kmd_feat.cpp new file mode 100644 index 00000000000..7cee0a38140 --- /dev/null +++ b/src/test-komodo/test_kmd_feat.cpp @@ -0,0 +1,478 @@ +#include +#include + +#include "consensus/upgrades.h" +#include "consensus/validation.h" +#include "core_io.h" +#include "key_io.h" +#include "main.h" +#include "primitives/transaction.h" +#include "txmempool.h" +#include "policy/fees.h" +#include "util.h" +#include "univalue.h" + +#include "komodo_defs.h" +#include "komodo_globals.h" +#include "komodo_interest.h" +#include "cc/CCinclude.h" +#include "komodo_hardfork.h" + + +CCriticalSection& get_cs_main(); // in main.cpp + +const int komodo_interest_height = 247205+1; +const std::string testwif("Usr24VoC3h4cSfSrFiGJkWLYwmkM1VnsBiMyWZvrF6QR5ZQ6Fbuu"); +const std::string testpk("034b082c5819b5bf8798a387630ad236a8e800dbce4c4e24a46f36dfddab3cbff5"); +const std::string testaddr("RXTUtWXgkepi8f2ohWLL9KhtGKRjBV48hT"); + +// Fake the input of transaction mtx0/0 +class FakeCoinsViewDB2 : public CCoinsView { // change name to FakeCoinsViewDB2 to avoid name conflict with same class name in different files (seems a bug in macos gcc) +public: + FakeCoinsViewDB2() { + // allowed mtx0 txids + sAllowedTxIn.insert(uint256S("c8ff545cdc5e921cdbbd24555a462340fc1092e09977944ec687c5bf3ef9c30b")); // 10 * COIN, nLockTime = 0 + sAllowedTxIn.insert(uint256S("529d8dcec041465fdf6c1f873ef1055eec106db5f02ae222814d3764bb8e6660")); // 10 * COIN, nLockTime = 1663755146 + sAllowedTxIn.insert(uint256S("3533600e69a22776afb765305a0ec46bcb06e1942f36a113d73733190092f9d5")); // 10 * COIN, nLockTime = 1663755147 + } + + bool GetCoins(const uint256 &txid, CCoins &coins) const { + if (sAllowedTxIn.count(txid)) { + CTxOut txOut; + txOut.nValue = 10 * COIN; + txOut.scriptPubKey = GetScriptForDestination(DecodeDestination(testaddr)); + CCoins newCoins; + newCoins.vout.resize(1); + newCoins.vout[0] = txOut; + newCoins.nHeight = komodo_interest_height-1; /* TODO: return correct nHeight depends on txid */ + coins.swap(newCoins); + return true; + } + return false; + } + + bool HaveCoins(const uint256 &txid) const { + if (sAllowedTxIn.count(txid)) + return true; + return false; + } + + uint256 GetBestBlock() const override + { + return bestBlockHash; + } + + bool BatchWrite(CCoinsMap &mapCoins, + const uint256 &hashBlock, + const uint256 &hashSproutAnchor, + const uint256 &hashSaplingAnchor, + CAnchorsSproutMap &mapSproutAnchors, + CAnchorsSaplingMap &mapSaplingAnchors, + CNullifiersMap &mapSproutNullifiers, + CNullifiersMap &mapSaplingNullifiers) { + return false; + } + + bool GetStats(CCoinsStats &stats) const { + return false; + } + + uint256 bestBlockHash; + std::set sAllowedTxIn; +}; + +bool TestSignTx(const CKeyStore& keystore, CMutableTransaction& mtx, int32_t vini, CAmount utxovalue, const CScript scriptPubKey) +{ + CTransaction txNewConst(mtx); + SignatureData sigdata; + auto consensusBranchId = CurrentEpochBranchId(chainActive.Height()+1, Params().GetConsensus()); + if (ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, vini, utxovalue, SIGHASH_ALL), scriptPubKey, sigdata, consensusBranchId) != 0) { + UpdateTransaction(mtx, vini, sigdata); + return true; + } else { + std::cerr << __func__ << " signing error for vini=" << vini << " amount=" << utxovalue << std::endl; + return false; + } +} + + +class KomodoFeatures : public ::testing::Test { +protected: + virtual void SetUp() { + SelectParams(CBaseChainParams::MAIN); + fPrintToConsoleOld = fPrintToConsole; + fPrintToConsole = true; // TODO save and restore + + chainName = assetchain(); // ensure KMD + + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); + KOMODO_REWIND = 0; + chainActive.SetTip(nullptr); + } + + virtual void TearDown() { + // Revert to test default. No-op on mainnet params. + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); + fPrintToConsole = fPrintToConsoleOld; + } + bool fPrintToConsoleOld; +}; + +// some komodo consensus extensions +TEST_F(KomodoFeatures, komodo_interest_validate) { + + // Add a fake transaction to the wallet + CMutableTransaction mtx0 = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_interest_height-1); + CScript scriptPubKey = GetScriptForDestination(DecodeDestination(testaddr)); + mtx0.vout.push_back(CTxOut(10 * COIN, scriptPubKey)); + mtx0.nLockTime = 1663755146; + + // Fake-mine the transaction + ASSERT_EQ(-1, chainActive.Height()); + CBlock block; + //block.hashPrevBlock = chainActive.Tip()->GetBlockHash(); + block.vtx.push_back(mtx0); + block.hashMerkleRoot = block.BuildMerkleTree(); + auto blockHash = block.GetHash(); + CBlockIndex *pfakeIndex = new CBlockIndex(block); // TODO: change back to auto if index is not cleaned + pfakeIndex->pprev = nullptr; + pfakeIndex->nHeight = komodo_interest_height-1; + pfakeIndex->nTime = 1663755146; + mapBlockIndex.insert(std::make_pair(blockHash, pfakeIndex)); + chainActive.SetTip(pfakeIndex); + EXPECT_TRUE(chainActive.Contains(pfakeIndex)); + EXPECT_EQ(komodo_interest_height-1, chainActive.Height()); + + FakeCoinsViewDB2 fakedb; + fakedb.bestBlockHash = blockHash; + CCoinsViewCache fakeview(&fakedb); + pcoinsTip = &fakeview; + + //std::cerr << " mtx0.GetHash()=" << mtx0.GetHash().GetHex() << std::endl; + EXPECT_NE(fakedb.sAllowedTxIn.count(mtx0.GetHash()), 0); + + CTxMemPool pool(::minRelayTxFee); + bool missingInputs; + CMutableTransaction mtxSpend = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_interest_height); + mtxSpend.vin.push_back(CTxIn(mtx0.GetHash(), 0)); + CScript scriptPubKey1 = GetScriptForDestination(DecodeDestination(testaddr)); + mtxSpend.vout.push_back(CTxOut(10 * COIN, scriptPubKey1)); + + CBasicKeyStore tempKeystore; + CKey key = DecodeSecret(testwif); + tempKeystore.AddKey(key); + + // create coinbase + CMutableTransaction txcb = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_interest_height); + txcb.vin.resize(1); + txcb.vin[0].prevout.SetNull(); + txcb.vin[0].scriptSig = (CScript() << komodo_interest_height << CScriptNum(1)) + COINBASE_FLAGS; + txcb.vout.resize(1); + txcb.vout[0].scriptPubKey = GetScriptForDestination(DecodeDestination(testaddr));; + txcb.vout[0].nValue = GetBlockSubsidy(komodo_interest_height, Params().GetConsensus()) + 0; + txcb.nExpiryHeight = 0; + txcb.nLockTime = pfakeIndex->GetMedianTimePast()+1; + + { + // check invalid interest in mempool + + mtxSpend.nLockTime = chainActive.Tip()->GetMedianTimePast() + 777 - 3600 - 1; // too long time to add into mempool (prevent incorrect interest) + EXPECT_TRUE(TestSignTx(tempKeystore, mtxSpend, 0, mtx0.vout[0].nValue, mtx0.vout[0].scriptPubKey)); + + CValidationState state1; + CTransaction tx1(mtxSpend); + + LOCK( get_cs_main() ); + EXPECT_FALSE(AcceptToMemoryPool(pool, state1, tx1, false, &missingInputs)); + EXPECT_EQ(state1.GetRejectReason(), "komodo-interest-invalid"); + } + { + // check invalid interest in block + + CBlock block; + block.vtx.push_back(txcb); + + mtxSpend.nLockTime = chainActive.Tip()->GetMedianTimePast() - 3600 - 1; // too long time staying in mempool (a bit longer than when adding ) + mtxSpend.vin[0].scriptSig.clear(); + EXPECT_TRUE(TestSignTx(tempKeystore, mtxSpend, 0, mtx0.vout[0].nValue, mtx0.vout[0].scriptPubKey)); + CTransaction tx1(mtxSpend); + block.vtx.push_back(tx1); + + block.nTime = pfakeIndex->GetMedianTimePast(); + + CValidationState state1; + EXPECT_FALSE(ContextualCheckBlock(false, block, state1, pfakeIndex)); + EXPECT_EQ(state1.GetRejectReason(), "komodo-interest-invalid"); + } + { + // check valid interest in mempool + + mtxSpend.nLockTime = chainActive.Tip()->GetMedianTimePast() + 777 - 3600; // not too long time to add into mempool + EXPECT_TRUE(TestSignTx(tempKeystore, mtxSpend, 0, mtx0.vout[0].nValue, mtx0.vout[0].scriptPubKey)); + + CValidationState state1; + CTransaction tx1(mtxSpend); + + LOCK( get_cs_main() ); + EXPECT_TRUE(AcceptToMemoryPool(pool, state1, tx1, false, &missingInputs)); + } + + { + // check valid interest in block + mtxSpend.nLockTime = chainActive.Tip()->GetMedianTimePast() - 3600; // not too long time in mempool + mtxSpend.vin[0].scriptSig.clear(); + EXPECT_TRUE(TestSignTx(tempKeystore, mtxSpend, 0, mtx0.vout[0].nValue, mtx0.vout[0].scriptPubKey)); + + CBlock block; + block.vtx.push_back(txcb); + CTransaction tx1(mtxSpend); + block.vtx.push_back(tx1); + block.nTime = pfakeIndex->GetMedianTimePast(); + + CValidationState state1; + EXPECT_TRUE(ContextualCheckBlock(false, block, state1, pfakeIndex)); + } + + { + // test interest calculations via CCoinsViewCache::GetValueIn + + const uint32_t tipTimes[] = { + 1663755146, + 1663762346, // chainActive.Tip()->GetMedianTimePast() + 2 * 3600 (MTP from 1663755146 + 2 * 3600) + 1663762346 + 31 * 24 * 60 * 60, /* month */ + 1663762346 + 6 * 30 * 24 * 60 * 60, /* half of a year */ + 1663762346 + 12 * 30 * 24 * 60 * 60, /* year (360 days) */ + 1663762346 + 365 * 24 * 60 * 60, /* year (365 days) */ + }; + + /* komodo_interest_height = 247205+1 */ + const CAmount interestCollectedBefore250k[] = {0, 11415, 4545454, 25000000, 50000000, 50000000}; + /* komodo_interest_height = 333332 */ + const CAmount interestCollectedBefore1M[] = {0, 5802, 4252378, 24663337, 49320871, 49994387}; + /* komodo_interest_height = 3000000 */ + const CAmount interestCollected[] = {0, 5795, 4235195, 4235195, 4235195, 4235195}; + /* komodo_interest_height = 7113400 */ + const CAmount interestCollectedAfterS7[] = {0, 5795 / 500, 4235195 / 500, 4235195 / 500, 4235195 / 500, 4235195 / 500}; + + /* check collected interest */ + + const size_t nMaxTipTimes = sizeof(tipTimes) / sizeof(tipTimes[0]); + const size_t nMaxInterestCollected = sizeof(interestCollected) / sizeof(interestCollected[0]); + assert(nMaxTipTimes == nMaxInterestCollected); + + const int testHeights[] = { + 247205 + 1, 333332, 3000000, nS7HardforkHeight + 1}; + + CValidationState state; + + for (size_t idx_ht = 0; idx_ht < sizeof(testHeights) / sizeof(testHeights[0]); ++idx_ht) + { + + pfakeIndex->nHeight = testHeights[idx_ht] - 1; + mtx0.nLockTime = 1663755146; + mtxSpend.vin[0] = CTxIn(mtx0.GetHash(), 0); + + for (size_t idx = 0; idx < nMaxTipTimes; ++idx) + { + // make fake last block + CBlock lastBlock; + lastBlock.nTime = tipTimes[idx]; + + CBlockIndex *pLastBlockIndex = new CBlockIndex(block); + pLastBlockIndex->pprev = pfakeIndex; + pLastBlockIndex->nHeight = testHeights[idx_ht]; + pLastBlockIndex->nTime = lastBlock.nTime; + chainActive.SetTip(pLastBlockIndex); + + mtxSpend.nLockTime = lastBlock.nTime; + mtxSpend.vin[0].scriptSig.clear(); + EXPECT_TRUE(TestSignTx(tempKeystore, mtxSpend, 0, mtx0.vout[0].nValue, mtx0.vout[0].scriptPubKey)); + CTransaction tx1(mtxSpend); + + mempool.clear(); + mapBlockIndex.clear(); + + // put tx which we trying to spend into mempool, + // bcz CCoinsViewCache::GetValueIn will call komodo_accrued_interest + // -> komodo_interest_args -> GetTransaction + + auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); + SetMockTime(mtxSpend.nLockTime); + CTxMemPoolEntry entry(mtx0, 0, GetTime(), 0, chainActive.Height(), mempool.HasNoInputsOf(mtx0), false, consensusBranchId); + mempool.addUnchecked(mtx0.GetHash(), entry, false); + + EXPECT_TRUE(mempool.exists(mtx0.GetHash())); + + // force komodo_getblockindex in komodo_interest_args return a value + uint256 zero; + zero.SetNull(); + mapBlockIndex.insert(std::make_pair(zero, pfakeIndex)); + + fakeview.GetBestBlock(); // bring the best block into scope + EXPECT_EQ(chainActive.Tip()->nHeight, testHeights[idx_ht]); + CAmount interest = 0; + CAmount nValueIn = fakeview.GetValueIn(chainActive.Tip()->nHeight, interest, tx1); + + switch (testHeights[idx_ht]) + { + case 247205 + 1: + ASSERT_EQ(interest, interestCollectedBefore250k[idx]); + break; + case 333332: + ASSERT_EQ(interest, interestCollectedBefore1M[idx]); + break; + case 3000000: + ASSERT_EQ(interest, interestCollected[idx]); + break; + default: + ASSERT_EQ(interest, interestCollectedAfterS7[idx]); + break; + } + + delete pLastBlockIndex; + } + } + } +} + +// check komodo_interestnew calculations +TEST_F(KomodoFeatures, komodo_interestnew) { + + // some not working values + EXPECT_EQ(komodo_interestnew(1, 1000LL, 1, 1), 0LL); + // time lower than cut off month time limit + EXPECT_EQ(komodo_interestnew(1000000, 10LL*COIN, 1663839248, 1663839248 + (31 * 24 * 60 - 1) * 60 + 3600 /*KOMODO_MAXMEMPOOLTIME*/), 10LL*COIN/10512000 * (31*24*60 - 59)); + + // since 7th season, according to KIP0001 AUR should be reduced from 5% to 0.01%, i.e. div by 500 + EXPECT_EQ(komodo_interestnew(7777777-1, 10LL*COIN, 1663839248, 1663839248 + (31 * 24 * 60 - 1) * 60 + 3600), 10LL*COIN/10512000 * (31*24*60 - 59) / 500); + // end of interest era + EXPECT_EQ(komodo_interestnew(7777777, 10LL*COIN, 1663839248, 1663839248 + (31 * 24 * 60 - 1) * 60 + 3600), 0LL); + + // value less than limit + EXPECT_EQ(komodo_interestnew(1000000, 10LL*COIN-1, 1663839248, 1663839248 + (31 * 24 * 60 - 1) * 60 + 3600), 0); + // tip less than nLockTime + EXPECT_EQ(komodo_interestnew(1000000, 10LL*COIN-1, 1663839248, 1663839248 - 1), 0); + // not timestamp value + EXPECT_EQ(komodo_interestnew(1000000, 10LL*COIN-1, 400000000U, 400000000U + 30 * 24 * 60 * 60 + 3600), 0); + + // too small period + EXPECT_EQ(komodo_interestnew(1000000, 10LL*COIN, 1663839248, 1663839248 + 3600 - 1), 0); + // time over cut off month time limit + EXPECT_EQ(komodo_interestnew(1000000, 10LL*COIN, 1663839248, 1663839248 + 31 * 24 * 60 * 60 + 3600+1), 10LL*COIN/10512000 * (31*24*60 - 59)); + EXPECT_EQ(komodo_interestnew(1000000, 10LL*COIN, 1663839248, 1663839248 + 32 * 24 * 60 * 60 + 3600), 10LL*COIN/10512000 * (31*24*60 - 59)); + + // time close to cut off year time limit + EXPECT_EQ(komodo_interestnew(1000000-1, 10LL*COIN, 1663839248, 1663839248 + (365 * 24 * 60 - 1) * 60 + 3600), 10LL*COIN/10512000 * (365*24*60 - 59)); + // time over cut off year time limit + EXPECT_EQ(komodo_interestnew(1000000-1, 10LL*COIN, 1663839248, 1663839248 + (365 * 24 * 60 - 1) * 60 + 3600 + 60), 10LL*COIN/10512000 * (365*24*60 - 59)); + EXPECT_EQ(komodo_interestnew(1000000-1, 10LL*COIN, 1663839248, 1663839248 + (365 * 24 * 60 - 1) * 60 + 3600 + 30 * 24 * 60), 10LL*COIN/10512000 * (365*24*60 - 59)); +} + +// check komodo_interest calculations +TEST_F(KomodoFeatures, komodo_interest) { + + const uint32_t activation = 1491350400; // 1491350400 5th April + + { + // some not working values should produce 0LL + EXPECT_EQ(komodo_interest(1, 1000LL, 1, 1), 0LL); + } + { + // nValue <= 25000LL*COIN and nValue >= 25000LL*COIN + // txheight >= 1000000 + // should be routed to komodo_interestnew + + for (CAmount nValue : { 10LL*COIN, 25001LL*COIN }) + { + // time lower than cut off month time limit + EXPECT_EQ(komodo_interest(1000000, nValue, 1663839248, 1663839248 + (31 * 24 * 60 - 1) * 60 + 3600), nValue/10512000 * (31*24*60 - 59)); + + // since 7th season, according to KIP0001 AUR should be reduced from 5% to 0.01%, i.e. div by 500 + EXPECT_EQ(komodo_interest(7777777-1, nValue, 1663839248, 1663839248 + (31 * 24 * 60 - 1) * 60 + 3600), nValue/10512000 * (31*24*60 - 59) / 500); + // end of interest era + EXPECT_EQ(komodo_interest(7777777 /*KOMODO_ENDOFERA*/, nValue, 1663839248, 1663839248 + (31 * 24 * 60 - 1) * 60 + 3600), 0LL); + + // tip less than nLockTime + EXPECT_EQ(komodo_interest(1000000, nValue-1, 1663839248, 1663839248 - 1), 0); + // not timestamp value + EXPECT_EQ(komodo_interest(1000000, nValue-1, 400000000U, 400000000U + 30 * 24 * 60 * 60 + 3600), 0); + + // too small period + EXPECT_EQ(komodo_interest(1000000, nValue, 1663839248, 1663839248 + 3600 - 1), 0); + // time over cut off month time limit + EXPECT_EQ(komodo_interest(1000000, nValue, 1663839248, 1663839248 + 31 * 24 * 60 * 60 + 3600+1), nValue/10512000 * (31*24*60 - 59)); + EXPECT_EQ(komodo_interest(1000000, nValue, 1663839248, 1663839248 + 32 * 24 * 60 * 60 + 3600), nValue/10512000 * (31*24*60 - 59)); + } + // value less than limit + EXPECT_EQ(komodo_interest(1000000, 10LL*COIN-1, 1663839248, 1663839248 + (31 * 24 * 60 - 1) * 60 + 3600), 0); + } + + for (auto days : { 1, 10, 365, 365*2, 365*3 }) + { + std::cerr << "running komodo_interest test for days=" << days << "..." << std::endl; + int32_t minutes = days * 24 * 60; + if (minutes > 365 * 24 * 60) + minutes = 365 * 24 * 60; + { + // nValue <= 25000LL*COIN + // txheight < 1000000 + + uint64_t numerator = (10LL*COIN / 20); // assumes 5%! + EXPECT_EQ(komodo_interest(1000000-1, 10LL*COIN, 1663839248, 1663839248 + minutes * 60), numerator * (minutes - 59) / (365ULL * 24 * 60)); + } + { + // nValue <= 25000LL*COIN + // txheight < 250000 + + uint64_t numerator = (10LL*COIN * 5000000 /*KOMODO_INTEREST*/); + uint32_t locktime = activation - 2 * days * 24 * 60 * 60; + uint32_t tiptime = locktime + minutes * 60; + ASSERT_TRUE(tiptime < activation); + uint64_t denominator = (365LL * 24 * 60) / minutes; + denominator = (denominator == 0LL) ? 1LL : denominator; + EXPECT_EQ(komodo_interest(250000-1, 10LL*COIN, locktime, tiptime), numerator / denominator / COIN); + } + { + // !exception + // nValue > 25000LL*COIN + // txheight < 250000 + + uint64_t numerator = (25000LL*COIN+1) / 20; // assumes 5%! + uint64_t denominator = (365LL * 24 * 60) / minutes; // no minutes-59 adjustment + denominator = (denominator == 0LL) ? 1LL : denominator; + EXPECT_EQ(komodo_interest(250000-1, 25000LL*COIN+1, 1663839248, 1663839248 + minutes * 60), numerator / denominator); + } + { + // !exception + // nValue > 25000LL*COIN + // txheight < 1000000 + + uint64_t numerator = (25000LL*COIN+1) / 20; // assumes 5%! + int32_t minutes_adj = minutes - 59; // adjusted since ht=250000 + EXPECT_EQ(komodo_interest(1000000-1, 25000LL*COIN+1, 1663839248, 1663839248 + minutes * 60), numerator * minutes_adj / (365LL * 24 * 60)); + } + { + // exception + // nValue > 25000LL*COIN + // txheight < 1000000 + + for (const auto htval : std::vector>{ {116607, 2502721100000LL}, {126891, 2879650000000LL}, {129510, 3000000000000LL}, {141549, 3500000000000LL}, {154473, 3983399350000LL}, {154736, 3983406748175LL}, {155013, 3983414006565LL}, {155492, 3983427592291LL}, {155613, 9997409999999797LL}, {157927, 9997410667451072LL}, {155613, 2590000000000LL}, {155949, 4000000000000LL} }) + { + int32_t txheight = htval.first; + CAmount nValue = htval.second; + uint64_t numerator = (static_cast(nValue) * 5000000 /*KOMODO_INTEREST*/); // NOTE: uint64_t (for CAmount it is an overflow here for some exceptions) + uint32_t locktime = 1484490069; // close to real tx locktime + // uint32_t locktime = 1663839248; + uint32_t tiptime = locktime + minutes * 60; + // uint32_t tiptime = 1663920715; // test writing time + // int32_t minutes = (tiptime - locktime) / 60; + uint64_t denominator = (365LL * 24 * 60) / minutes; + denominator = (denominator == 0LL) ? 1LL : denominator; + if (txheight < 155949) + EXPECT_EQ(komodo_interest(txheight, nValue, locktime, tiptime), numerator / denominator / COIN); + } + } + } +} diff --git a/src/gtest/test_mempool.cpp b/src/test-komodo/test_mempool.cpp similarity index 85% rename from src/gtest/test_mempool.cpp rename to src/test-komodo/test_mempool.cpp index 6ef626e5f90..e92fc092170 100644 --- a/src/gtest/test_mempool.cpp +++ b/src/test-komodo/test_mempool.cpp @@ -10,8 +10,53 @@ #include "policy/fees.h" #include "util.h" -// Implementation is in test_checktransaction.cpp -extern CMutableTransaction GetValidTransaction(); +void CreateJoinSplitSignature(CMutableTransaction& mtx, uint32_t consensusBranchId) { + // Generate an ephemeral keypair. + uint256 joinSplitPubKey; + unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES]; + crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey); + mtx.joinSplitPubKey = joinSplitPubKey; + + // Compute the correct hSig. + // TODO: #966. + static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); + // Empty output script. + CScript scriptCode; + CTransaction signTx(mtx); + uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId); + if (dataToBeSigned == one) { + throw std::runtime_error("SignatureHash failed"); + } + + // Add the signature + assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL, + dataToBeSigned.begin(), 32, + joinSplitPrivKey + ) == 0); +} + +CMutableTransaction GetValidTransaction() { + uint32_t consensusBranchId = SPROUT_BRANCH_ID; + + CMutableTransaction mtx; + mtx.vin.resize(2); + mtx.vin[0].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); + mtx.vin[0].prevout.n = 0; + mtx.vin[1].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000002"); + mtx.vin[1].prevout.n = 0; + mtx.vout.resize(2); + // mtx.vout[0].scriptPubKey = + mtx.vout[0].nValue = 0; + mtx.vout[1].nValue = 0; + mtx.vjoinsplit.resize(2); + mtx.vjoinsplit[0].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); + mtx.vjoinsplit[0].nullifiers.at(1) = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); + mtx.vjoinsplit[1].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000002"); + mtx.vjoinsplit[1].nullifiers.at(1) = uint256S("0000000000000000000000000000000000000000000000000000000000000003"); + + CreateJoinSplitSignature(mtx, consensusBranchId); + return mtx; +} // Fake the input of transaction 5295156213414ed77f6e538e7e8ebe14492156906b9fe995b242477818789364 // - 532639cc6bebed47c1c69ae36dd498c68a012e74ad12729adbd3dbb56f8f3f4a, 0 @@ -96,12 +141,14 @@ TEST(Mempool, PriorityStatsDoNotCrash) { CTxMemPoolEntry entry(tx, nFees, nTime, dPriority, nHeight, true, false, SPROUT_BRANCH_ID); - // Check it does not crash (ie. the death test fails) - EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(testPool.addUnchecked(tx.GetHash(), entry), ""), ""); + // This should not crash + EXPECT_TRUE(testPool.addUnchecked(tx.GetHash(), entry)); EXPECT_EQ(dPriority, MAX_PRIORITY); } +CCriticalSection& get_cs_main(); // in main.cpp + TEST(Mempool, TxInputLimit) { SelectParams(CBaseChainParams::REGTEST); @@ -119,6 +166,7 @@ TEST(Mempool, TxInputLimit) { // Check it fails as expected CValidationState state1; CTransaction tx1(mtx); + LOCK( get_cs_main() ); EXPECT_FALSE(AcceptToMemoryPool(pool, state1, tx1, false, &missingInputs)); EXPECT_EQ(state1.GetRejectReason(), "bad-txns-version-too-low"); @@ -182,6 +230,7 @@ TEST(Mempool, OverwinterNotActiveYet) { CValidationState state1; CTransaction tx1(mtx); + LOCK( get_cs_main() ); EXPECT_FALSE(AcceptToMemoryPool(pool, state1, tx1, false, &missingInputs)); EXPECT_EQ(state1.GetRejectReason(), "tx-overwinter-not-active"); @@ -206,6 +255,7 @@ TEST(Mempool, SproutV3TxFailsAsExpected) { CValidationState state1; CTransaction tx1(mtx); + LOCK( get_cs_main() ); EXPECT_FALSE(AcceptToMemoryPool(pool, state1, tx1, false, &missingInputs)); EXPECT_EQ(state1.GetRejectReason(), "version"); } @@ -227,6 +277,7 @@ TEST(Mempool, SproutV3TxWhenOverwinterActive) { CValidationState state1; CTransaction tx1(mtx); + LOCK( get_cs_main() ); EXPECT_FALSE(AcceptToMemoryPool(pool, state1, tx1, false, &missingInputs)); EXPECT_EQ(state1.GetRejectReason(), "tx-overwinter-flag-not-set"); @@ -248,6 +299,8 @@ TEST(Mempool, SproutNegativeVersionTxWhenOverwinterActive) { mtx.vjoinsplit.resize(0); // no joinsplits mtx.fOverwintered = false; + LOCK( get_cs_main() ); + // A Sprout transaction with version -3 is created using Sprout code (as found in zcashd <= 1.0.14). // First four bytes of transaction, parsed as an uint32_t, has the value: 0xfffffffd // This test simulates an Overwinter node receiving this transaction, but incorrectly deserializing the diff --git a/src/test-komodo/test_miner.cpp b/src/test-komodo/test_miner.cpp new file mode 100644 index 00000000000..be777308253 --- /dev/null +++ b/src/test-komodo/test_miner.cpp @@ -0,0 +1,8 @@ +#include + +bool test_tromp_equihash(); + +TEST(test_miner, check) +{ + EXPECT_FALSE(test_tromp_equihash()); +} diff --git a/src/test-komodo/test_notary.cpp b/src/test-komodo/test_notary.cpp new file mode 100644 index 00000000000..66ed5937621 --- /dev/null +++ b/src/test-komodo/test_notary.cpp @@ -0,0 +1,229 @@ +#include "testutils.h" +#include "chainparams.h" +#include "komodo_notary.h" + +#include + +//void undo_init_notaries(); // test helper +void komodo_notaries_uninit(); + + +namespace TestNotary +{ + +/*** + * A little class to help with the different formats keys come in + */ +class my_key +{ +public: + my_key(uint8_t in[33]) + { + for(int i = 0; i < 33; ++i) + key.push_back(in[i]); + } + my_key(const std::string& in) + { + for(int i = 0; i < 33; ++i) + key.push_back( + (unsigned int)strtol(in.substr(i*2, 2).c_str(), nullptr, 16) ); + } + bool fill(uint8_t in[33]) + { + memcpy(in, key.data(), 33); + return true; + } +private: + std::vector key; + friend bool operator==(const my_key& lhs, const my_key& rhs); +}; + +bool operator==(const my_key& lhs, const my_key& rhs) +{ + if (lhs.key == rhs.key) + return true; + return false; +} + +TEST(TestNotary, KomodoNotaries) +{ + // Test komodo_notaries(), getkmdseason() + chainName = assetchain(""); // set as KMD + SelectParams(CBaseChainParams::MAIN); + komodo_notaries_uninit(); + //undo_init_STAKED(); + uint8_t pubkeys[64][33]; + int32_t height = 0; + uint32_t timestamp = 0; + // Get the pubkeys of the first era + int32_t result = komodo_notaries(pubkeys, height, timestamp); + EXPECT_EQ(result, 35); + // the first notary didn't change between era 1 and 2, so look at the 2nd notary + EXPECT_EQ( my_key(pubkeys[1]), my_key("02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344")); + // make sure the era hasn't changed before it is supposed to + for(;height <= 179999; ++height) + { + result = komodo_notaries(pubkeys, height, timestamp); + EXPECT_EQ(result, 35); + EXPECT_EQ( getkmdseason(height), 1); + EXPECT_EQ( my_key(pubkeys[1]), my_key("02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344")); + if (result != 35 || getkmdseason(height) != 1) break; // cancel long test + } + EXPECT_EQ(height, 180000); + // at 180000 we start using notaries_elected(komodo_defs.h) instead of Notaries_genesis(komodo_notary.cpp) + for(;height <= 814000; ++height) + { + result = komodo_notaries(pubkeys, height, timestamp); + EXPECT_EQ(result, 64); + EXPECT_EQ( getkmdseason(height), 1); + EXPECT_EQ( my_key(pubkeys[1]), my_key("02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344")); + if (result != 64 || getkmdseason(height) != 1) break; // cancel long test + } + // make sure the era changes when it was supposed to, and we have a new key + EXPECT_EQ(height, 814001); + result = komodo_notaries(pubkeys, height, timestamp); + EXPECT_EQ(result, 64); + EXPECT_EQ( getkmdseason(height), 2); + EXPECT_EQ( my_key(pubkeys[1]), my_key("030f34af4b908fb8eb2099accb56b8d157d49f6cfb691baa80fdd34f385efed961") ); + + // now try the same thing with notaries_staked, which uses timestamp instead of height + // NOTE: If height is passed instead of timestamp, the timestamp is computed based on block timestamps + // notaries come from notaries_STAKED(notaries_staked.h) + // also tests STAKED_era() + height = 0; + timestamp = 1; + komodo_notaries_uninit(); + //undo_init_STAKED(); + chainName = assetchain("LABS"); + // we should be in era 1 now + result = komodo_notaries(pubkeys, height, timestamp); + EXPECT_EQ(result, 22); + EXPECT_EQ( STAKED_era(timestamp), 1); + EXPECT_EQ( my_key(pubkeys[13]), my_key("03669457b2934d98b5761121dd01b243aed336479625b293be9f8c43a6ae7aaeff")); + timestamp = 1572523200; + EXPECT_EQ(result, 22); + EXPECT_EQ( STAKED_era(timestamp), 1); + EXPECT_EQ( my_key(pubkeys[13]), my_key("03669457b2934d98b5761121dd01b243aed336479625b293be9f8c43a6ae7aaeff")); + // Moving to era 2 should change the notaries. But there is a gap of 777 that uses komodo notaries for some reason + // (NOTE: the first 12 are the same, so use the 13th) + timestamp++; + EXPECT_EQ(timestamp, 1572523201); + result = komodo_notaries(pubkeys, height, timestamp); + EXPECT_EQ(result, 64); + EXPECT_EQ( STAKED_era(timestamp), 0); + EXPECT_EQ( pubkeys[13][0], 0); + // advance past the gap + timestamp += 778; + result = komodo_notaries(pubkeys, height, timestamp); + EXPECT_EQ(result, 24); + EXPECT_EQ( STAKED_era(timestamp), 2); + EXPECT_EQ( my_key(pubkeys[13]), my_key("02d1dd4c5d5c00039322295aa965f9787a87d234ed4f8174231bbd6162e384eba8")); + + // now test getacseason() + EXPECT_EQ( getacseason(0), 1); + EXPECT_EQ( getacseason(1), 1); + EXPECT_EQ( getacseason(1525132800), 1); + EXPECT_EQ( getacseason(1525132801), 2); +} + +TEST(TestNotary, ElectedNotary) +{ + // exercise the routine that checks to see if a particular public key is a notary at the current height + + SelectParams(CBaseChainParams::MAIN); + // setup + komodo_notaries_uninit(); + //undo_init_STAKED(); + my_key first_era("02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344"); + my_key second_era("030f34af4b908fb8eb2099accb56b8d157d49f6cfb691baa80fdd34f385efed961"); + + int32_t numnotaries; + uint8_t pubkey[33]; + first_era.fill(pubkey); + int32_t height = 0; + uint32_t timestamp = 0; + + // check the KMD chain, first era + chainName = assetchain(); + int32_t result = komodo_electednotary(&numnotaries, pubkey, height, timestamp); + EXPECT_EQ(result, 1); + EXPECT_EQ( numnotaries, 35); + // now try a wrong key + second_era.fill(pubkey); + result = komodo_electednotary(&numnotaries, pubkey, height, timestamp); + EXPECT_EQ(result, -1); + EXPECT_EQ(numnotaries, 35); + + // KMD chain, second era + height = 814001; + result = komodo_electednotary(&numnotaries, pubkey, height, timestamp); + EXPECT_EQ(result, 1); + EXPECT_EQ( numnotaries, 64); + // now try a wrong key + first_era.fill(pubkey); + result = komodo_electednotary(&numnotaries, pubkey, height, timestamp); + EXPECT_EQ(result, -1); + EXPECT_EQ(numnotaries, 64); +} + +// season 7 tests for KMD: +TEST(TestNotary, KomodoNotaries_S7_KMD) +{ + uint8_t pubkeys[64][33]; + + SelectParams(CBaseChainParams::MAIN); + komodo_notaries_uninit(); + chainName = assetchain(""); // set as KMD + + EXPECT_EQ( getkmdseason(3484958+1), 8); + EXPECT_EQ( getkmdseason(8113400), 8); + EXPECT_EQ( getkmdseason(8113400+1), 0); + int32_t result1 = komodo_notaries(pubkeys, 3484958+1, 0); + EXPECT_EQ(result1, 64); + EXPECT_EQ( my_key(pubkeys[0]), my_key("03955c7999538cee313bf196a7df59db208c651f6a5a1b0eed94732ba753b4f3f4")); + EXPECT_EQ( my_key(pubkeys[63]), my_key("02f9a7b49282885cd03969f1f5478287497bc8edfceee9eac676053c107c5fcdaf")); + + // try wrong pubkey + int32_t numnotaries; + my_key wrong_pk("02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344"); + uint8_t pubkey[33]; + wrong_pk.fill(pubkey); + int32_t result2 = komodo_electednotary(&numnotaries, pubkey, 3484958+1, 0); + EXPECT_EQ(result2, -1); + EXPECT_EQ(numnotaries, 64); + + // cleanup + komodo_notaries_uninit(); +} + +// season 7 tests for asset chain: +TEST(TestNotary, KomodoNotaries_S7_AS) +{ + uint8_t pubkeys[64][33]; + + SelectParams(CBaseChainParams::MAIN); + komodo_notaries_uninit(); + chainName = assetchain("MYASSET"); + EXPECT_EQ( getacseason(1688132253+1), 8); + EXPECT_EQ( getacseason(1951328000), 8); + EXPECT_EQ( getacseason(1951328001), 0); + + int32_t result1 = komodo_notaries(pubkeys, 0, 1688132253+1); + EXPECT_EQ(result1, 64); + EXPECT_EQ( my_key(pubkeys[0]), my_key("03955c7999538cee313bf196a7df59db208c651f6a5a1b0eed94732ba753b4f3f4")); + EXPECT_EQ( my_key(pubkeys[63]), my_key("02f9a7b49282885cd03969f1f5478287497bc8edfceee9eac676053c107c5fcdaf")); + + // try wrong pubkey + int32_t numnotaries; + my_key wrong_pk("02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344"); + uint8_t pubkey[33]; + wrong_pk.fill(pubkey); + int32_t result2 = komodo_electednotary(&numnotaries, pubkey, 3484958+1, 1688132253+1); + EXPECT_EQ(result2, -1); + EXPECT_EQ(numnotaries, 64); + + // cleanup + komodo_notaries_uninit(); +} + +} // namespace TestNotary \ No newline at end of file diff --git a/src/test-komodo/test_oldhash_removal.cpp b/src/test-komodo/test_oldhash_removal.cpp new file mode 100644 index 00000000000..624419f56f0 --- /dev/null +++ b/src/test-komodo/test_oldhash_removal.cpp @@ -0,0 +1,468 @@ +#include +#include "komodo_utils.h" +#include +#include "hash.h" +#include "random.h" + +namespace TestOldHashRemoval { + + /* old rmd160 implementation derived from LibTomCrypt */ + + #define MIN(x, y) ( ((x)<(y))?(x):(y) ) + + #define STORE32L(x, y) \ + { (y)[3] = (uint8_t)(((x)>>24)&255); (y)[2] = (uint8_t)(((x)>>16)&255); \ + (y)[1] = (uint8_t)(((x)>>8)&255); (y)[0] = (uint8_t)((x)&255); } + + #define LOAD32L(x, y) \ + { x = (uint32_t)(((uint64_t)((y)[3] & 255)<<24) | \ + ((uint32_t)((y)[2] & 255)<<16) | \ + ((uint32_t)((y)[1] & 255)<<8) | \ + ((uint32_t)((y)[0] & 255))); } + + #define STORE64L(x, y) \ + { (y)[7] = (uint8_t)(((x)>>56)&255); (y)[6] = (uint8_t)(((x)>>48)&255); \ + (y)[5] = (uint8_t)(((x)>>40)&255); (y)[4] = (uint8_t)(((x)>>32)&255); \ + (y)[3] = (uint8_t)(((x)>>24)&255); (y)[2] = (uint8_t)(((x)>>16)&255); \ + (y)[1] = (uint8_t)(((x)>>8)&255); (y)[0] = (uint8_t)((x)&255); } + + // rmd160: the five basic functions F(), G() and H() + #define F(x, y, z) ((x) ^ (y) ^ (z)) + #define G(x, y, z) (((x) & (y)) | (~(x) & (z))) + #define H(x, y, z) (((x) | ~(y)) ^ (z)) + #define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) + #define J(x, y, z) ((x) ^ ((y) | ~(z))) + #define ROLc(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) + + /* the ten basic operations FF() through III() */ + #define FF(a, b, c, d, e, x, s) \ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + + #define GG(a, b, c, d, e, x, s) \ + (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + + #define HH(a, b, c, d, e, x, s) \ + (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + + #define II(a, b, c, d, e, x, s) \ + (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + + #define JJ(a, b, c, d, e, x, s) \ + (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + + #define FFF(a, b, c, d, e, x, s) \ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + + #define GGG(a, b, c, d, e, x, s) \ + (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + + #define HHH(a, b, c, d, e, x, s) \ + (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + + #define III(a, b, c, d, e, x, s) \ + (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + + #define JJJ(a, b, c, d, e, x, s) \ + (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + + static int32_t rmd160_vcompress(struct rmd160_vstate *md,uint8_t *buf) + { + uint32_t aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,X[16]; + int i; + + /* load words X */ + for (i = 0; i < 16; i++){ + LOAD32L(X[i], buf + (4 * i)); + } + + /* load state */ + aa = aaa = md->state[0]; + bb = bbb = md->state[1]; + cc = ccc = md->state[2]; + dd = ddd = md->state[3]; + ee = eee = md->state[4]; + + /* round 1 */ + FF(aa, bb, cc, dd, ee, X[ 0], 11); + FF(ee, aa, bb, cc, dd, X[ 1], 14); + FF(dd, ee, aa, bb, cc, X[ 2], 15); + FF(cc, dd, ee, aa, bb, X[ 3], 12); + FF(bb, cc, dd, ee, aa, X[ 4], 5); + FF(aa, bb, cc, dd, ee, X[ 5], 8); + FF(ee, aa, bb, cc, dd, X[ 6], 7); + FF(dd, ee, aa, bb, cc, X[ 7], 9); + FF(cc, dd, ee, aa, bb, X[ 8], 11); + FF(bb, cc, dd, ee, aa, X[ 9], 13); + FF(aa, bb, cc, dd, ee, X[10], 14); + FF(ee, aa, bb, cc, dd, X[11], 15); + FF(dd, ee, aa, bb, cc, X[12], 6); + FF(cc, dd, ee, aa, bb, X[13], 7); + FF(bb, cc, dd, ee, aa, X[14], 9); + FF(aa, bb, cc, dd, ee, X[15], 8); + + /* round 2 */ + GG(ee, aa, bb, cc, dd, X[ 7], 7); + GG(dd, ee, aa, bb, cc, X[ 4], 6); + GG(cc, dd, ee, aa, bb, X[13], 8); + GG(bb, cc, dd, ee, aa, X[ 1], 13); + GG(aa, bb, cc, dd, ee, X[10], 11); + GG(ee, aa, bb, cc, dd, X[ 6], 9); + GG(dd, ee, aa, bb, cc, X[15], 7); + GG(cc, dd, ee, aa, bb, X[ 3], 15); + GG(bb, cc, dd, ee, aa, X[12], 7); + GG(aa, bb, cc, dd, ee, X[ 0], 12); + GG(ee, aa, bb, cc, dd, X[ 9], 15); + GG(dd, ee, aa, bb, cc, X[ 5], 9); + GG(cc, dd, ee, aa, bb, X[ 2], 11); + GG(bb, cc, dd, ee, aa, X[14], 7); + GG(aa, bb, cc, dd, ee, X[11], 13); + GG(ee, aa, bb, cc, dd, X[ 8], 12); + + /* round 3 */ + HH(dd, ee, aa, bb, cc, X[ 3], 11); + HH(cc, dd, ee, aa, bb, X[10], 13); + HH(bb, cc, dd, ee, aa, X[14], 6); + HH(aa, bb, cc, dd, ee, X[ 4], 7); + HH(ee, aa, bb, cc, dd, X[ 9], 14); + HH(dd, ee, aa, bb, cc, X[15], 9); + HH(cc, dd, ee, aa, bb, X[ 8], 13); + HH(bb, cc, dd, ee, aa, X[ 1], 15); + HH(aa, bb, cc, dd, ee, X[ 2], 14); + HH(ee, aa, bb, cc, dd, X[ 7], 8); + HH(dd, ee, aa, bb, cc, X[ 0], 13); + HH(cc, dd, ee, aa, bb, X[ 6], 6); + HH(bb, cc, dd, ee, aa, X[13], 5); + HH(aa, bb, cc, dd, ee, X[11], 12); + HH(ee, aa, bb, cc, dd, X[ 5], 7); + HH(dd, ee, aa, bb, cc, X[12], 5); + + /* round 4 */ + II(cc, dd, ee, aa, bb, X[ 1], 11); + II(bb, cc, dd, ee, aa, X[ 9], 12); + II(aa, bb, cc, dd, ee, X[11], 14); + II(ee, aa, bb, cc, dd, X[10], 15); + II(dd, ee, aa, bb, cc, X[ 0], 14); + II(cc, dd, ee, aa, bb, X[ 8], 15); + II(bb, cc, dd, ee, aa, X[12], 9); + II(aa, bb, cc, dd, ee, X[ 4], 8); + II(ee, aa, bb, cc, dd, X[13], 9); + II(dd, ee, aa, bb, cc, X[ 3], 14); + II(cc, dd, ee, aa, bb, X[ 7], 5); + II(bb, cc, dd, ee, aa, X[15], 6); + II(aa, bb, cc, dd, ee, X[14], 8); + II(ee, aa, bb, cc, dd, X[ 5], 6); + II(dd, ee, aa, bb, cc, X[ 6], 5); + II(cc, dd, ee, aa, bb, X[ 2], 12); + + /* round 5 */ + JJ(bb, cc, dd, ee, aa, X[ 4], 9); + JJ(aa, bb, cc, dd, ee, X[ 0], 15); + JJ(ee, aa, bb, cc, dd, X[ 5], 5); + JJ(dd, ee, aa, bb, cc, X[ 9], 11); + JJ(cc, dd, ee, aa, bb, X[ 7], 6); + JJ(bb, cc, dd, ee, aa, X[12], 8); + JJ(aa, bb, cc, dd, ee, X[ 2], 13); + JJ(ee, aa, bb, cc, dd, X[10], 12); + JJ(dd, ee, aa, bb, cc, X[14], 5); + JJ(cc, dd, ee, aa, bb, X[ 1], 12); + JJ(bb, cc, dd, ee, aa, X[ 3], 13); + JJ(aa, bb, cc, dd, ee, X[ 8], 14); + JJ(ee, aa, bb, cc, dd, X[11], 11); + JJ(dd, ee, aa, bb, cc, X[ 6], 8); + JJ(cc, dd, ee, aa, bb, X[15], 5); + JJ(bb, cc, dd, ee, aa, X[13], 6); + + /* parallel round 1 */ + JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); + JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); + JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); + JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); + JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); + JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); + JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); + JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); + + /* parallel round 2 */ + III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); + III(ddd, eee, aaa, bbb, ccc, X[11], 13); + III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); + III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); + III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); + III(eee, aaa, bbb, ccc, ddd, X[13], 8); + III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); + III(ccc, ddd, eee, aaa, bbb, X[10], 11); + III(bbb, ccc, ddd, eee, aaa, X[14], 7); + III(aaa, bbb, ccc, ddd, eee, X[15], 7); + III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); + III(ddd, eee, aaa, bbb, ccc, X[12], 7); + III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); + III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); + III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); + III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); + + /* parallel round 3 */ + HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); + HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); + HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); + HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); + HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); + HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); + HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); + HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); + HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); + HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); + HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); + HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); + HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); + HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); + HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); + HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); + + /* parallel round 4 */ + GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); + GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); + GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); + GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); + GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); + GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); + GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); + GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); + GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); + GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); + GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); + GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); + GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); + GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); + GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); + GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); + + /* parallel round 5 */ + FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); + FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); + FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); + FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); + FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); + FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); + FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); + FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); + FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); + FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); + FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); + FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); + FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); + FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); + FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); + FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); + + /* combine results */ + ddd += cc + md->state[1]; /* final result for md->state[0] */ + md->state[1] = md->state[2] + dd + eee; + md->state[2] = md->state[3] + ee + aaa; + md->state[3] = md->state[4] + aa + bbb; + md->state[4] = md->state[0] + bb + ccc; + md->state[0] = ddd; + + return 0; + } + + /** + Initialize the hash state + @param md The hash state you wish to initialize + @return 0 if successful + */ + int rmd160_vinit(struct rmd160_vstate * md) + { + md->state[0] = 0x67452301UL; + md->state[1] = 0xefcdab89UL; + md->state[2] = 0x98badcfeUL; + md->state[3] = 0x10325476UL; + md->state[4] = 0xc3d2e1f0UL; + md->curlen = 0; + md->length = 0; + return 0; + } + + /** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return 0 if successful + */ + int rmd160_vprocess (struct rmd160_vstate * md, const unsigned char *in, unsigned long inlen) + { + unsigned long n; + int err; + if (md->curlen > sizeof(md->buf)) { + return -1; + } + while (inlen > 0) { + if (md->curlen == 0 && inlen >= 64) { + if ((err = rmd160_vcompress (md, (unsigned char *)in)) != 0) { + return err; + } + md->length += 64 * 8; + in += 64; + inlen -= 64; + } else { + n = MIN(inlen, (64 - md->curlen)); + memcpy(md->buf + md->curlen, in, (size_t)n); + md->curlen += n; + in += n; + inlen -= n; + if (md->curlen == 64) { + if ((err = rmd160_vcompress (md, md->buf)) != 0) { + return err; + } + md->length += 8*64; + md->curlen = 0; + } + } + } + return 0; + } + + /** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (20 bytes) + @return 0 if successful + */ + int rmd160_vdone(struct rmd160_vstate * md, unsigned char *out) + { + int i; + if (md->curlen >= sizeof(md->buf)) { + return -1; + } + /* increase the length of the message */ + md->length += md->curlen * 8; + + /* append the '1' bit */ + md->buf[md->curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->curlen > 56) { + while (md->curlen < 64) { + md->buf[md->curlen++] = (unsigned char)0; + } + rmd160_vcompress(md, md->buf); + md->curlen = 0; + } + /* pad upto 56 bytes of zeroes */ + while (md->curlen < 56) { + md->buf[md->curlen++] = (unsigned char)0; + } + /* store length */ + STORE64L(md->length, md->buf+56); + rmd160_vcompress(md, md->buf); + /* copy output */ + for (i = 0; i < 5; i++) { + STORE32L(md->state[i], out+(4*i)); + } + return 0; + } + + void calc_rmd160(char deprecated[41],uint8_t buf[20],uint8_t *msg,int32_t len) + { + struct rmd160_vstate md; + TestOldHashRemoval::rmd160_vinit(&md); + TestOldHashRemoval::rmd160_vprocess(&md, msg, len); + TestOldHashRemoval::rmd160_vdone(&md, buf); + } + + #undef F + #undef G + #undef H + #undef I + #undef J + #undef ROLc + #undef FF + #undef GG + #undef HH + #undef II + #undef JJ + #undef FFF + #undef GGG + #undef HHH + #undef III + #undef JJJ + + void calc_rmd160_sha256_new(uint8_t rmd160[20],uint8_t *data,int32_t datalen) { + CHash160().Write((const unsigned char *)data, datalen).Finalize(rmd160); // SHA-256 + RIPEMD-160 + } + + TEST(TestOldHashRemoval, calc_rmd160) + { + /* test vectors from http://gobittest.appspot.com/Address */ + + uint8_t sha256_hash_1[] = { + 0x60, 0x0f, 0xfe, 0x42, 0x2b, 0x4e, 0x00, 0x73, 0x1a, 0x59, 0x55, 0x7a, 0x5c, 0xca, 0x46, 0xcc, 0x18, 0x39, 0x44, 0x19, 0x10, 0x06, 0x32, 0x4a, 0x44, 0x7b, 0xdb, 0x2d, 0x98, 0xd4, 0xb4, 0x08 }; + uint8_t rmd160_hash_1[] = { + 0x1, 0x9, 0x66, 0x77, 0x60, 0x6, 0x95, 0x3d, 0x55, 0x67, 0x43, 0x9e, 0x5e, 0x39, 0xf8, 0x6a, 0xd, 0x27, 0x3b, 0xee }; + + uint8_t rmd160[20]; + bits256 hash; + + memset(hash.bytes, 0, sizeof(hash)); + memset(rmd160, 0, sizeof(rmd160)); + + memcpy(hash.bytes, sha256_hash_1, sizeof(hash)); + calc_rmd160(0, rmd160, hash.bytes, sizeof(hash)); + EXPECT_EQ(memcmp(rmd160, rmd160_hash_1, sizeof(rmd160)), 0); + + // echo "0450863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B23522CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6" | sed 's/../0x&,/g' | tr '[:upper:]' '[:lower:]' + uint8_t public_ecsda[] = { + 0x04, 0x50, 0x86, 0x3a, 0xd6, 0x4a, 0x87, 0xae, 0x8a, 0x2f, 0xe8, 0x3c, 0x1a, 0xf1, 0xa8, 0x40, 0x3c, 0xb5, 0x3f, 0x53, 0xe4, 0x86, 0xd8, 0x51, 0x1d, 0xad, 0x8a, 0x04, 0x88, 0x7e, 0x5b, 0x23, 0x52, 0x2c, 0xd4, 0x70, 0x24, 0x34, 0x53, 0xa2, 0x99, 0xfa, 0x9e, 0x77, 0x23, 0x77, 0x16, 0x10, 0x3a, 0xbc, 0x11, 0xa1, 0xdf, 0x38, 0x85, 0x5e, 0xd6, 0xf2, 0xee, 0x18, 0x7e, 0x9c, 0x58, 0x2b, 0xa6 }; + + memset(rmd160, 0, sizeof(rmd160)); + calc_rmd160_sha256(rmd160,public_ecsda,sizeof(public_ecsda)); + EXPECT_EQ(memcmp(rmd160, rmd160_hash_1, sizeof(rmd160)), 0); + + memset(rmd160, 0, sizeof(rmd160)); + calc_rmd160_sha256_new(rmd160,public_ecsda,sizeof(public_ecsda)); + EXPECT_EQ(memcmp(rmd160, rmd160_hash_1, sizeof(rmd160)), 0); + + for (size_t idx = 0; idx < 64; idx++) { + uint8_t pubkey[33]; + uint8_t rmd160_l[20], rmd160_r[20]; + memset(pubkey, 0, sizeof(pubkey)); + GetRandBytes(pubkey, sizeof(pubkey)); + calc_rmd160_sha256(rmd160_l,pubkey,sizeof(pubkey)); + calc_rmd160_sha256_new(rmd160_r,pubkey,sizeof(pubkey)); + EXPECT_EQ(memcmp(rmd160_l, rmd160_r, 20), 0); + } + + } + +} // namespace TestOldHashRemoval diff --git a/src/test-komodo/test_parse_notarisation.cpp b/src/test-komodo/test_parse_notarisation.cpp index 9eab052d2f0..786b41aa1ff 100644 --- a/src/test-komodo/test_parse_notarisation.cpp +++ b/src/test-komodo/test_parse_notarisation.cpp @@ -4,17 +4,87 @@ #include "core_io.h" #include "key.h" #include "testutils.h" +#include "assetchain.h" +#include "komodo_utils.h" +#include "komodo_notary.h" #include "komodo_structs.h" +#include "komodo_extern_globals.h" #include "test_parse_notarisation.h" +#include "chainparamsbase.h" +#include #include -komodo_state *komodo_stateptr(char *symbol,char *dest); +// todo remove +/*komodo_state *komodo_stateptr(char *symbol,char *dest); void komodo_notarized_update(struct komodo_state *sp,int32_t nHeight,int32_t notarized_height, uint256 notarized_hash,uint256 notarized_desttxid,uint256 MoM,int32_t MoMdepth); const notarized_checkpoint *komodo_npptr(int32_t height); int32_t komodo_prevMoMheight(); int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp); +// method in komodo_utils.cpp: +void set_kmd_user_password_port(const std::string& ltc_config_filename); +extern char KMDUSERPASS[8705]; +extern char BTCUSERPASS[8192]; +extern uint16_t DEST_PORT;*/ + +#ifdef __WINDOWS__ +// for when HOMEDRIVE and HOMEPATH is used... +std::pair parse_drive(const std::string& in) +{ + size_t pos = in.find(":"); + std::string drive; + std::string path; + if (pos < 3 && pos != 0) + { + drive = in.substr(0, pos+1); + path = in.substr(pos + 1); + } + return {drive, path}; +} + +char concat[1024]; +bool set_home(const std::string& in) +{ + const char* profile = getenv("USERPROFILE"); + if (profile == nullptr) + { + // divide homedrive and homepath + auto pair = parse_drive(in); + std::string val = "HOMEDRIVE=" + pair.first; + _putenv(val.c_str()); + val = "HOMEPATH=" + pair.second; + _putenv(val.c_str()); + return true; + } + std::string val = "USERPROFILE=" + in; + _putenv(val.c_str()); + return true; +} + +const char* get_home() +{ + concat[0] = 0; + const char* profile = getenv("USERPROFILE"); + if (profile == nullptr) + { + strcpy(concat, getenv("HOMEDRIVE")); + strcat(concat, getenv("HOMEPATH") ); + return concat; + } + return profile; +} +#else +const char* get_home() +{ + return getenv("HOME"); +} +bool set_home(const std::string& in) +{ + setenv("HOME", in.c_str(), true); + return true; +} +#endif class komodo_state_accessor : public komodo_state { @@ -45,7 +115,6 @@ namespace old_space { uint64_t deposited,issued,withdrawn,approved,redeemed,shorted; struct notarized_checkpoint *NPOINTS; int32_t NUM_NPOINTS,last_NPOINTSi; //std::list> events; - uint32_t RTbufs[64][3]; uint64_t RTmask; //bool add_event(const std::string& symbol, const uint32_t height, std::shared_ptr in); }; @@ -63,8 +132,6 @@ namespace old_space { fprintf(stderr,"komodo_notarized_update REJECT notarized_height %d > %d nHeight\n",notarized_height,nHeight); return; } - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - fprintf(stderr,"[%s] komodo_notarized_update nHeight.%d notarized_height.%d\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height); portable_mutex_lock(&komodo_mutex); sp->NPOINTS = (struct notarized_checkpoint *)realloc(sp->NPOINTS,(sp->NUM_NPOINTS+1) * sizeof(*sp->NPOINTS)); np = &sp->NPOINTS[sp->NUM_NPOINTS++]; @@ -84,7 +151,6 @@ namespace old_space { int32_t i; struct komodo_state *sp; struct notarized_checkpoint *np = 0; - //if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) sp = &old_space::ks_old; { @@ -111,7 +177,6 @@ namespace old_space { struct notarized_checkpoint *komodo_npptr_at(int idx) { char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - //if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) sp = &old_space::ks_old; if (idx < sp->NUM_NPOINTS) @@ -125,7 +190,6 @@ namespace old_space { zero.SetNull(); char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; int32_t i; struct komodo_state *sp; struct notarized_checkpoint *np = 0; - //if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) sp = &old_space::ks_old; { for (i=sp->NUM_NPOINTS-1; i>=0; i--) @@ -145,7 +209,6 @@ namespace old_space { char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - //if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) sp = &old_space::ks_old; { if ( sp->NUM_NPOINTS > 0 ) @@ -406,9 +469,14 @@ TEST(TestParseNotarisation, test_notarizeddata) EXPECT_EQ(txid, expected_txid); } -TEST(TestParseNotarisation, OldVsNew) +TEST(TestParseNotarisation, DISABLED_OldVsNew) { - ASSETCHAINS_SYMBOL[0] = 0; + /*** + * This test requires a binary file of notarization data + * as well as a long time to run. Re-enable this test to check + * the notarization checkpoints. + */ + chainName = assetchain(""); char symbol[4] = { 0 }; char dest[4] = { 0 }; @@ -520,4 +588,123 @@ TEST(TestParseNotarisation, OldVsNew) // for l in `g 'parse notarisation' ~/.komodo/debug.log | pyline 'l.split()[8]'`; do hoek decodeTx '{"hex":"'`src/komodo-cli getrawtransaction "$l"`'"}' | jq '.outputs[1].script.op_return' | pyline 'import base64; print base64.b64decode(l).encode("hex")'; done +TEST(TestParseNotarisation, FilePaths) +{ +#if defined(__APPLE__) + std::string komodo_conf = "Komodo.conf"; +#else + std::string komodo_conf = "komodo.conf"; +#endif + std::string ltc_conf = "litecoin.conf"; + + // helper for home directory + class MockDataDirectory + { + public: + MockDataDirectory() + { + ClearDatadirCache(); + data_path = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + auto komodo_path = data_path / os_dir / kmd_dir / "regtest"; + auto ltc_path = data_path / os_dir / ltc_dir / "regtest"; + boost::filesystem::create_directories(komodo_path); + boost::filesystem::create_directories(ltc_path); + orig_home = get_home(); + set_home(data_path.string().c_str()); + } + ~MockDataDirectory() + { + boost::filesystem::remove_all(data_path); + set_home(orig_home.string().c_str()); + ClearDatadirCache(); + } + bool create_config(const boost::filesystem::path& filesubpath, const std::string& user, + const std::string& pass, uint16_t port) + { + std::string file = (data_path / os_dir / filesubpath).string(); + std::ofstream komodo(file); + komodo << "rpcuser=" << user << "\n" + << "rpcpassword=" << pass << "\n" + << "rpcport=" << std::to_string(port) << "\n"; + return true; + } + boost::filesystem::path data_path; + boost::filesystem::path orig_home; +#ifdef __WINDOWS__ + const boost::filesystem::path os_dir = "AppData/Roaming"; + const boost::filesystem::path kmd_dir = "Komodo"; + const boost::filesystem::path ltc_dir = "Litecoin"; +#elif __APPLE__ + const boost::filesystem::path os_dir = "Library/Application Support"; + const boost::filesystem::path kmd_dir = "Komodo"; + const boost::filesystem::path ltc_dir = "Litecoin"; +#else + const boost::filesystem::path os_dir = ""; + const boost::filesystem::path kmd_dir = ".komodo"; + const boost::filesystem::path ltc_dir = ".litecoin"; +#endif + }; + +#ifndef __WINDOWS__ // we cannot use temp path on windows due to implementation of GetAppDir() + SelectParams(CBaseChainParams::REGTEST); + { + // default + MockDataDirectory home; + mapArgs.erase("-datadir"); + ASSETCHAINS_P2PPORT = 0; + ASSETCHAINS_RPCPORT = 0; + memset(KMDUSERPASS, 0, sizeof(KMDUSERPASS) ); + memset(BTCUSERPASS, 0, sizeof(BTCUSERPASS) ); + DEST_PORT=0; + IS_KOMODO_NOTARY = 0; + home.create_config(home.kmd_dir / "regtest" / komodo_conf, "test1", "my_password", 1234); + set_kmd_user_password_port(""); + EXPECT_EQ( std::string(KMDUSERPASS), std::string("test1:my_password") ); + EXPECT_EQ( std::string(BTCUSERPASS), std::string("")); + EXPECT_EQ(DEST_PORT, 0); + EXPECT_EQ(ASSETCHAINS_P2PPORT, 7770); + EXPECT_EQ(ASSETCHAINS_RPCPORT, 7771); + } + { + // with -datadir + MockDataDirectory home; + mapArgs["-datadir"] = (home.data_path / home.os_dir / home.kmd_dir).string(); + ASSETCHAINS_P2PPORT = 0; + ASSETCHAINS_RPCPORT = 0; + memset(KMDUSERPASS, 0, sizeof(KMDUSERPASS) ); + memset(BTCUSERPASS, 0, sizeof(BTCUSERPASS) ); + DEST_PORT=0; + IS_KOMODO_NOTARY = 0; + std::string expected_kmd("test1:my_password"); + home.create_config(home.kmd_dir / "regtest" / komodo_conf, "test1", "my_password", 1234); + set_kmd_user_password_port(""); + EXPECT_EQ( std::string(KMDUSERPASS), std::string("test1:my_password") ); + EXPECT_EQ( std::string(BTCUSERPASS), std::string("")); + EXPECT_EQ(DEST_PORT, 0); + EXPECT_EQ(ASSETCHAINS_P2PPORT, 7770); + EXPECT_EQ(ASSETCHAINS_RPCPORT, 7771); + } + { + // with -notary + MockDataDirectory home; + mapArgs["-datadir"] = (home.data_path / home.os_dir / home.kmd_dir).string(); + ASSETCHAINS_P2PPORT = 0; + ASSETCHAINS_RPCPORT = 0; + memset(KMDUSERPASS, 0, sizeof(KMDUSERPASS) ); + memset(BTCUSERPASS, 0, sizeof(BTCUSERPASS) ); + DEST_PORT=0; + IS_KOMODO_NOTARY = 1; + std::string expected_kmd("test1:my_password"); + home.create_config(home.kmd_dir / "regtest" / komodo_conf, "test1", "my_password", 1234); + home.create_config(home.ltc_dir / "regtest" / ltc_conf, "test2", "ltc_password", 5678); + set_kmd_user_password_port((home.ltc_dir / "regtest" / ltc_conf).string()); + EXPECT_EQ(std::string(KMDUSERPASS), std::string("test1:my_password")); + EXPECT_EQ(std::string(BTCUSERPASS), std::string("test2:ltc_password")); + EXPECT_EQ(DEST_PORT, 5678); + EXPECT_EQ(ASSETCHAINS_P2PPORT, 7770); + EXPECT_EQ(ASSETCHAINS_RPCPORT, 7771); + } +#endif // #ifndef __WINDOWS__ } + +} // namespace TestParseNotarisation diff --git a/src/test-komodo/test_parse_notarisation.h b/src/test-komodo/test_parse_notarisation.h index afe80acb71f..901fa5330d8 100644 --- a/src/test-komodo/test_parse_notarisation.h +++ b/src/test-komodo/test_parse_notarisation.h @@ -7,3 +7,4 @@ * @returns a big vector */ std::vector get_test_checkpoints_from_file(const std::string& filename); +const notarized_checkpoint *komodo_npptr(int32_t height); diff --git a/src/test-komodo/test_parse_notarisation_data.cpp b/src/test-komodo/test_parse_notarisation_data.cpp index ee212ae3e73..ddf7010c952 100644 --- a/src/test-komodo/test_parse_notarisation_data.cpp +++ b/src/test-komodo/test_parse_notarisation_data.cpp @@ -1,4 +1,10 @@ + +#include "komodo_utils.h" +#include "komodo_notary.h" #include "komodo_structs.h" +#include "komodo_globals.h" +#include "komodo_extern_globals.h" + #include #include diff --git a/src/gtest/test_pow.cpp b/src/test-komodo/test_pow.cpp similarity index 67% rename from src/gtest/test_pow.cpp rename to src/test-komodo/test_pow.cpp index 4557f6db11d..e06f6f80286 100644 --- a/src/gtest/test_pow.cpp +++ b/src/test-komodo/test_pow.cpp @@ -1,9 +1,9 @@ -#include #include "chain.h" #include "chainparams.h" #include "pow.h" #include "random.h" +#include TEST(PoW, DifficultyAveraging) { SelectParams(CBaseChainParams::MAIN); @@ -73,16 +73,19 @@ TEST(PoW, MinDifficultyRules) { SelectParams(CBaseChainParams::TESTNET); const Consensus::Params& params = Params().GetConsensus(); size_t lastBlk = 2*params.nPowAveragingWindow; - size_t firstBlk = lastBlk - params.nPowAveragingWindow; + const uint32_t startTime = 1269211443; // Start with blocks evenly-spaced and equal difficulty std::vector blocks(lastBlk+1); + uint32_t nextTime = startTime; for (int i = 0; i <= lastBlk; i++) { + nextTime = nextTime + params.nPowTargetSpacing; blocks[i].pprev = i ? &blocks[i - 1] : nullptr; blocks[i].nHeight = params.nPowAllowMinDifficultyBlocksAfterHeight.get() + i; - blocks[i].nTime = 1269211443 + i * params.nPowTargetSpacing; + blocks[i].nTime = nextTime; blocks[i].nBits = 0x1e7fffff; /* target 0x007fffff000... */ - blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + GetBlockProof(blocks[i - 1]) : arith_uint256(0); + blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + + GetBlockProof(blocks[i - 1]) : arith_uint256(0); } // Create a new block at the target spacing @@ -96,16 +99,50 @@ TEST(PoW, MinDifficultyRules) { bnRes *= params.AveragingWindowTimespan(); EXPECT_EQ(GetNextWorkRequired(&blocks[lastBlk], &next, params), bnRes.GetCompact()); - // Delay last block up to the edge of the min-difficulty limit + // Delay last block a bit, time warp protection should prevent any change next.nTime += params.nPowTargetSpacing * 5; // Result should be unchanged, modulo integer division precision loss EXPECT_EQ(GetNextWorkRequired(&blocks[lastBlk], &next, params), bnRes.GetCompact()); - // Delay last block over the min-difficulty limit - next.nTime += 1; + // Delay last block to a huge number. Result should be unchanged, time warp protection + next.nTime = std::numeric_limits::max(); + EXPECT_EQ(GetNextWorkRequired(&blocks[lastBlk], &next, params), bnRes.GetCompact()); + + // space all blocks out so the median is above the limits and difficulty should drop + nextTime = startTime; + for (int i = 0; i <= lastBlk; i++) { + nextTime = nextTime + ( params.MaxActualTimespan() / params.nPowAveragingWindow + 1); + blocks[i].nTime = nextTime; + blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + + GetBlockProof(blocks[i - 1]) : arith_uint256(0); + } + + // difficulty should have decreased ( nBits increased ) + EXPECT_GT(GetNextWorkRequired(&blocks[lastBlk], &next, params), + bnRes.GetCompact()); + + // diffuculty should never decrease below minimum + arith_uint256 minWork = UintToArith256(params.powLimit); + for (int i = 0; i <= lastBlk; i++) { + blocks[i].nBits = minWork.GetCompact(); + blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + + GetBlockProof(blocks[i - 1]) : arith_uint256(0); + } + EXPECT_EQ(GetNextWorkRequired(&blocks[lastBlk], &next, params), minWork.GetCompact()); + + // space all blocks out so the median is under limits and difficulty should increase + nextTime = startTime; + for (int i = 0; i <= lastBlk; i++) { + nextTime = nextTime + (params.MinActualTimespan() / params.nPowAveragingWindow - 1); + blocks[i].nTime = nextTime; + blocks[i].nBits = 0x1e7fffff; /* target 0x007fffff000... */ + blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + + GetBlockProof(blocks[i - 1]) : arith_uint256(0); + } + + // difficulty should have increased ( nBits decreased ) + EXPECT_LT(GetNextWorkRequired(&blocks[lastBlk], &next, params), + bnRes.GetCompact()); - // Result should be the minimum difficulty - EXPECT_EQ(GetNextWorkRequired(&blocks[lastBlk], &next, params), - UintToArith256(params.powLimit).GetCompact()); } diff --git a/src/gtest/test_random.cpp b/src/test-komodo/test_random.cpp similarity index 91% rename from src/gtest/test_random.cpp rename to src/test-komodo/test_random.cpp index d89702bcdf4..91d390e05a3 100644 --- a/src/gtest/test_random.cpp +++ b/src/test-komodo/test_random.cpp @@ -2,8 +2,16 @@ #include "random.h" -extern int GenZero(int n); -extern int GenMax(int n); +int GenZero(int n) +{ + return 0; +} + +int GenMax(int n) +{ + return n-1; +} + TEST(Random, MappedShuffle) { std::vector a {8, 4, 6, 3, 5}; diff --git a/src/gtest/test_txid.cpp b/src/test-komodo/test_txid.cpp similarity index 94% rename from src/gtest/test_txid.cpp rename to src/test-komodo/test_txid.cpp index 9b4a21068d1..f3500b08c32 100644 --- a/src/gtest/test_txid.cpp +++ b/src/test-komodo/test_txid.cpp @@ -8,7 +8,7 @@ #include "utilstrencodings.h" /* - Test that removing #1144 succeeded by verifying the hash of a transaction is over the entire serialized form. + Verify the hash of a transaction is over the entire serialized form. */ TEST(txid_tests, check_txid_and_hash_are_same) { // Random zcash transaction aacaa62d40fcdd9192ed35ea9df31660ccf7f6c60566530faaa444fb5d0d410e diff --git a/src/test-komodo/testutils.cpp b/src/test-komodo/testutils.cpp index c17de8bb14b..47a29b1edea 100644 --- a/src/test-komodo/testutils.cpp +++ b/src/test-komodo/testutils.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "core_io.h" #include "key.h" @@ -18,24 +19,69 @@ #include "primitives/transaction.h" #include "script/cc.h" #include "script/interpreter.h" - +#include "komodo_extern_globals.h" +#include "komodo_globals.h" +#include "komodo_notary.h" +#include "komodo_bitcoind.h" +#include "utilmoneystr.h" #include "testutils.h" - +#include "coincontrol.h" +#include "cc/CCinclude.h" std::string notaryPubkey = "0205a8ad0c1dbc515f149af377981aab58b836af008d4d7ab21bd76faf80550b47"; std::string notarySecret = "UxFWWxsf1d7w7K5TvAWSkeX4H95XQKwdwGv49DXwWUTzPTTjHBbU"; CKey notaryKey; - /* * We need to have control of clock, * otherwise block production can fail. */ int64_t nMockTime; -extern uint32_t USE_EXTERNAL_PUBKEY; +extern int32_t USE_EXTERNAL_PUBKEY; extern std::string NOTARY_PUBKEY; +void adjust_hwmheight(int32_t in); // in komodo.cpp +CCriticalSection& get_cs_main(); // in main.cpp +std::shared_ptr generateBlock(CWallet* wallet, CValidationState* state = nullptr); // in mining.cpp + +void displayTransaction(const CTransaction& tx) +{ + std::cout << "Transaction Hash: " << tx.GetHash().ToString(); + for(size_t i = 0; i < tx.vin.size(); ++i) + { + std::cout << "\nvIn " << i + << " prevout hash : " << tx.vin[i].prevout.hash.ToString() + << " n: " << tx.vin[i].prevout.n; + } + for(size_t i = 0; i < tx.vout.size(); ++i) + { + std::cout << "\nvOut " << i + << " nValue: " << tx.vout[i].nValue + << " scriptPubKey: " << tx.vout[i].scriptPubKey.ToString() + << " interest: " << tx.vout[i].interest; + } + std::cout << "\n"; +} + +void displayBlock(const CBlock& blk) +{ + std::cout << "Block Hash: " << blk.GetHash().ToString() + << "\nPrev Hash: " << blk.hashPrevBlock.ToString() + << "\n"; + for(size_t i = 0; i < blk.vtx.size(); ++i) + { + std::cout << i << " "; + displayTransaction(blk.vtx[i]); + } + std::cout << "\n"; +} + +void setConsoleDebugging(bool enable) +{ + fPrintToConsole = enable; +} + void setupChain() { SelectParams(CBaseChainParams::REGTEST); @@ -44,7 +90,6 @@ void setupChain() NOTARY_PUBKEY = notaryPubkey; USE_EXTERNAL_PUBKEY = 1; mapArgs["-mineraddress"] = "bogus"; - COINBASE_MATURITY = 1; // Global mock time nMockTime = GetTime(); @@ -53,11 +98,6 @@ void setupChain() // Init blockchain ClearDatadirCache(); - auto pathTemp = GetTempPath() / strprintf("test_komodo_%li_%i", GetTime(), GetRand(100000)); - if (ASSETCHAINS_SYMBOL[0]) - pathTemp = pathTemp / strprintf("_%s", ASSETCHAINS_SYMBOL); - boost::filesystem::create_directories(pathTemp); - mapArgs["-datadir"] = pathTemp.string(); pblocktree = new CBlockTreeDB(1 << 20, true); CCoinsViewDB *pcoinsdbview = new CCoinsViewDB(1 << 23, true); pcoinsTip = new CCoinsViewCache(pcoinsdbview); @@ -65,40 +105,55 @@ void setupChain() InitBlockIndex(); } - +/*** + * Generate a block + * @param block a place to store the block (nullptr skips the disk read) + */ void generateBlock(CBlock *block) { + SetMockTime(nMockTime+=100); // CreateNewBlock can fail if not enough time passes + UniValue params; params.setArray(); params.push_back(1); - uint256 blockId; - - SetMockTime(nMockTime+=100); // CreateNewBlock can fail if not enough time passes try { UniValue out = generate(params, false, CPubKey()); + uint256 blockId; blockId.SetHex(out[0].getValStr()); - if (block) ASSERT_TRUE(ReadBlockFromDisk(*block, mapBlockIndex[blockId], false)); + if (block) + ASSERT_TRUE(ReadBlockFromDisk(*block, mapBlockIndex[blockId], false)); } catch (const UniValue& e) { FAIL() << "failed to create block: " << e.write().data(); } } - +/*** + * Accept a transaction, failing the gtest if the tx is not accepted + * @param tx the transaction to be accepted + */ void acceptTxFail(const CTransaction tx) { CValidationState state; - if (!acceptTx(tx, state)) FAIL() << state.GetRejectReason(); + if (!acceptTx(tx, state)) + FAIL() << state.GetRejectReason(); } bool acceptTx(const CTransaction tx, CValidationState &state) { LOCK(cs_main); - return AcceptToMemoryPool(mempool, state, tx, false, NULL); + bool missingInputs = false; + bool accepted = AcceptToMemoryPool(mempool, state, tx, false, &missingInputs, false, -1); + return accepted && !missingInputs; } - +/*** + * Create a transaction based on input + * @param txIn the vin data (which becomes prevout) + * @param nOut the index of txIn to use as prevout + * @returns the transaction + */ CMutableTransaction spendTx(const CTransaction &txIn, int nOut) { CMutableTransaction mtx; @@ -125,7 +180,7 @@ std::vector getSig(const CMutableTransaction mtx, CScript inputPubKey, * In order to do tests there needs to be inputs to spend. * This method creates a block and returns a transaction that spends the coinbase. */ -void getInputTx(CScript scriptPubKey, CTransaction &txIn) +CTransaction getInputTx(CScript scriptPubKey) { // Get coinbase CBlock block; @@ -143,5 +198,707 @@ void getInputTx(CScript scriptPubKey, CTransaction &txIn) // Accept acceptTxFail(mtx); - txIn = CTransaction(mtx); + return CTransaction(mtx); +} + +/**** + * A class to provide a simple chain for tests + */ + +TestChain::TestChain() +{ + CleanGlobals(); + previousNetwork = Params().NetworkIDString(); + dataDir = GetTempPath() / strprintf("test_komodo_%li_%i", GetTime(), GetRand(100000)); + if (!chainName.isKMD()) + dataDir = dataDir / strprintf("_%s", chainName.symbol().c_str()); + boost::filesystem::create_directories(dataDir); + mapArgs["-datadir"] = dataDir.string(); + + setupChain(); + USE_EXTERNAL_PUBKEY = 0; // we want control of who mines the block + CBitcoinSecret vchSecret; + vchSecret.SetString(notarySecret); // this returns false due to network prefix mismatch but works anyway + notaryKey = vchSecret.GetKey(); +} + +TestChain::~TestChain() +{ + CleanGlobals(); + // cruel and crude, but cleans up any wallet dbs so subsequent tests run. + bitdb = std::shared_ptr(new CDBEnv{}); + try { + boost::filesystem::remove_all(dataDir); + } catch(boost::filesystem::filesystem_error &ex) {} // throws exception on windows due to db.log being busy (apparently it is not closed) + if (previousNetwork == "main") + SelectParams(CBaseChainParams::MAIN); + if (previousNetwork == "regtest") + SelectParams(CBaseChainParams::REGTEST); + if (previousNetwork == "test") + SelectParams(CBaseChainParams::TESTNET); + +} + +boost::filesystem::path TestChain::GetDataDir() { return dataDir; } + +void TestChain::CleanGlobals() +{ + // hwmheight can get skewed if komodo_connectblock not called (which some tests do) + adjust_hwmheight(0); + for(int i = 0; i < KOMODO_STATES_NUMBER; ++i) + { + komodo_state s = KOMODO_STATES[i]; + s.events.clear(); + // TODO: clean notarization points + } +} + +/*** + * Get the block index at the specified height + * @param height the height (0 indicates current height) + * @returns the block index + */ +CBlockIndex *TestChain::GetIndex(uint32_t height) +{ + if (height == 0) + return chainActive.Tip(); + return chainActive[height]; + +} + +void TestChain::IncrementChainTime() +{ + SetMockTime(nMockTime += 100); +} + +CCoinsViewCache *TestChain::GetCoinsViewCache() +{ + return pcoinsTip; +} + +std::shared_ptr TestChain::generateBlock(std::shared_ptr wallet, CValidationState* state) +{ + std::shared_ptr block; + if (wallet == nullptr) + { + CBlock blk; + ::generateBlock(&blk); + block = std::shared_ptr(new CBlock(blk) ); + } + else + block = ::generateBlock(wallet.get(), state); + return block; +} + +bool TestChain::ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, + bool fJustCheck, bool fCheckPOW) +{ + LOCK( get_cs_main() ); + return ::ConnectBlock(block, state, pindex, *(this->GetCoinsViewCache()), fJustCheck, fCheckPOW); +} + +CKey TestChain::getNotaryKey() { return notaryKey; } + +CValidationState TestChain::acceptTx(const CTransaction& tx) +{ + CValidationState retVal; + bool accepted = ::acceptTx(tx, retVal); + if (!accepted && retVal.IsValid()) + retVal.DoS(100, false, 0U, "acceptTx returned false"); + return retVal; +} + +/****** + * @brief A wallet for testing + * @param chain the chain + * @param name a name for the wallet + */ +TestWallet::TestWallet(const std::string& name) + : CWallet( name + ".dat") +{ + key.MakeNewKey(true); + LOCK(cs_wallet); + bool firstRunRet; + DBErrors err = LoadWallet(firstRunRet); + AddKey(key); + RegisterValidationInterface(this); +} + +/****** + * @brief A wallet for testing + * @param chain the chain + * @param in a key that already exists + * @param name a name for the wallet + */ +TestWallet::TestWallet(const CKey& in, const std::string& name) + : CWallet( name + ".dat"), key(in) +{ + LOCK( cs_wallet ); + bool firstRunRet; + DBErrors err = LoadWallet(firstRunRet); + AddKey(key); + RegisterValidationInterface(this); +} + +TestWallet::~TestWallet() +{ + UnregisterValidationInterface(this); + // TODO: remove file +} + +/*** + * @returns the public key + */ +CPubKey TestWallet::GetPubKey() const { return key.GetPubKey(); } + +/*** + * @returns the private key + */ +CKey TestWallet::GetPrivKey() const { return key; } + +/*** + * Sign a typical transaction + * @param hash the hash to sign + * @param hashType SIGHASH_ALL or something similar + * @returns the bytes to add to ScriptSig +*/ +std::vector TestWallet::Sign(uint256 hash, unsigned char hashType) +{ + std::vector retVal; + key.Sign(hash, retVal); + retVal.push_back(hashType); + return retVal; +} + +/*** + * Sign a cryptocondition + * @param cc the cryptocondition + * @param hash the hash to sign + * @returns the bytes to add to ScriptSig +*/ +std::vector TestWallet::Sign(CC* cc, uint256 hash) +{ + int out = cc_signTreeSecp256k1Msg32(cc, key.begin(), hash.begin()); + return CCSigVec(cc); +} + +/*** + * Transfer to another user + * @param to who to transfer to + * @param amount the amount + * @returns the results + */ +CTransaction TestWallet::Transfer(std::shared_ptr to, CAmount amount, CAmount fee) +{ + TransactionInProcess tip = CreateSpendTransaction(to, amount, fee); + if (!CWallet::CommitTransaction( tip.transaction, tip.reserveKey)) + throw std::logic_error("Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."); + return tip.transaction; +} + +/************* + * @brief Create a transaction, do not place in mempool + * @note throws std::logic_error if there was a problem + * @param to who to send to + * @param amount the amount to send + * @param fee the fee + * @returns the transaction +*/ +TransactionInProcess TestWallet::CreateSpendTransaction(std::shared_ptr to, + CAmount amount, CAmount fee, bool commit) +{ + CAmount curBalance = this->GetBalance(); + CAmount curImatureBalance = this->GetImmatureBalance(); + CAmount curUnconfirmedBalance = this->GetUnconfirmedBalance(); + + // Check amount + if (amount <= 0) + throw std::logic_error("Invalid amount"); + + if (amount > curBalance) + throw std::logic_error("Insufficient funds"); + + // Build recipient vector + std::vector vecSend; + bool fSubtractFeeFromAmount = false; + CRecipient recipient = {GetScriptForDestination(to->GetPubKey()), amount, fSubtractFeeFromAmount}; + vecSend.push_back(recipient); + // other items needed for transaction creation call + CAmount nFeeRequired; + std::string strError; + int nChangePosRet = -1; + TransactionInProcess retVal(this); + if (!CWallet::CreateTransaction(vecSend, retVal.transaction, retVal.reserveKey, nFeeRequired, + nChangePosRet, strError)) + { + if (!fSubtractFeeFromAmount && amount + nFeeRequired > GetBalance()) + strError = strprintf("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!", + FormatMoney(nFeeRequired)); + throw std::logic_error(strError); + } + + if (commit && !CommitTransaction(retVal.transaction, retVal.reserveKey)) + { + std::logic_error("Unable to commit transaction"); + } + + return retVal; +} + +/************* + * @brief Create a transaction, do not place in mempool + * @note throws std::logic_error if there was a problem + * @param to who to send to + * @param amount the amount to send + * @param fee the fee + * @param txToSpend the specific transaction to spend (ok if not transmitted yet) + * @returns the transaction +*/ +TransactionInProcess TestWallet::CreateSpendTransaction(std::shared_ptr to, + CAmount amount, CAmount fee, CCoinControl& coinControl) +{ + // verify the passed-in transaction has enough funds + std::vector availableTxs; + coinControl.ListSelected(availableTxs); + CTransaction tx; + uint256 hashBlock; + if (!myGetTransaction(availableTxs[0].hash, tx, hashBlock)) + throw std::logic_error("Requested tx not found"); + + CAmount curBalance = tx.vout[availableTxs[0].n].nValue; + + // Check amount + if (amount <= 0) + throw std::logic_error("Invalid amount"); + + if (amount > curBalance) + throw std::logic_error("Insufficient funds"); + + // Build recipient vector + std::vector vecSend; + bool fSubtractFeeFromAmount = false; + CRecipient recipient = {GetScriptForDestination(to->GetPubKey()), amount, fSubtractFeeFromAmount}; + vecSend.push_back(recipient); + // other items needed for transaction creation call + CAmount nFeeRequired; + std::string strError; + int nChangePosRet = -1; + TransactionInProcess retVal(this); + if (!CreateTransaction(vecSend, retVal.transaction, retVal.reserveKey, strError, &coinControl)) + { + if (!fSubtractFeeFromAmount && amount + nFeeRequired > curBalance) + strError = strprintf("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!", + FormatMoney(nFeeRequired)); + throw std::logic_error(strError); + } + + return retVal; +} + +/**** + * @brief create a transaction spending a vout that is not yet in the wallet + * @param vecSend the recipients + * @param wtxNew the resultant tx + * @param reserveKey the key used + * @param strFailReason the reason for any failure + * @param outputControl the tx to spend + * @returns true on success + */ +bool TestWallet::CreateTransaction(const std::vector& vecSend, CWalletTx& wtxNew, + CReserveKey& reservekey, std::string& strFailReason, CCoinControl* coinControl) +{ + bool sign = true; + int nChangePosRet = 0; + uint64_t interest2 = 0; + CAmount nValue = 0; + unsigned int nSubtractFeeFromAmount = 0; + BOOST_FOREACH (const CRecipient& recipient, vecSend) + { + if (nValue < 0 || recipient.nAmount < 0) + { + strFailReason = _("Transaction amounts must be positive"); + return false; + } + nValue += recipient.nAmount; + + if (recipient.fSubtractFeeFromAmount) + nSubtractFeeFromAmount++; + } + if (vecSend.empty() || nValue < 0) + { + strFailReason = _("Transaction amounts must be positive"); + return false; + } + + wtxNew.fTimeReceivedIsTxTime = true; + wtxNew.BindWallet(this); + int nextBlockHeight = chainActive.Height() + 1; + CMutableTransaction txNew = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextBlockHeight); + + if (IS_MODE_EXCHANGEWALLET && chainName.isKMD()) + txNew.nLockTime = 0; + else + { + if ( !komodo_hardfork_active((uint32_t)chainActive.Tip()->nTime) ) + txNew.nLockTime = (uint32_t)chainActive.Tip()->nTime + 1; // set to a time close to now + else + txNew.nLockTime = (uint32_t)chainActive.Tip()->GetMedianTimePast(); + } + + // Activates after Overwinter network upgrade + if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) { + if (txNew.nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD){ + strFailReason = _("nExpiryHeight must be less than TX_EXPIRY_HEIGHT_THRESHOLD."); + return false; + } + } + + unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING; + if (!NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) { + max_tx_size = MAX_TX_SIZE_BEFORE_SAPLING; + } +/* + // Discourage fee sniping. + // + // However because of a off-by-one-error in previous versions we need to + // neuter it by setting nLockTime to at least one less than nBestHeight. + // Secondly currently propagation of transactions created for block heights + // corresponding to blocks that were just mined may be iffy - transactions + // aren't re-accepted into the mempool - we additionally neuter the code by + // going ten blocks back. Doesn't yet do anything for sniping, but does act + // to shake out wallet bugs like not showing nLockTime'd transactions at + // all. + txNew.nLockTime = std::max(0, chainActive.Height() - 10); + + // Secondly occasionally randomly pick a nLockTime even further back, so + // that transactions that are delayed after signing for whatever reason, + // e.g. high-latency mix networks and some CoinJoin implementations, have + // better privacy. + if (GetRandInt(10) == 0) + txNew.nLockTime = std::max(0, (int)txNew.nLockTime - GetRandInt(100)); + + assert(txNew.nLockTime <= (unsigned int)chainActive.Height()); + assert(txNew.nLockTime < LOCKTIME_THRESHOLD);*/ + + { + LOCK2(cs_main, cs_wallet); + { + CAmount nFeeRet = 0; + while (true) + { + txNew.vin.clear(); + txNew.vout.clear(); + wtxNew.fFromMe = true; + nChangePosRet = -1; + bool fFirst = true; + + CAmount nTotalValue = nValue; + if (nSubtractFeeFromAmount == 0) + nTotalValue += nFeeRet; + double dPriority = 0; + // vouts to the payees + BOOST_FOREACH (const CRecipient& recipient, vecSend) + { + CTxOut txout(recipient.nAmount, recipient.scriptPubKey); + + if (recipient.fSubtractFeeFromAmount) + { + txout.nValue -= nFeeRet / nSubtractFeeFromAmount; // Subtract fee equally from each selected recipient + + if (fFirst) // first receiver pays the remainder not divisible by output count + { + fFirst = false; + txout.nValue -= nFeeRet % nSubtractFeeFromAmount; + } + } + + if (txout.IsDust(::minRelayTxFee)) + { + if (recipient.fSubtractFeeFromAmount && nFeeRet > 0) + { + if (txout.nValue < 0) + strFailReason = _("The transaction amount is too small to pay the fee"); + else + strFailReason = _("The transaction amount is too small to send after the fee has been deducted"); + } + else + strFailReason = _("Transaction amount too small"); + return false; + } + txNew.vout.push_back(txout); + } + + // Choose coins to use + std::vector > setCoins; + CAmount nValueIn = 0; + interest2 = 0; + std::vector ctrlVec; + coinControl->ListSelected(ctrlVec); + for(const auto& p : ctrlVec) + { + CTransaction tx; + uint256 hashBlock; + if (myGetTransaction(p.hash, tx, hashBlock)) + { + setCoins.push_back(std::pair(tx, p.n)); + } + } + for(const auto& pcoin : setCoins) + { + CAmount nCredit = pcoin.first.vout[pcoin.second].nValue; + nValueIn += nCredit; + //The coin age after the next block (depth+1) is used instead of the current, + //reflecting an assumption the user would accept a bit more delay for + //a chance at a free transaction. + //But mempool inputs might still be in the mempool, so their age stays 0 + if ( !IS_MODE_EXCHANGEWALLET && chainName.isKMD()) + { + interest2 += pcoin.first.vout[pcoin.second].interest; + } + int age = 0; + if (age != 0) + age += 1; + dPriority += (double)nCredit * age; + } + if ( chainName.isKMD() && DONATION_PUBKEY.size() == 66 && interest2 > 5000 ) + { + CScript scriptDonation = CScript() << ParseHex(DONATION_PUBKEY) << OP_CHECKSIG; + CTxOut newTxOut(interest2,scriptDonation); + int32_t nDonationPosRet = txNew.vout.size() - 1; // dont change first or last + std::vector::iterator position = txNew.vout.begin()+nDonationPosRet; + txNew.vout.insert(position, newTxOut); + interest2 = 0; + } + CAmount nChange = (nValueIn - nValue); + if (nSubtractFeeFromAmount == 0) + nChange -= nFeeRet; + + if (nChange > 0) + { + // Fill a vout to ourself + // TODO: pass in scriptChange instead of reservekey so + // change transaction isn't always pay-to-bitcoin-address + CScript scriptChange; + + // coin control: send change to custom address + if (coinControl && !boost::get(&coinControl->destChange)) + scriptChange = GetScriptForDestination(coinControl->destChange); + + // no coin control: send change to newly generated address + else + { + // Note: We use a new key here to keep it from being obvious which side is the change. + // The drawback is that by not reusing a previous key, the change may be lost if a + // backup is restored, if the backup doesn't have the new private key for the change. + // If we reused the old key, it would be possible to add code to look for and + // rediscover unknown transactions that were written with keys of ours to recover + // post-backup change. + + // Reserve a new key pair from key pool + CPubKey vchPubKey; + bool ret; + ret = reservekey.GetReservedKey(vchPubKey); + assert(ret); // should never fail, as we just unlocked + scriptChange = GetScriptForDestination(vchPubKey.GetID()); + } + + CTxOut newTxOut(nChange, scriptChange); + + // We do not move dust-change to fees, because the sender would end up paying more than requested. + // This would be against the purpose of the all-inclusive feature. + // So instead we raise the change and deduct from the recipient. + if (nSubtractFeeFromAmount > 0 && newTxOut.IsDust(::minRelayTxFee)) + { + CAmount nDust = newTxOut.GetDustThreshold(::minRelayTxFee) - newTxOut.nValue; + newTxOut.nValue += nDust; // raise change until no more dust + for (unsigned int i = 0; i < vecSend.size(); i++) // subtract from first recipient + { + if (vecSend[i].fSubtractFeeFromAmount) + { + txNew.vout[i].nValue -= nDust; + if (txNew.vout[i].IsDust(::minRelayTxFee)) + { + strFailReason = _("The transaction amount is too small to send after the fee has been deducted"); + return false; + } + break; + } + } + } + + // Never create dust outputs; if we would, just + // add the dust to the fee. + if (newTxOut.IsDust(::minRelayTxFee)) + { + nFeeRet += nChange; + reservekey.ReturnKey(); + } + else + { + nChangePosRet = txNew.vout.size() - 1; // dont change first or last + std::vector::iterator position = txNew.vout.begin()+nChangePosRet; + txNew.vout.insert(position, newTxOut); + } + } else reservekey.ReturnKey(); + + // Fill vin + // + // Note how the sequence number is set to max()-1 so that the + // nLockTime set above actually works. + for(const auto& coin : setCoins) + txNew.vin.push_back(CTxIn(coin.first.GetHash(),coin.second,CScript(), + std::numeric_limits::max()-1)); + + // Check mempooltxinputlimit to avoid creating a transaction which the local mempool rejects + size_t limit = (size_t)GetArg("-mempooltxinputlimit", 0); + { + LOCK(cs_main); + if (NetworkUpgradeActive(chainActive.Height() + 1, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) { + limit = 0; + } + } + if (limit > 0) { + size_t n = txNew.vin.size(); + if (n > limit) { + strFailReason = _(strprintf("Too many transparent inputs %zu > limit %zu", n, limit).c_str()); + return false; + } + } + + // Grab the current consensus branch ID + auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); + + // Sign + int nIn = 0; + CTransaction txNewConst(txNew); + for(const auto& coin : setCoins) + { + bool signSuccess; + const CScript& scriptPubKey = coin.first.vout[coin.second].scriptPubKey; + SignatureData sigdata; + if (sign) + signSuccess = ProduceSignature(TransactionSignatureCreator( + this, &txNewConst, nIn, coin.first.vout[coin.second].nValue, SIGHASH_ALL), + scriptPubKey, sigdata, consensusBranchId); + else + signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, sigdata, consensusBranchId); + + if (!signSuccess) + { + strFailReason = _("Signing transaction failed"); + return false; + } else { + UpdateTransaction(txNew, nIn, sigdata); + } + + nIn++; + } + + unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION); + + // Remove scriptSigs if we used dummy signatures for fee calculation + if (!sign) { + BOOST_FOREACH (CTxIn& vin, txNew.vin) + vin.scriptSig = CScript(); + } + + // Embed the constructed transaction data in wtxNew. + *static_cast(&wtxNew) = CTransaction(txNew); + + // Limit size + if (nBytes >= max_tx_size) + { + strFailReason = _("Transaction too large"); + return false; + } + + dPriority = wtxNew.ComputePriority(dPriority, nBytes); + + // Can we complete this as a free transaction? + if (fSendFreeTransactions && nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE) + { + // Not enough fee: enough priority? + double dPriorityNeeded = mempool.estimatePriority(nTxConfirmTarget); + // Not enough mempool history to estimate: use hard-coded AllowFree. + if (dPriorityNeeded <= 0 && AllowFree(dPriority)) + break; + + // Small enough, and priority high enough, to send for free + if (dPriorityNeeded > 0 && dPriority >= dPriorityNeeded) + break; + } + + CAmount nFeeNeeded = GetMinimumFee(nBytes, nTxConfirmTarget, mempool); + if ( nFeeNeeded < 5000 ) + nFeeNeeded = 5000; + + // If we made it here and we aren't even able to meet the relay fee on the next pass, give up + // because we must be at the maximum allowed fee. + if (nFeeNeeded < ::minRelayTxFee.GetFee(nBytes)) + { + strFailReason = _("Transaction too large for fee policy"); + return false; + } + + if (nFeeRet >= nFeeNeeded) + break; // Done, enough fee included. + + // Include more fee and try again. + nFeeRet = nFeeNeeded; + continue; + } + } + } + + return true; +} + +/** + * Call after CreateTransaction unless you want to abort + */ +bool TestWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CValidationState& state) +{ + { + LOCK2(cs_main, cs_wallet); + LogPrintf("CommitTransaction:\n%s", wtxNew.ToString()); + { + // This is only to keep the database open to defeat the auto-flush for the + // duration of this scope. This is the only place where this optimization + // maybe makes sense; please don't do it anywhere else. + CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r+") : NULL; + + // Take key pair from key pool so it won't be used again + reservekey.KeepKey(); + + // Add tx to wallet, because if it has change it's also ours, + // otherwise just for transaction history. + AddToWallet(wtxNew, false, pwalletdb); + + // Notify that old coins are spent + std::set setCoins; + BOOST_FOREACH(const CTxIn& txin, wtxNew.vin) + { + CWalletTx &coin = mapWallet[txin.prevout.hash]; + coin.BindWallet(this); + NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED); + } + + if (fFileBacked) + delete pwalletdb; + } + + if (fBroadcastTransactions) + { + // Broadcast + if (!::AcceptToMemoryPool(mempool, state, wtxNew, false, nullptr)) + { + fprintf(stderr,"commit failed\n"); + // This must not fail. The transaction has already been signed and recorded. + LogPrintf("CommitTransaction(): Error: Transaction not valid\n"); + return false; + } + wtxNew.RelayWalletTransaction(); + } + } + return true; } diff --git a/src/test-komodo/testutils.h b/src/test-komodo/testutils.h index bbf702f263d..149366b2cdc 100644 --- a/src/test-komodo/testutils.h +++ b/src/test-komodo/testutils.h @@ -1,8 +1,8 @@ -#ifndef TESTUTILS_H -#define TESTUTILS_H +#pragma once #include "main.h" - +#include "wallet/wallet.h" +#include "consensus/validation.h" #define VCH(a,b) std::vector(a, a + b) @@ -16,14 +16,181 @@ extern std::string notaryPubkey; extern std::string notarySecret; extern CKey notaryKey; +/*** + * @brief Look inside a transaction + * @param tx the transaction to look at + */ +void displayTransaction(const CTransaction& tx); +/**** + * @brief Look inside a block + * @param blk the block to look at + */ +void displayBlock(const CBlock& blk); + +void setConsoleDebugging(bool enable); void setupChain(); +/*** + * Generate a block + * @param block a place to store the block (read from disk) + */ void generateBlock(CBlock *block=NULL); bool acceptTx(const CTransaction tx, CValidationState &state); void acceptTxFail(const CTransaction tx); -void getInputTx(CScript scriptPubKey, CTransaction &txIn); +/**** + * In order to do tests there needs to be inputs to spend. + * This method creates a block and returns a transaction that spends the coinbase. + * @param scriptPubKey + * @returns the transaction + */ +CTransaction getInputTx(CScript scriptPubKey); CMutableTransaction spendTx(const CTransaction &txIn, int nOut=0); std::vector getSig(const CMutableTransaction mtx, CScript inputPubKey, int nIn=0); +class TransactionInProcess +{ +public: + TransactionInProcess(CWallet* wallet) : reserveKey(wallet) {} + CWalletTx transaction; + CReserveKey reserveKey; +}; + +class TestWallet; + +class TestChain +{ +public: + /*** + * ctor to create a chain + */ + TestChain(); + /*** + * dtor to release resources + */ + ~TestChain(); + /*** + * Get the block index at the specified height + * @param height the height (0 indicates current height + * @returns the block index + */ + CBlockIndex *GetIndex(uint32_t height = 0); + /*** + * Get this chains view of the state of the chain + * @returns the view + */ + CCoinsViewCache *GetCoinsViewCache(); + /** + * Generate a block + * @returns the block generated + */ + std::shared_ptr generateBlock(std::shared_ptr wallet, + CValidationState* validationState = nullptr); + /**** + * @brief set the chain time to something reasonable + * @note must be called after generateBlock if you + * want to produce another block + */ + void IncrementChainTime(); + /*** + * @returns the notary's key + */ + CKey getNotaryKey(); + /*** + * Add a transactoion to the mempool + * @param tx the transaction + * @returns the results + */ + CValidationState acceptTx(const CTransaction &tx); + /**** + * @brief attempt to connect a block to the chain + * @param block the block to connect + * @param state where to hold the results + * @param pindex the new chain index + * @param justCheck whether or not to do all checks + * @param checkPOW true to check PoW + * @returns true on success + */ + bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, + bool fJustCheck = false,bool fCheckPOW = false); + + boost::filesystem::path GetDataDir(); +private: + boost::filesystem::path dataDir; + std::string previousNetwork; + void CleanGlobals(); +}; -#endif /* TESTUTILS_H */ +/*** + * An easy-to-use wallet for testing Komodo + */ +class TestWallet : public CWallet +{ +public: + TestWallet(const std::string& name); + TestWallet(const CKey& in, const std::string& name); + ~TestWallet(); + /*** + * @returns the public key + */ + CPubKey GetPubKey() const; + /*** + * @returns the private key + */ + CKey GetPrivKey() const; + /*** + * Sign a typical transaction + * @param hash the hash to sign + * @param hashType SIGHASH_ALL or something similar + * @returns the bytes to add to ScriptSig + */ + std::vector Sign(uint256 hash, unsigned char hashType); + /*** + * Sign a cryptocondition + * @param cc the cryptocondition + * @param hash the hash to sign + * @returns the bytes to add to ScriptSig + */ + std::vector Sign(CC* cc, uint256 hash); + /***** + * @brief create a transaction with 1 recipient (signed) + * @param to who to send funds to + * @param amount + * @param fee + * @returns the transaction + */ + TransactionInProcess CreateSpendTransaction(std::shared_ptr to, CAmount amount, + CAmount fee = 0, bool commit = true); + /************* + * @brief Create a transaction, do not place in mempool + * @note throws std::logic_error if there was a problem + * @param to who to send to + * @param amount the amount to send + * @param fee the fee + * @param txToSpend the specific transaction to spend (ok if not transmitted yet) + * @returns the transaction + */ + TransactionInProcess CreateSpendTransaction(std::shared_ptr to, + CAmount amount, CAmount fee, CCoinControl& coinControl); + /**** + * @brief create a transaction spending a vout that is not yet in the wallet + * @param vecSend the recipients + * @param wtxNew the resultant tx + * @param reserveKey the key used + * @param strFailReason the reason for any failure + * @param outputControl the tx to spend + * @returns true on success + */ + bool CreateTransaction(const std::vector& vecSend, CWalletTx& wtxNew, + CReserveKey& reservekey, std::string& strFailReason, CCoinControl* coinControl); + using CWallet::CommitTransaction; + bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CValidationState& state); + /*** + * Transfer to another user (sends to mempool) + * @param to who to transfer to + * @param amount the amount + * @returns the results + */ + CTransaction Transfer(std::shared_ptr to, CAmount amount, CAmount fee = 0); +private: + CKey key; +}; diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 522f0d8f293..27b3917e027 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -91,7 +91,7 @@ TestingSetup::TestingSetup() // instead of unit tests, but for now we need these here. RegisterAllCoreRPCCommands(tableRPC); #ifdef ENABLE_WALLET - bitdb.MakeMock(); + bitdb->MakeMock(); RegisterWalletRPCCommands(tableRPC); #endif ClearDatadirCache(); @@ -129,8 +129,8 @@ TestingSetup::~TestingSetup() delete pcoinsdbview; delete pblocktree; #ifdef ENABLE_WALLET - bitdb.Flush(true); - bitdb.Reset(); + bitdb->Flush(true); + bitdb->Reset(); #endif boost::filesystem::remove_all(pathTemp); } diff --git a/src/threadsafety.h b/src/threadsafety.h index d01c50abb6b..a5ef4525393 100644 --- a/src/threadsafety.h +++ b/src/threadsafety.h @@ -1,55 +1,72 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_THREADSAFETY_H -#define BITCOIN_THREADSAFETY_H - -#ifdef __clang__ -// TL;DR Add GUARDED_BY(mutex) to member variables. The others are -// rarely necessary. Ex: int nFoo GUARDED_BY(cs_foo); -// -// See http://clang.llvm.org/docs/LanguageExtensions.html#threadsafety -// for documentation. The clang compiler can do advanced static analysis -// of locking when given the -Wthread-safety option. -#define LOCKABLE __attribute__((lockable)) -#define SCOPED_LOCKABLE __attribute__((scoped_lockable)) -#define GUARDED_BY(x) __attribute__((guarded_by(x))) -#define GUARDED_VAR __attribute__((guarded_var)) -#define PT_GUARDED_BY(x) __attribute__((pt_guarded_by(x))) -#define PT_GUARDED_VAR __attribute__((pt_guarded_var)) -#define ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__))) -#define ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__))) -#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((exclusive_lock_function(__VA_ARGS__))) -#define SHARED_LOCK_FUNCTION(...) __attribute__((shared_lock_function(__VA_ARGS__))) -#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((exclusive_trylock_function(__VA_ARGS__))) -#define SHARED_TRYLOCK_FUNCTION(...) __attribute__((shared_trylock_function(__VA_ARGS__))) -#define UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__))) -#define LOCK_RETURNED(x) __attribute__((lock_returned(x))) -#define LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__))) -#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((exclusive_locks_required(__VA_ARGS__))) -#define SHARED_LOCKS_REQUIRED(...) __attribute__((shared_locks_required(__VA_ARGS__))) -#define NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) +#ifndef THREAD_SAFETY_ANALYSIS_13_H +#define THREAD_SAFETY_ANALYSIS_13_H + +// Enable thread safety attributes only with clang. +// The attributes can be safely erased when compiling with other compilers. +#if defined(__clang__) && (!defined(SWIG)) +#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) #else -#define LOCKABLE -#define SCOPED_LOCKABLE -#define GUARDED_BY(x) -#define GUARDED_VAR -#define PT_GUARDED_BY(x) -#define PT_GUARDED_VAR -#define ACQUIRED_AFTER(...) -#define ACQUIRED_BEFORE(...) -#define EXCLUSIVE_LOCK_FUNCTION(...) -#define SHARED_LOCK_FUNCTION(...) -#define EXCLUSIVE_TRYLOCK_FUNCTION(...) -#define SHARED_TRYLOCK_FUNCTION(...) -#define UNLOCK_FUNCTION(...) -#define LOCK_RETURNED(x) -#define LOCKS_EXCLUDED(...) -#define EXCLUSIVE_LOCKS_REQUIRED(...) -#define SHARED_LOCKS_REQUIRED(...) -#define NO_THREAD_SAFETY_ANALYSIS -#endif // __GNUC__ - -#endif // BITCOIN_THREADSAFETY_H +#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op +#endif + +#define CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) + +#define SCOPED_CAPABILITY \ + THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) + +#define GUARDED_BY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) + +#define PT_GUARDED_BY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) + +#define ACQUIRED_BEFORE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) + +#define ACQUIRED_AFTER(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) + +#define REQUIRES(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) + +#define REQUIRES_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) + +#define ACQUIRE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) + +#define ACQUIRE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) + +#define RELEASE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) + +#define RELEASE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) + +#define RELEASE_GENERIC(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_generic_capability(__VA_ARGS__)) + +#define TRY_ACQUIRE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) + +#define TRY_ACQUIRE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) + +#define EXCLUDES(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) + +#define ASSERT_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) + +#define ASSERT_SHARED_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) + +#define RETURN_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) + +#define NO_THREAD_SAFETY_ANALYSIS \ + THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) + +#endif // THREAD_SAFETY_ANALYSIS_13_H diff --git a/src/tui/README.md b/src/tui/README.md index 61e733794b4..960c1e7d088 100644 --- a/src/tui/README.md +++ b/src/tui/README.md @@ -1,6 +1,6 @@ # Komodo Cryptoconditons Terminal User Interfaces (aka TUIs) -These tools creating for demonstration and partial automation of Komodo cryptoconditions modules testing. (RogueCC game, AssetsCC, OraclesCC, GatewaysCC, MarmaraCC, ...) +These tools creating for demonstration and partial automation of Komodo cryptoconditions modules testing. (RogueCC game, AssetsCC, OraclesCC, GatewaysCC,...) Developer installation (on Ubuntu 18.04) : @@ -42,10 +42,6 @@ Have files uploader/downloader functionality - also there is a AWS branch for AW At the moment raw version of manual gateway how-to guide can be found here: https://docs.komodoplatform.com/cc/contracts/gateways/scenarios/tutorial.html I advice to read it before you start use this tool to understand the flow. -# TUI for MarmaraCC - -`python3 marmara_tui.py` - ![alt text](https://i.imgur.com/uonMWHl.png) # TUI for AssetsCC (not much finished) diff --git a/src/tui/tui_marmara.py b/src/tui/tui_marmara.py deleted file mode 100755 index cfe6288902c..00000000000 --- a/src/tui/tui_marmara.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python3 - -from lib import rpclib, tuilib -import os -import time - - -header = "\ -___ ___ _____ _ _ _____ \n\ -| \/ | |_ _| | | |_ _|\n\ -| . . | __ _ _ __ _ __ ___ __ _ _ __ __ _ | | | | | | | |\n\ -| |\/| |/ _` | '__| '_ ` _ \ / _` | '__/ _` | | | | | | | | |\n\ -| | | | (_| | | | | | | | | (_| | | | (_| | | | | |_| |_| |_\n\ -\_| |_/\__,_|_| |_| |_| |_|\__,_|_| \__,_| \_/ \___/ \___/\n" - - -menuItems = [ - {"Check current connection": tuilib.getinfo_tui}, - {"Check mempool": tuilib.print_mempool}, - {"Check MARMARA info": tuilib.marmara_info_tui}, - {"Lock funds for MARMARA": tuilib.marmara_lock_tui}, - {"Request MARMARA cheque": tuilib.marmara_receive_tui}, - {"Issue MARMARA cheque": tuilib.marmara_issue_tui}, - {"Check credit loop status": tuilib.marmara_creditloop_tui}, - {"Settle MARMARA loop": tuilib.marmara_settlement_tui}, - {"Exit": exit} -] - - -def main(): - while True: - os.system('clear') - print(tuilib.colorize(header, 'pink')) - print(tuilib.colorize('CLI version 0.1\n', 'green')) - for item in menuItems: - print(tuilib.colorize("[" + str(menuItems.index(item)) + "] ", 'blue') + list(item.keys())[0]) - choice = input(">> ") - try: - if int(choice) < 0: - raise ValueError - # Call the matching function - if list(menuItems[int(choice)].keys())[0] == "Exit": - list(menuItems[int(choice)].values())[0]() - else: - list(menuItems[int(choice)].values())[0](rpc_connection) - except (ValueError, IndexError): - pass - - -if __name__ == "__main__": - while True: - chain = input("Input assetchain name (-ac_name= value) you want to work with: ") - try: - print(tuilib.colorize("Welcome to the MarmaraCC TUI!\n" - "Please provide asset chain RPC connection details for initialization", "blue")) - rpc_connection = tuilib.def_credentials(chain) - rpclib.getinfo(rpc_connection) - except Exception: - print(tuilib.colorize("Cant connect to RPC! Please re-check credentials.", "pink")) - else: - print(tuilib.colorize("Succesfully connected!\n", "green")) - with (open("lib/logo.txt", "r")) as logo: - for line in logo: - print(line, end='') - time.sleep(0.04) - print("\n") - break - main() diff --git a/src/txdb.cpp b/src/txdb.cpp index 762166cfdb7..b87d3487439 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2016-2022 The Zcash developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -26,6 +27,7 @@ #include "pow.h" #include "uint256.h" #include "core_io.h" +#include "komodo_bitcoind.h" #include @@ -214,10 +216,11 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, return db.WriteBatch(batch); } -CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe, bool compression, int maxOpenFiles) : CDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe, compression, maxOpenFiles) { +CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe, bool compression, int maxOpenFiles) + : CDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe, compression, maxOpenFiles) { } -bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) { +bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) const { return Read(make_pair(DB_BLOCK_FILES, nFile), info); } @@ -228,12 +231,12 @@ bool CBlockTreeDB::WriteReindexing(bool fReindexing) { return Erase(DB_REINDEX_FLAG); } -bool CBlockTreeDB::ReadReindexing(bool &fReindexing) { +bool CBlockTreeDB::ReadReindexing(bool &fReindexing) const { fReindexing = Exists(DB_REINDEX_FLAG); return true; } -bool CBlockTreeDB::ReadLastBlockFile(int &nFile) { +bool CBlockTreeDB::ReadLastBlockFile(int &nFile) const { return Read(DB_LAST_BLOCK, nFile); } @@ -283,14 +286,36 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const { return true; } -bool CBlockTreeDB::WriteBatchSync(const std::vector >& fileInfo, int nLastFile, const std::vector& blockinfo) { +/*** + * Write a batch of records and sync + * @param fileInfo the records to write + * @param nLastFile the value for DB_LAST_BLOCK + * @param blockinfo the index records to write + * @returns true on success + */ +bool CBlockTreeDB::WriteBatchSync(const std::vector >& fileInfo, int nLastFile, const std::vector& blockinfo) { CDBBatch batch(*this); - for (std::vector >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) { - batch.Write(make_pair(DB_BLOCK_FILES, it->first), *it->second); + for (const auto& it : fileInfo) { + batch.Write(make_pair(DB_BLOCK_FILES, it.first), *it.second); } batch.Write(DB_LAST_BLOCK, nLastFile); - for (std::vector::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) { - batch.Write(make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it)); + for (const auto& it : blockinfo) { + std::pair key = make_pair(DB_BLOCK_INDEX, it->GetBlockHash()); + try { + CDiskBlockIndex dbindex {it, [this, &key]() { + // It can happen that the index entry is written, then the Equihash solution is cleared from memory, + // then the index entry is rewritten. In that case we must read the solution from the old entry. + CDiskBlockIndex dbindex_old; + if (!Read(key, dbindex_old)) { + LogPrintf("%s: Failed to read index entry", __func__); + throw runtime_error("Failed to read index entry"); + } + return dbindex_old.GetSolution(); + }}; + batch.Write(key, dbindex); + } catch (const runtime_error&) { + return false; + } } return WriteBatch(batch, true); } @@ -303,7 +328,11 @@ bool CBlockTreeDB::EraseBatchSync(const std::vector& blockin return WriteBatch(batch, true); } -bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) { +bool CBlockTreeDB::ReadDiskBlockIndex(const uint256 &blockhash, CDiskBlockIndex &dbindex) const { + return Read(make_pair(DB_BLOCK_INDEX, blockhash), dbindex); +} + +bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) const { return Read(make_pair(DB_TXINDEX, txid), pos); } @@ -314,7 +343,7 @@ bool CBlockTreeDB::WriteTxIndex(const std::vector return WriteBatch(batch); } -bool CBlockTreeDB::ReadSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) { +bool CBlockTreeDB::ReadSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) const { return Read(make_pair(DB_SPENTINDEX, key), value); } @@ -436,7 +465,6 @@ bool CBlockTreeDB::ReadAddressIndex(uint160 addressHash, int type, } bool getAddressFromIndex(const int &type, const uint160 &hash, std::string &address); -uint32_t komodo_segid32(char *coinaddr); #define DECLARE_IGNORELIST std::map ignoredMap = { \ {"RReUxSs5hGE39ELU23DfydX8riUuzdrHAE", 1}, \ @@ -464,7 +492,7 @@ bool CBlockTreeDB::Snapshot2(std::map &addressAmounts, Un int64_t utxos = 0; int64_t ignoredAddresses = 0, cryptoConditionsUTXOs = 0, cryptoConditionsTotals = 0; DECLARE_IGNORELIST boost::scoped_ptr iter(NewIterator()); - //std::map addressAmounts; + for (iter->SeekToLast(); iter->Valid(); iter->Prev()) { boost::this_thread::interruption_point(); @@ -475,7 +503,7 @@ bool CBlockTreeDB::Snapshot2(std::map &addressAmounts, Un iter->GetKey(keyObj); char chType = keyObj.first; CAddressIndexIteratorKey indexKey = keyObj.second; - //fprintf(stderr, "chType=%d\n", chType); + if (chType == DB_ADDRESSUNSPENTINDEX) { try { @@ -502,18 +530,14 @@ bool CBlockTreeDB::Snapshot2(std::map &addressAmounts, Un if ( pos == addressAmounts.end() ) { // insert new address + utxo amount - //fprintf(stderr, "inserting new address %s with amount %li\n", address.c_str(), nValue); addressAmounts[address] = nValue; totalAddresses++; } else { // update unspent tally for this address - //fprintf(stderr, "updating address %s with new utxo amount %li\n", address.c_str(), nValue); addressAmounts[address] += nValue; } - //fprintf(stderr,"{\"%s\", %.8f},\n",address.c_str(),(double)nValue/COIN); - // total += nValue; utxos++; total += nValue; } @@ -530,8 +554,7 @@ bool CBlockTreeDB::Snapshot2(std::map &addressAmounts, Un break; } } - //fprintf(stderr, "total=%f, totalAddresses=%li, utxos=%li, ignored=%li\n", (double) total / COIN, totalAddresses, utxos, ignoredAddresses); - + // this is for the snapshot RPC, you can skip this by passing a 0 as the last argument. if (ret) { @@ -557,17 +580,16 @@ bool CBlockTreeDB::Snapshot2(std::map &addressAmounts, Un return true; } -extern std::vector > vAddressSnapshot; +extern std::vector > vAddressSnapshot; // daily snapshot UniValue CBlockTreeDB::Snapshot(int top) { - int topN = 0; std::vector > vaddr; - //std::vector >> tokenids; std::map addressAmounts; UniValue result(UniValue::VOBJ); UniValue addressesSorted(UniValue::VARR); result.push_back(Pair("start_time", (int) time(NULL))); + if ( (vAddressSnapshot.size() > 0 && top < 0) || (Snapshot2(addressAmounts,&result) && top >= 0) ) { if ( top > -1 ) @@ -650,7 +672,7 @@ bool CBlockTreeDB::WriteTimestampBlockIndex(const CTimestampBlockIndexKey &block return WriteBatch(batch); } -bool CBlockTreeDB::ReadTimestampBlockIndex(const uint256 &hash, unsigned int <imestamp) { +bool CBlockTreeDB::ReadTimestampBlockIndex(const uint256 &hash, unsigned int <imestamp) const { CTimestampBlockIndexValue(lts); if (!Read(std::make_pair(DB_BLOCKHASHINDEX, hash), lts)) @@ -664,7 +686,7 @@ bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) { return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0'); } -bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) { +bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) const { char ch; if (!Read(std::make_pair(DB_FLAG, name), ch)) return false; @@ -712,7 +734,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts() pindexNew->nTime = diskindex.nTime; pindexNew->nBits = diskindex.nBits; pindexNew->nNonce = diskindex.nNonce; - pindexNew->nSolution = diskindex.nSolution; + // the Equihash solution will be loaded lazily from the dbindex entry pindexNew->nStatus = diskindex.nStatus; pindexNew->nCachedBranchId = diskindex.nCachedBranchId; pindexNew->nTx = diskindex.nTx; @@ -720,14 +742,24 @@ bool CBlockTreeDB::LoadBlockIndexGuts() pindexNew->nSaplingValue = diskindex.nSaplingValue; pindexNew->segid = diskindex.segid; pindexNew->nNotaryPay = diskindex.nNotaryPay; -//fprintf(stderr,"loadguts ht.%d\n",pindexNew->nHeight); - // Consistency checks - auto header = pindexNew->GetBlockHeader(); - if (header.GetHash() != pindexNew->GetBlockHash()) - return error("LoadBlockIndex(): block header inconsistency detected: on-disk = %s, in-memory = %s", - diskindex.ToString(), pindexNew->ToString()); + if ( 0 ) // POW will be checked before any block is connected { + // Consistency checks + CBlockHeader header; + { + LOCK(cs_main); + try { + header = pindexNew->GetBlockHeader(); + } catch (const runtime_error&) { + return error("LoadBlockIndex(): failed to read index entry: diskindex hash = %s", + diskindex.GetBlockHash().ToString()); + } + } + if (header.GetHash() != pindexNew->GetBlockHash()) + return error("LoadBlockIndex(): block header inconsistency detected: on-disk = %s, in-memory = %s", + diskindex.ToString(), pindexNew->ToString()); + uint8_t pubkey33[33]; komodo_index2pubkey33(pubkey33,pindexNew,pindexNew->nHeight); if (!CheckProofOfWork(header,pubkey33,pindexNew->nHeight,Params().GetConsensus())) diff --git a/src/txdb.h b/src/txdb.h index 195f4c183c6..0e7908c7d88 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2016-2022 The Zcash developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -45,6 +46,7 @@ struct CTimestampBlockIndexValue; struct CSpentIndexKey; struct CSpentIndexValue; class uint256; +class CDiskBlockIndex; //! -dbcache default (MiB) static const int64_t nDefaultDbCache = 450; @@ -53,7 +55,9 @@ static const int64_t nMaxDbCache = sizeof(void*) > 4 ? 16384 : 1024; //! min. -dbcache in (MiB) static const int64_t nMinDbCache = 4; -/** CCoinsView backed by the coin database (chainstate/) */ +/** + * CCoinsView backed by the coin database (chainstate/) +*/ class CCoinsViewDB : public CCoinsView { protected: @@ -65,7 +69,17 @@ class CCoinsViewDB : public CCoinsView bool GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const; bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const; bool GetNullifier(const uint256 &nf, ShieldedType type) const; + /*** + * @param txid the transaction id + * @param coins the coins within the txid + * @returns true on success + */ bool GetCoins(const uint256 &txid, CCoins &coins) const; + /**** + * Determine if a txid exists + * @param txid + * @returns true if the txid exists in the database + */ bool HaveCoins(const uint256 &txid) const; uint256 GetBestBlock() const; uint256 GetBestAnchor(ShieldedType type) const; @@ -80,42 +94,210 @@ class CCoinsViewDB : public CCoinsView bool GetStats(CCoinsStats &stats) const; }; -/** Access to the block database (blocks/index/) */ +/** + * Access to the block database (blocks/index/) + * This database consists of: + * - CBlockFileInfo records that contain info about the individual files that store blocks + * - CBlockIndex info about the blocks themselves + * - txid / CDiskTxPos index + * - spent index + * - unspent index + * - address / amount + * - timestamp index + * - block hash / timestamp index + */ class CBlockTreeDB : public CDBWrapper { public: + /**** + * ctor + * + * @param nCacheSize leveldb cache size + * @param fMemory use leveldb memory environment + * @param fWipe wipe data + * @param compression enable leveldb compression + * @param maxOpenFiles leveldb max open files + */ CBlockTreeDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false, bool compression = true, int maxOpenFiles = 1000); private: CBlockTreeDB(const CBlockTreeDB&); void operator=(const CBlockTreeDB&); public: - bool WriteBatchSync(const std::vector >& fileInfo, int nLastFile, const std::vector& blockinfo); + /*** + * Write a batch of records and sync + * @param fileInfo the block file info records to write + * @param nLastFile the value for DB_LAST_BLOCK + * @param blockinfo the block index records to write + * @returns true on success + */ + bool WriteBatchSync(const std::vector >& fileInfo, int nLastFile, + const std::vector& blockinfo); + /*** + * Erase a batch of block index records and sync + * @param blockinfo the records + * @returns true on success + */ bool EraseBatchSync(const std::vector& blockinfo); - bool ReadBlockFileInfo(int nFile, CBlockFileInfo &fileinfo); - bool ReadLastBlockFile(int &nFile); + /*** + * Read the file information + * @param nFile the file to read + * @param fileinfo where to store the results + * @returns true on success + */ + bool ReadBlockFileInfo(int nFile, CBlockFileInfo &fileinfo) const; + /**** + * Read the value of DB_LAST_BLOCK + * @param nFile where to store the results + * @returns true on success + */ + bool ReadLastBlockFile(int &nFile) const; + /*** + * Write to the DB_REINDEX_FLAG + * @param fReindex true to set DB_REINDEX_FLAG, false to erase the key + * @returns true on success + */ bool WriteReindexing(bool fReindex); - bool ReadReindexing(bool &fReindex); - bool ReadTxIndex(const uint256 &txid, CDiskTxPos &pos); + /**** + * Retrieve the value of DB_REINDEX_FLAG + * @param fReindex true if DB_REINDEX_FLAG exists + * @returns true on success + */ + bool ReadReindexing(bool &fReindex) const; + + bool ReadDiskBlockIndex(const uint256 &blockhash, CDiskBlockIndex &dbindex) const; + /*** + * Retrieve the location of a particular transaction index value + * @param txid what to look for + * @param pos the results + * @returns true on success + */ + bool ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) const; + /**** + * Write transaction index records + * @param list the records to write + * @returns true on success + */ bool WriteTxIndex(const std::vector > &list); - bool ReadSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value); + /**** + * Read a value from the spent index + * @param key the key + * @param value the value + * @returns true on success + */ + bool ReadSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) const; + /**** + * Update a batch of spent index entries + * @param vect the entries to add/update + * @returns true on success + */ bool UpdateSpentIndex(const std::vector >&vect); + /**** + * Update the unspent indexes for an address + * @param vect the name/value pairs + * @returns true on success + */ bool UpdateAddressUnspentIndex(const std::vector >&vect); + /**** + * Read the unspent key/value pairs for a particular address + * @param addressHash the address + * @param type the address type + * @param vect the results + * @returns true on success + */ bool ReadAddressUnspentIndex(uint160 addressHash, int type, std::vector > &vect); + /***** + * Write a batch of address index / amount records + * @param vect a collection of address index/amount records + * @returns true on success + */ bool WriteAddressIndex(const std::vector > &vect); + /**** + * Remove a batch of address index / amount records + * @param vect the records to erase + * @returns true on success + */ bool EraseAddressIndex(const std::vector > &vect); + /**** + * Read a range of address index / amount records for a particular address + * @param addressHash the address to look for + * @param type the address type + * @param addressIndex the address index / amount records found + * @param start the starting index + * @param end the end + * @returns true on success + */ bool ReadAddressIndex(uint160 addressHash, int type, std::vector > &addressIndex, int start = 0, int end = 0); + /**** + * Write a timestamp entry to the db + * @param timestampIndex the record to write + * @returns true on success + */ bool WriteTimestampIndex(const CTimestampIndexKey ×tampIndex); - bool ReadTimestampIndex(const unsigned int &high, const unsigned int &low, const bool fActiveOnly, std::vector > &vect); + /**** + * Read the timestamp entry from the db + * @param high ending timestamp (most recent) + * @param low starting timestamp (oldest) + * @param fActiveOnly only include on-chain active entries in the results + * @param vect the results + * @returns true on success + */ + bool ReadTimestampIndex(const unsigned int &high, const unsigned int &low, const bool fActiveOnly, + std::vector > &vect); + /**** + * Write a block hash / timestamp record + * @param blockhashIndex the key (the hash) + * @param logicalts the value (the timestamp) + * @returns true on success + */ bool WriteTimestampBlockIndex(const CTimestampBlockIndexKey &blockhashIndex, const CTimestampBlockIndexValue &logicalts); - bool ReadTimestampBlockIndex(const uint256 &hash, unsigned int &logicalTS); + /***** + * Given a hash, find its timestamp + * @param hash the hash (the key) + * @param logicalTS the timestamp (the value) + * @returns true on success + */ + bool ReadTimestampBlockIndex(const uint256 &hash, unsigned int &logicalTS) const; + /*** + * Store a flag value in the DB + * @param name the key + * @param fValue the value + * @returns true on success + */ bool WriteFlag(const std::string &name, bool fValue); - bool ReadFlag(const std::string &name, bool &fValue); + /*** + * Read a flag value from the DB + * @param name the key + * @param fValue the value + * @returns true on success + */ + bool ReadFlag(const std::string &name, bool &fValue) const; + /**** + * Load the block headers from disk + * NOTE: this does no consistency check beyond verifying records exist + * @returns true on success + */ bool LoadBlockIndexGuts(); + /**** + * Check if a block is on the active chain + * @param hash the block hash + * @returns true if the block exists on the active chain + */ bool blockOnchainActive(const uint256 &hash); + /**** + * Get a snapshot + * @param top max number of results, sorted by amount descending (aka richlist) + * @returns the data ( a collection of (addr, amount, segid) ) + */ UniValue Snapshot(int top); + /**** + * Get a snapshot + * @param addressAmounts the results + * @param ret results summary (passing nullptr skips compiling this summary) + * @returns true on success + */ bool Snapshot2(std::map &addressAmounts, UniValue *ret); }; diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 2ff9dd051ff..69f84b1c241 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -31,7 +31,9 @@ #include "utilmoneystr.h" #include "validationinterface.h" #include "version.h" -#define _COINBASE_MATURITY 100 +#include "komodo_globals.h" +#include "komodo_utils.h" +#include "komodo_bitcoind.h" using namespace std; @@ -125,7 +127,6 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, if (!tx.IsCoinImport()) { for (unsigned int i = 0; i < tx.vin.size(); i++) { - if (tx.IsPegsImport() && i==0) continue; mapNextTx[tx.vin[i].prevout] = CInPoint(&tx, i); } } @@ -153,7 +154,6 @@ void CTxMemPool::addAddressIndex(const CTxMemPoolEntry &entry, const CCoinsViewC uint256 txhash = tx.GetHash(); for (unsigned int j = 0; j < tx.vin.size(); j++) { - if (tx.IsPegsImport() && j==0) continue; const CTxIn input = tx.vin[j]; const CTxOut &prevout = view.GetOutputFor(input); @@ -259,7 +259,6 @@ void CTxMemPool::addSpentIndex(const CTxMemPoolEntry &entry, const CCoinsViewCac uint256 txhash = tx.GetHash(); for (unsigned int j = 0; j < tx.vin.size(); j++) { - if (tx.IsPegsImport() && j==0) continue; const CTxIn input = tx.vin[j]; const CTxOut &prevout = view.GetOutputFor(input); @@ -391,15 +390,8 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list& rem } } -extern uint64_t ASSETCHAINS_TIMELOCKGTE; -int64_t komodo_block_unlocktime(uint32_t nHeight); - void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags) { - // Remove transactions spending a coinbase which are now immature - extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - COINBASE_MATURITY = _COINBASE_MATURITY; // Remove transactions spending a coinbase which are now immature and no-longer-final transactions LOCK(cs); list transactionsToRemove; @@ -414,7 +406,7 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem continue; const CCoins *coins = pcoins->AccessCoins(txin.prevout.hash); if (nCheckFrequency != 0) assert(coins); - if (!coins || (coins->IsCoinBase() && (((signed long)nMemPoolHeight) - coins->nHeight < COINBASE_MATURITY) && + if (!coins || (coins->IsCoinBase() && (((signed long)nMemPoolHeight) - coins->nHeight < Params().CoinbaseMaturity()) && ((signed long)nMemPoolHeight < komodo_block_unlocktime(coins->nHeight) && coins->IsAvailable(0) && coins->vout[0].nValue >= ASSETCHAINS_TIMELOCKGTE))) { transactionsToRemove.push_back(tx); @@ -508,25 +500,26 @@ void CTxMemPool::removeConflicts(const CTransaction &tx, std::list } } -int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag); -extern char ASSETCHAINS_SYMBOL[]; - void CTxMemPool::removeExpired(unsigned int nBlockHeight) { - CBlockIndex *tipindex; + std::list transactionsToRemove; // Remove expired txs from the mempool LOCK(cs); - list transactionsToRemove; for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) { const CTransaction& tx = it->GetTx(); - tipindex = chainActive.LastTip(); + CBlockIndex *tipindex = chainActive.Tip(); // TODO: should be under cs_main lock? + + bool fInterestNotValidated = chainName.isKMD() // KMD + && tipindex != nullptr // chain has blocks on it + && !komodo_validate_interest(tx, tipindex->nHeight + 1, tipindex->GetMedianTimePast() + 777); // TODO: should not we use nBlockHeight instead of tipindex? - bool fInterestNotValidated = ASSETCHAINS_SYMBOL[0] == 0 && tipindex != 0 && komodo_validate_interest(tx,tipindex->nHeight+1,tipindex->GetMedianTimePast() + 777,0) < 0; if (IsExpiredTx(tx, nBlockHeight) || fInterestNotValidated) { if (fInterestNotValidated && tipindex != 0) - LogPrintf("Removing interest violate txid.%s nHeight.%d nTime.%u vs locktime.%u\n",tx.GetHash().ToString(),tipindex->nHeight+1,tipindex->GetMedianTimePast() + 777,tx.nLockTime); + LogPrintf("Removing interest violate txid.%s nHeight.%d nTime.%u vs locktime.%u\n", + tx.GetHash().ToString(),tipindex->nHeight+1, + tipindex->GetMedianTimePast() + 777,tx.nLockTime); transactionsToRemove.push_back(tx); } } diff --git a/src/util.cpp b/src/util.cpp index fa62ba1ff85..15a5ce6b1a2 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -30,7 +30,7 @@ #include "sync.h" #include "utilstrencodings.h" #include "utiltime.h" -#include "komodo_defs.h" +#include "komodo_globals.h" #include #include @@ -528,52 +528,74 @@ void PrintExceptionContinue(const std::exception* pex, const char* pszThread) strMiscWarning = message; } -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -//int64_t MAX_MONEY = 200000000 * 100000000LL; -boost::filesystem::path GetDefaultDataDir() +namespace fs = boost::filesystem; + +/** + * @brief get the OS-specific default application data directory + * @note Windows: be "C:\Users\[username]\AppData\Roaming" + * @note Mac: ~/Library/Application Support + * @note Unix: ~/ + * @returns the default path to the application data directory + */ +boost::filesystem::path GetAppDir() { - namespace fs = boost::filesystem; - char symbol[KOMODO_ASSETCHAIN_MAXLEN]; - if ( ASSETCHAINS_SYMBOL[0] != 0 ){ - strcpy(symbol,ASSETCHAINS_SYMBOL); - } - - else symbol[0] = 0; - // Windows < Vista: C:\Documents and Settings\Username\Application Data\Zcash - // Windows >= Vista: C:\Users\Username\AppData\Roaming\Zcash - // Mac: ~/Library/Application Support/Zcash - // Unix: ~/.zcash + // Windows < Vista: C:\Documents and Settings\Username\Application Data + // Windows >= Vista: C:\Users\Username\AppData\Roaming + // Mac: ~/Library/Application Support + // Unix: ~ + fs::path pathRet; + #ifdef _WIN32 // Windows - if ( symbol[0] == 0 ) - return GetSpecialFolderPath(CSIDL_APPDATA) / "Komodo"; - else return GetSpecialFolderPath(CSIDL_APPDATA) / "Komodo" / symbol; + pathRet = GetSpecialFolderPath(CSIDL_APPDATA); #else - fs::path pathRet; + // Linux or Mac char* pszHome = getenv("HOME"); if (pszHome == NULL || strlen(pszHome) == 0) pathRet = fs::path("/"); else pathRet = fs::path(pszHome); -#ifdef MAC_OSX + #ifdef MAC_OSX // Mac - pathRet /= "Library/Application Support"; + pathRet /= "Library"; TryCreateDirectory(pathRet); - if ( symbol[0] == 0 ) - return pathRet / "Komodo"; + pathRet /= "Application Support"; + TryCreateDirectory(pathRet); // not sure why this is needed as GetDataDir will create the whole path + #endif +#endif + return pathRet; +} + +/**** + * @brief get the OS-specific default komodod data directory + * @note Windows: be "C:\Users\[username]\AppData\Roaming\Komodo" + * @note Mac: ~/Library/Application Support/Komodo + * @note Unix: ~/.komodo + * @returns the default path to the Komodo data directory + */ +boost::filesystem::path GetDefaultDataDir() +{ + fs::path pathRet = GetAppDir(); + +#if defined(_WIN32) || defined(MAC_OSX) + if (chainName.isKMD()) + { + pathRet /= "Komodo"; + } else { pathRet /= "Komodo"; TryCreateDirectory(pathRet); - return pathRet / symbol; + pathRet /= chainName.symbol(); } + return pathRet; #else // Unix - if ( symbol[0] == 0 ) + if (chainName.isKMD()) return pathRet / ".komodo"; - else return pathRet / ".komodo" / symbol; -#endif + else + return pathRet / ".komodo" / chainName.symbol(); #endif } @@ -649,7 +671,13 @@ const boost::filesystem::path GetExportDir() return path; } - +/**** + * @brief determine the data directory + * @note looks at the -datadir command-line parameter or OS-specific defaults + * @note creates the directory if it does not already exist + * @param fNetSpecific if true, adds network-specific subdirectory (i.e. "regtest" or "testnet3") + * @returns the full OS-specific data directory including Komodo (i.e. "~/.komodo") + */ const boost::filesystem::path &GetDataDir(bool fNetSpecific) { namespace fs = boost::filesystem; @@ -677,8 +705,6 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific) path /= BaseParams().DataDir(); fs::create_directories(path); - //std::string assetpath = path + "/assets"; - //boost::filesystem::create_directory(assetpath); return path; } @@ -691,8 +717,8 @@ void ClearDatadirCache() boost::filesystem::path GetConfigFile() { char confname[512]; - if ( !mapArgs.count("-conf") && ASSETCHAINS_SYMBOL[0] != 0 ){ - sprintf(confname,"%s.conf",ASSETCHAINS_SYMBOL); + if ( !mapArgs.count("-conf") && !chainName.isKMD() ){ + sprintf(confname,"%s.conf",chainName.symbol().c_str()); } else { @@ -735,7 +761,6 @@ void ReadConfigFile(map& mapSettingsRet, } // If datadir is changed in .conf file: ClearDatadirCache(); - extern uint16_t BITCOIND_RPCPORT; BITCOIND_RPCPORT = GetArg("-rpcport",BaseParams().RPCPort()); } diff --git a/src/util.h b/src/util.h index 17bf19952b0..bc4e31f9768 100644 --- a/src/util.h +++ b/src/util.h @@ -139,8 +139,39 @@ int RaiseFileDescriptorLimit(int nMinFD); void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest); bool TryCreateDirectory(const boost::filesystem::path& p); +/** + * @brief get the OS-specific default application data directory + * @note Windows: be "C:\Users\[username]\AppData\Roaming" + * @note Mac: ~/Library/Application Support + * @note Unix: ~/ + * @returns the default path to the application data directory + */ +boost::filesystem::path GetAppDir(); +/**** + * @brief get the OS-specific default komodod data directory + * @note Windows: be "C:\Users\[username]\AppData\Roaming\Komodo" + * @note Mac: ~/Library/Application Support/Komodo + * @note Unix: ~/.komodo + * @returns the default path to the Komodo data directory + */ boost::filesystem::path GetDefaultDataDir(); +/**** + * @brief determine the data directory + * @note looks at the -datadir command-line parameter or OS-specific defaults + * @note creates the directory if it does not already exist + * @param fNetSpecific if true, adds network-specific subdirectory (i.e. "regtest" or "testnet3") + * @returns the full OS-specific data directory including Komodo (i.e. "~/.komodo") + */ const boost::filesystem::path &GetDataDir(bool fNetSpecific = true); +/** + * @brief get the OS-specific default application data directory + * @note Windows: be "C:\Users\[username]\AppData\Roaming" + * @note Mac: ~/Library/Application Support + * @note Unix: ~/ + * @returns the default path to the application data directory + */ +boost::filesystem::path GetAppDir(); + void ClearDatadirCache(); boost::filesystem::path GetConfigFile(); #ifndef _WIN32 diff --git a/src/utiltime.cpp b/src/utiltime.cpp index f1a408a31d4..6c1afec5604 100644 --- a/src/utiltime.cpp +++ b/src/utiltime.cpp @@ -9,43 +9,66 @@ #include "utiltime.h" +#include #include #include #include -using namespace std; - static int64_t nMockTime = 0; //! For unit testing +/*** + * Get the current time + */ int64_t GetTime() { - if (nMockTime) return nMockTime; + if (nMockTime) + return nMockTime; return time(NULL); } +/*** + * Set the current time (for unit testing) + * @param nMocKtimeIn the time that will be returned by GetTime() + */ void SetMockTime(int64_t nMockTimeIn) { nMockTime = nMockTimeIn; } +/*** + * @returns the system time in milliseconds since the epoch (1/1/1970) + */ int64_t GetTimeMillis() { return std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()).count(); } +/**** + * @returns the system time in microseconds since the epoch (1/1/1970) + */ int64_t GetTimeMicros() { return std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()).count(); } +/**** + * @param n the number of milliseconds to put the current thread to sleep + */ void MilliSleep(int64_t n) { + //std::this_thread::sleep_for(std::chrono::milliseconds(n)); <-- unable to use due to boost interrupt logic boost::this_thread::sleep_for(boost::chrono::milliseconds(n)); } +/*** + * Convert time into a formatted string + * @param pszFormat the format + * @param nTime the time + * @returns the time in the format + */ std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime) { // std::locale takes ownership of the pointer diff --git a/src/utiltime.h b/src/utiltime.h index 900992f8717..f84ff2d111a 100644 --- a/src/utiltime.h +++ b/src/utiltime.h @@ -2,19 +2,41 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_UTILTIME_H -#define BITCOIN_UTILTIME_H +#pragma once #include #include +/*** + * Set the current time (for unit testing) + * @param nMocKtimeIn the time that will be returned by GetTime() + */ +void SetMockTime(int64_t nMockTimeIn); + +/*** + * @brief Get the current time + */ int64_t GetTime(); + +/*** + * @returns the system time in milliseconds since the epoch (1/1/1970) + */ int64_t GetTimeMillis(); + +/**** + * @returns the system time in microseconds since the epoch (1/1/1970) + */ int64_t GetTimeMicros(); -void SetMockTime(int64_t nMockTimeIn); + +/**** + * @param n the number of milliseconds to put the current thread to sleep + */ void MilliSleep(int64_t n); +/*** + * Convert time into a formatted string + * @param pszFormat the format + * @param nTime the time + * @returns the time in the format + */ std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime); - -#endif // BITCOIN_UTILTIME_H diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 6ea07be9ec4..d01e8a849b5 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -20,7 +20,6 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.RescanWallet.connect(boost::bind(&CValidationInterface::RescanWallet, pwalletIn)); g_signals.ChainTip.connect(boost::bind(&CValidationInterface::ChainTip, pwalletIn, _1, _2, _3, _4, _5)); g_signals.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); - g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1)); g_signals.BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); } @@ -28,7 +27,6 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) { void UnregisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1)); - g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); g_signals.ChainTip.disconnect(boost::bind(&CValidationInterface::ChainTip, pwalletIn, _1, _2, _3, _4, _5)); g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); g_signals.UpdatedTransaction.disconnect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1)); @@ -41,7 +39,6 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) { void UnregisterAllValidationInterfaces() { g_signals.BlockChecked.disconnect_all_slots(); g_signals.Broadcast.disconnect_all_slots(); - g_signals.Inventory.disconnect_all_slots(); g_signals.ChainTip.disconnect_all_slots(); g_signals.SetBestChain.disconnect_all_slots(); g_signals.UpdatedTransaction.disconnect_all_slots(); diff --git a/src/validationinterface.h b/src/validationinterface.h index 30b9cf0a787..fbbd3dc49ee 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -42,7 +42,6 @@ class CValidationInterface { virtual void ChainTip(const CBlockIndex *pindex, const CBlock *pblock, SproutMerkleTree sproutTree, SaplingMerkleTree saplingTree, bool added) {} virtual void SetBestChain(const CBlockLocator &locator) {} virtual void UpdatedTransaction(const uint256 &hash) {} - virtual void Inventory(const uint256 &hash) {} virtual void ResendWalletTransactions(int64_t nBestBlockTime) {} virtual void BlockChecked(const CBlock&, const CValidationState&) {} friend void ::RegisterValidationInterface(CValidationInterface*); @@ -65,8 +64,6 @@ struct CMainSignals { boost::signals2::signal ChainTip; /** Notifies listeners of a new active block chain. */ boost::signals2::signal SetBestChain; - /** Notifies listeners about an inventory item being seen on the network. */ - boost::signals2::signal Inventory; /** Tells listeners to broadcast their data. */ boost::signals2::signal Broadcast; /** Notifies listeners of a block validation result */ diff --git a/src/version.h b/src/version.h index 2f777536db5..ba4212ce0dc 100644 --- a/src/version.h +++ b/src/version.h @@ -24,7 +24,7 @@ * network protocol versioning */ -static const int PROTOCOL_VERSION = 170011; +static const int PROTOCOL_VERSION = 170012; //! initial proto version, to be increased after version/verack negotiation static const int INIT_PROTO_VERSION = 209; @@ -33,8 +33,8 @@ static const int INIT_PROTO_VERSION = 209; static const int GETHEADERS_VERSION = 31800; //! disconnect from peers older than this proto version -static const int MIN_PEER_PROTO_VERSION = 170010; -static const int STAKEDMIN_PEER_PROTO_VERSION = 170010; +static const int MIN_PEER_PROTO_VERSION = 170011; +static const int STAKEDMIN_PEER_PROTO_VERSION = 170011; //! nTime field added to CAddress, starting with this version; //! if possible, avoid requesting addresses nodes older than this diff --git a/src/wallet-utility-res.rc b/src/wallet-utility-res.rc new file mode 100644 index 00000000000..f34cd625b86 --- /dev/null +++ b/src/wallet-utility-res.rc @@ -0,0 +1,35 @@ +#include // needed for VERSIONINFO +#include "clientversion.h" // holds the needed client version information + +#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD +#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD) +#define VER_FILEVERSION VER_PRODUCTVERSION +#define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VER_FILEVERSION +PRODUCTVERSION VER_PRODUCTVERSION +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_APP +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" // U.S. English - multilingual (hex) + BEGIN + VALUE "CompanyName", "Komodo" + VALUE "FileDescription", "wallet-utility (Wallet utility)" + VALUE "FileVersion", VER_FILEVERSION_STR + VALUE "InternalName", "wallet-utility" + VALUE "LegalCopyright", COPYRIGHT_STR + VALUE "LegalTrademarks1", "Distributed under the MIT software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php." + VALUE "OriginalFilename", "wallet-utility.exe" + VALUE "ProductName", "wallet-utility" + VALUE "ProductVersion", VER_PRODUCTVERSION_STR + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1252 // language neutral - multilingual (decimal) + END +END diff --git a/src/wallet-utility.cpp b/src/wallet-utility.cpp index 4622a1059f3..7137334b782 100644 --- a/src/wallet-utility.cpp +++ b/src/wallet-utility.cpp @@ -9,7 +9,10 @@ #include #include "komodo_defs.h" -char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; + +#include "assetchain.h" +assetchain chainName; + int64_t MAX_MONEY = 200000000 * 100000000LL; uint64_t ASSETCHAINS_SUPPLY; uint16_t BITCOIND_RPCPORT = 7771; diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index afac9c6eb7f..9556723ca72 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -39,6 +39,7 @@ #include "wallet.h" #include "walletdb.h" #include "zcash/IncrementalMerkleTree.hpp" +#include "komodo_bitcoind.h" #include #include @@ -46,7 +47,6 @@ #include #include "paymentdisclosuredb.h" -int32_t komodo_blockheight(uint256 hash); using namespace libzcash; diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index dca93461be0..a1ef6860118 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -39,6 +39,10 @@ #include "zcash/IncrementalMerkleTree.hpp" #include "sodium.h" #include "miner.h" +#include "komodo_notary.h" +#include "komodo_bitcoind.h" +#include "rpc/rawtransaction.h" +#include "komodo_bitcoind.h" #include @@ -52,15 +56,6 @@ using namespace libzcash; -extern char ASSETCHAINS_SYMBOL[65]; - -int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); -int32_t komodo_blockheight(uint256 hash); -int tx_height( const uint256 &hash ); -bool komodo_hardfork_active(uint32_t time); -extern UniValue signrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue sendrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); - int find_output(UniValue obj, int n) { UniValue outputMapValue = find_value(obj, "outputmap"); if (!outputMapValue.isArray()) { @@ -374,10 +369,10 @@ bool AsyncRPCOperation_sendmany::main_impl() { } // for Komodo, set lock time to accure interest, for other chains, set // locktime to spend time locked coinbases - if (ASSETCHAINS_SYMBOL[0] == 0) + if (chainName.isKMD()) { - //if ((uint32_t)chainActive.LastTip()->nTime < ASSETCHAINS_STAKED_HF_TIMESTAMP) - if ( !komodo_hardfork_active((uint32_t)chainActive.LastTip()->nTime) ) + //if ((uint32_t)chainActive.Tip()->nTime < ASSETCHAINS_STAKED_HF_TIMESTAMP) + if ( !komodo_hardfork_active((uint32_t)chainActive.Tip()->nTime) ) builder_.SetLockTime((uint32_t)time(NULL) - 60); // set lock time for Komodo interest else builder_.SetLockTime((uint32_t)chainActive.Tip()->GetMedianTimePast()); @@ -391,10 +386,10 @@ bool AsyncRPCOperation_sendmany::main_impl() { CTxIn in(COutPoint(txid, vout)); rawTx.vin.push_back(in); } - if (ASSETCHAINS_SYMBOL[0] == 0) + if (chainName.isKMD()) { - //if ((uint32_t)chainActive.LastTip()->nTime < ASSETCHAINS_STAKED_HF_TIMESTAMP) - if ( !komodo_hardfork_active((uint32_t)chainActive.LastTip()->nTime) ) + //if ((uint32_t)chainActive.Tip()->nTime < ASSETCHAINS_STAKED_HF_TIMESTAMP) + if ( !komodo_hardfork_active((uint32_t)chainActive.Tip()->nTime) ) rawTx.nLockTime = (uint32_t)time(NULL) - 60; // jl777 else rawTx.nLockTime = (uint32_t)chainActive.Tip()->GetMedianTimePast(); @@ -599,8 +594,8 @@ bool AsyncRPCOperation_sendmany::main_impl() { CMutableTransaction mtx(tx_); crypto_sign_keypair(joinSplitPubKey_.begin(), joinSplitPrivKey_); mtx.joinSplitPubKey = joinSplitPubKey_; - //if ((uint32_t)chainActive.LastTip()->nTime < ASSETCHAINS_STAKED_HF_TIMESTAMP) - if ( !komodo_hardfork_active((uint32_t)chainActive.LastTip()->nTime) ) + //if ((uint32_t)chainActive.Tip()->nTime < ASSETCHAINS_STAKED_HF_TIMESTAMP) + if ( !komodo_hardfork_active((uint32_t)chainActive.Tip()->nTime) ) mtx.nLockTime = (uint32_t)time(NULL) - 60; // jl777 else mtx.nLockTime = (uint32_t)chainActive.Tip()->GetMedianTimePast(); @@ -1375,8 +1370,8 @@ void AsyncRPCOperation_sendmany::add_taddr_outputs_to_tx() { CTxOut out(nAmount, scriptPubKey); rawTx.vout.push_back(out); } - //if ((uint32_t)chainActive.LastTip()->nTime < ASSETCHAINS_STAKED_HF_TIMESTAMP) - if ( !komodo_hardfork_active((uint32_t)chainActive.LastTip()->nTime) ) + //if ((uint32_t)chainActive.Tip()->nTime < ASSETCHAINS_STAKED_HF_TIMESTAMP) + if ( !komodo_hardfork_active((uint32_t)chainActive.Tip()->nTime) ) rawTx.nLockTime = (uint32_t)time(NULL) - 60; // jl777 else rawTx.nLockTime = (uint32_t)chainActive.Tip()->GetMedianTimePast(); @@ -1406,8 +1401,8 @@ void AsyncRPCOperation_sendmany::add_taddr_change_output_to_tx(CBitcoinAddress * CMutableTransaction rawTx(tx_); rawTx.vout.push_back(out); - //if ((uint32_t)chainActive.LastTip()->nTime < ASSETCHAINS_STAKED_HF_TIMESTAMP) - if ( !komodo_hardfork_active((uint32_t)chainActive.LastTip()->nTime) ) + //if ((uint32_t)chainActive.Tip()->nTime < ASSETCHAINS_STAKED_HF_TIMESTAMP) + if ( !komodo_hardfork_active((uint32_t)chainActive.Tip()->nTime) ) rawTx.nLockTime = (uint32_t)time(NULL) - 60; // jl777 else rawTx.nLockTime = (uint32_t)chainActive.Tip()->GetMedianTimePast(); diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp index 6db4eb6c0e1..9cedc43159a 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp @@ -38,6 +38,7 @@ #include "zcash/IncrementalMerkleTree.hpp" #include "sodium.h" #include "miner.h" +#include "komodo_globals.h" #include #include @@ -51,7 +52,6 @@ #include "paymentdisclosuredb.h" using namespace libzcash; -extern uint64_t ASSETCHAINS_TIMELOCKGTE; static int find_output(UniValue obj, int n) { UniValue outputMapValue = find_value(obj, "outputmap"); diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index dd0880b756a..f1ca0f51197 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -46,7 +46,10 @@ unsigned int nWalletDBUpdated; // CDB // -CDBEnv bitdb; +// A singleton for all wallets in this process +// Making this a static variable causes problems with testing, so +// switching to a shared_ptr +std::shared_ptr bitdb(new CDBEnv()); void CDBEnv::EnvShutdown() { @@ -254,17 +257,17 @@ CDB::CDB(const std::string& strFilename, const char* pszMode, bool fFlushOnClose nFlags |= DB_CREATE; { - LOCK(bitdb.cs_db); - if (!bitdb.Open(GetDataDir())) + LOCK(bitdb->cs_db); + if (!bitdb->Open(GetDataDir())) throw runtime_error("CDB: Failed to open database environment."); strFile = strFilename; - ++bitdb.mapFileUseCount[strFile]; - pdb = bitdb.mapDb[strFile]; + ++bitdb->mapFileUseCount[strFile]; + pdb = bitdb->mapDb[strFile]; if (pdb == NULL) { - pdb = new Db(bitdb.dbenv, 0); + pdb = new Db(bitdb->dbenv, 0); - bool fMockDb = bitdb.IsMock(); + bool fMockDb = bitdb->IsMock(); if (fMockDb) { DbMpoolFile* mpf = pdb->get_mpf(); ret = mpf->set_flags(DB_MPOOL_NOFILE, 1); @@ -282,7 +285,7 @@ CDB::CDB(const std::string& strFilename, const char* pszMode, bool fFlushOnClose if (ret != 0) { delete pdb; pdb = NULL; - --bitdb.mapFileUseCount[strFile]; + --bitdb->mapFileUseCount[strFile]; strFile = ""; throw runtime_error(strprintf("CDB: Error %d, can't open database %s", ret, strFile)); } @@ -294,7 +297,7 @@ CDB::CDB(const std::string& strFilename, const char* pszMode, bool fFlushOnClose fReadOnly = fTmp; } - bitdb.mapDb[strFile] = pdb; + bitdb->mapDb[strFile] = pdb; } } } @@ -309,7 +312,7 @@ void CDB::Flush() if (fReadOnly) nMinutes = 1; - bitdb.dbenv->txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100) * 1024 : 0, nMinutes, 0); + bitdb->dbenv->txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100) * 1024 : 0, nMinutes, 0); } void CDB::Close() @@ -325,8 +328,8 @@ void CDB::Close() Flush(); { - LOCK(bitdb.cs_db); - --bitdb.mapFileUseCount[strFile]; + LOCK(bitdb->cs_db); + --bitdb->mapFileUseCount[strFile]; } } @@ -357,19 +360,19 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) { while (true) { { - LOCK(bitdb.cs_db); - if (!bitdb.mapFileUseCount.count(strFile) || bitdb.mapFileUseCount[strFile] == 0) { + LOCK(bitdb->cs_db); + if (!bitdb->mapFileUseCount.count(strFile) || bitdb->mapFileUseCount[strFile] == 0) { // Flush log data to the dat file - bitdb.CloseDb(strFile); - bitdb.CheckpointLSN(strFile); - bitdb.mapFileUseCount.erase(strFile); + bitdb->CloseDb(strFile); + bitdb->CheckpointLSN(strFile); + bitdb->mapFileUseCount.erase(strFile); bool fSuccess = true; LogPrintf("CDB::Rewrite: Rewriting %s...\n", strFile); string strFileRes = strFile + ".rewrite"; { // surround usage of db with extra {} CDB db(strFile.c_str(), "r"); - Db* pdbCopy = new Db(bitdb.dbenv, 0); + Db* pdbCopy = new Db(bitdb->dbenv, 0); int ret = pdbCopy->open(NULL, // Txn pointer strFileRes.c_str(), // Filename @@ -412,17 +415,17 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) } if (fSuccess) { db.Close(); - bitdb.CloseDb(strFile); + bitdb->CloseDb(strFile); if (pdbCopy->close(0)) fSuccess = false; delete pdbCopy; } } if (fSuccess) { - Db dbA(bitdb.dbenv, 0); + Db dbA(bitdb->dbenv, 0); if (dbA.remove(strFile.c_str(), NULL, 0)) fSuccess = false; - Db dbB(bitdb.dbenv, 0); + Db dbB(bitdb->dbenv, 0); if (dbB.rename(strFileRes.c_str(), NULL, strFile.c_str(), 0)) fSuccess = false; } diff --git a/src/wallet/db.h b/src/wallet/db.h index 8ad246de434..dd9d50a56f5 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -60,7 +60,7 @@ class CDBEnv public: mutable CCriticalSection cs_db; - DbEnv *dbenv; + DbEnv *dbenv = nullptr; std::map mapFileUseCount; std::map mapDb; @@ -109,7 +109,7 @@ class CDBEnv } }; -extern CDBEnv bitdb; +extern std::shared_ptr bitdb; /** RAII class that provides access to a Berkeley database */ @@ -292,7 +292,7 @@ class CDB { if (!pdb || activeTxn) return false; - DbTxn* ptxn = bitdb.TxnBegin(); + DbTxn* ptxn = bitdb->TxnBegin(); if (!ptxn) return false; activeTxn = ptxn; diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index f4ed27e9633..2e97752b5ea 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -28,7 +28,7 @@ #include "util.h" #include "utiltime.h" #include "wallet.h" - +#include "komodo_nSPV_defs.h" #include #include @@ -409,7 +409,7 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys if (!file.is_open()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file"); - int64_t nTimeBegin = chainActive.LastTip()->GetBlockTime(); + int64_t nTimeBegin = chainActive.Tip()->GetBlockTime(); bool fGood = true; @@ -490,7 +490,7 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys file.close(); pwalletMain->ShowProgress("", 100); // hide progress dialog in GUI - CBlockIndex *pindex = chainActive.LastTip(); + CBlockIndex *pindex = chainActive.Tip(); while (pindex && pindex->pprev && pindex->GetBlockTime() > nTimeBegin - 7200) pindex = pindex->pprev; @@ -1007,13 +1007,6 @@ UniValue z_exportviewingkey(const UniValue& params, bool fHelp, const CPubKey& m return EncodeViewingKey(vk); } -extern int32_t KOMODO_NSPV; -#ifndef KOMODO_NSPV_FULLNODE -#define KOMODO_NSPV_FULLNODE (KOMODO_NSPV <= 0) -#endif // !KOMODO_NSPV_FULLNODE -#ifndef KOMODO_NSPV_SUPERLITE -#define KOMODO_NSPV_SUPERLITE (KOMODO_NSPV > 0) -#endif // !KOMODO_NSPV_SUPERLITE uint256 zeroid; UniValue NSPV_getinfo_req(int32_t reqht); UniValue NSPV_login(char *wifstr); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index e4175196917..9e17a27a35c 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -38,6 +38,12 @@ #include "script/interpreter.h" #include "zcash/zip32.h" #include "notaries_staked.h" +#include "komodo.h" +#include "komodo_bitcoind.h" +#include "komodo_notary.h" +#include "komodo_kv.h" +#include "komodo_gateway.h" +#include "komodo_globals.h" #include "utiltime.h" #include "asyncrpcoperation.h" @@ -53,13 +59,15 @@ #include #include -//#include #include #include +#include "main.h" +#include "rpc/rawtransaction.h" #include "komodo_defs.h" +#include "komodo_interest.h" #include "hex.h" #include @@ -67,16 +75,8 @@ using namespace std; using namespace libzcash; -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -extern std::string ASSETCHAINS_OVERRIDE_PUBKEY; const std::string ADDR_TYPE_SPROUT = "sprout"; const std::string ADDR_TYPE_SAPLING = "sapling"; -extern UniValue TxJoinSplitToJSON(const CTransaction& tx); -extern int32_t KOMODO_INSYNC; -uint32_t komodo_segid32(char *coinaddr); -int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); -int32_t komodo_isnotaryvout(char *coinaddr,uint32_t tiptime); // from ac_private chains only -CBlockIndex *komodo_getblockindex(uint256 hash); int64_t nWalletUnlockTime; static CCriticalSection cs_nWalletUnlockTime; @@ -89,8 +89,6 @@ UniValue z_getoperationstatus_IMPL(const UniValue&, bool); #define VALID_PLAN_NAME(x) (strlen(x) <= PLAN_NAME_MAX) #define THROW_IF_SYNCING(INSYNC) if (INSYNC == 0) { throw runtime_error(strprintf("%s: Chain still syncing at height %d, aborting to prevent linkability analysis!",__FUNCTION__,chainActive.Tip()->nHeight)); } -int tx_height( const uint256 &hash ); - std::string HelpRequiringPassphrase() { return pwalletMain && pwalletMain->IsCrypted() @@ -134,8 +132,6 @@ void Unlock2NSPV(const CPubKey &pk) } } -uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); - void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry) { //int32_t i,n,txheight; uint32_t locktime; uint64_t interest = 0; @@ -165,17 +161,9 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry) entry.push_back(Pair("vjoinsplit", TxJoinSplitToJSON(wtx))); } -string AccountFromValue(const UniValue& value) -{ - string strAccount = value.get_str(); - //if (strAccount != "") - // throw JSONRPCError(RPC_WALLET_ACCOUNTS_UNSUPPORTED, "Accounts are unsupported"); - return strAccount; -} - -char *komodo_chainname() +const std::string AccountFromValue(const UniValue& value) { - return(ASSETCHAINS_SYMBOL[0] == 0 ? (char *)"KMD" : ASSETCHAINS_SYMBOL); + return value.get_str(); } void OS_randombytes(unsigned char *x,long xlen); @@ -188,11 +176,11 @@ UniValue getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) if (fHelp || params.size() > 1) throw runtime_error( "getnewaddress ( \"account\" )\n" - "\nReturns a new " + strprintf("%s",komodo_chainname()) + " address for receiving payments.\n" + "\nReturns a new " + chainName.ToString() + " address for receiving payments.\n" "\nArguments:\n" "1. \"account\" (string, optional) DEPRECATED. If provided, it MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n" "\nResult:\n" - "\"" + strprintf("%s",komodo_chainname()) + "_address\" (string) The new " + strprintf("%s",komodo_chainname()) + " address\n" + "\"" + chainName.ToString() + "_address\" (string) The new " + chainName.ToString() + " address\n" "\nExamples:\n" + HelpExampleCli("getnewaddress", "") + HelpExampleRpc("getnewaddress", "") @@ -282,11 +270,11 @@ UniValue getaccountaddress(const UniValue& params, bool fHelp, const CPubKey& my if (fHelp || params.size() != 1) throw runtime_error( "getaccountaddress \"account\"\n" - "\nDEPRECATED. Returns the current " + strprintf("%s",komodo_chainname()) + " address for receiving payments to this account.\n" + "\nDEPRECATED. Returns the current " + chainName.ToString() + " address for receiving payments to this account.\n" "\nArguments:\n" "1. \"account\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n" "\nResult:\n" - "\"" + strprintf("%s",komodo_chainname()) + "_address\" (string) The account " + strprintf("%s",komodo_chainname()) + " address\n" + "\"" + chainName.ToString() + "_address\" (string) The account " + chainName.ToString() + " address\n" "\nExamples:\n" + HelpExampleCli("getaccountaddress", "") + HelpExampleCli("getaccountaddress", "\"\"") @@ -314,7 +302,7 @@ UniValue getrawchangeaddress(const UniValue& params, bool fHelp, const CPubKey& if (fHelp || params.size() > 1) throw runtime_error( "getrawchangeaddress\n" - "\nReturns a new " + strprintf("%s",komodo_chainname()) + " address, for receiving change.\n" + "\nReturns a new " + chainName.ToString() + " address, for receiving change.\n" "This is for use with raw transactions, NOT normal use.\n" "\nResult:\n" "\"address\" (string) The address\n" @@ -348,10 +336,10 @@ UniValue setaccount(const UniValue& params, bool fHelp, const CPubKey& mypk) if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( - "setaccount \"" + strprintf("%s",komodo_chainname()) + "_address\" \"account\"\n" + "setaccount \"" + chainName.ToString() + "_address\" \"account\"\n" "\nDEPRECATED. Sets the account associated with the given address.\n" "\nArguments:\n" - "1. \"" + strprintf("%s",komodo_chainname()) + "_address\" (string, required) The " + strprintf("%s",komodo_chainname()) + " address to be associated with an account.\n" + "1. \"" + chainName.ToString() + "_address\" (string, required) The " + chainName.ToString() + " address to be associated with an account.\n" "2. \"account\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n" "\nExamples:\n" + HelpExampleCli("setaccount", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" \"tabby\"") @@ -394,10 +382,10 @@ UniValue getaccount(const UniValue& params, bool fHelp, const CPubKey& mypk) if (fHelp || params.size() != 1) throw runtime_error( - "getaccount \"" + strprintf("%s",komodo_chainname()) + "_address\"\n" + "getaccount \"" + chainName.ToString() + "_address\"\n" "\nDEPRECATED. Returns the account associated with the given address.\n" "\nArguments:\n" - "1. \"" + strprintf("%s",komodo_chainname()) + "_address\" (string, required) The " + strprintf("%s",komodo_chainname()) + " address for account lookup.\n" + "1. \"" + chainName.ToString() + "_address\" (string, required) The " + chainName.ToString() + " address for account lookup.\n" "\nResult:\n" "\"accountname\" (string) the account address\n" "\nExamples:\n" @@ -434,7 +422,7 @@ UniValue getaddressesbyaccount(const UniValue& params, bool fHelp, const CPubKey "1. \"account\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n" "\nResult:\n" "[ (json array of string)\n" - " \"" + strprintf("%s",komodo_chainname()) + "_address\" (string) a " + strprintf("%s",komodo_chainname()) + " address associated with the given account\n" + " \"" + chainName.ToString() + "_address\" (string) a " + chainName.ToString() + " address associated with the given account\n" " ,...\n" "]\n" "\nExamples:\n" @@ -510,19 +498,19 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) if (fHelp || params.size() < 2 || params.size() > 5) throw runtime_error( - "sendtoaddress \"" + strprintf("%s",komodo_chainname()) + "_address\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n" + "sendtoaddress \"" + chainName.ToString() + "_address\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n" "\nSend an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n" + HelpRequiringPassphrase() + "\nArguments:\n" - "1. \"" + strprintf("%s",komodo_chainname()) + "_address\" (string, required) The " + strprintf("%s",komodo_chainname()) + " address to send to.\n" - "2. \"amount\" (numeric, required) The amount in " + strprintf("%s",komodo_chainname()) + " to send. eg 0.1\n" + "1. \"" + chainName.ToString() + "_address\" (string, required) The " + chainName.ToString() + " address to send to.\n" + "2. \"amount\" (numeric, required) The amount in " + chainName.ToString() + " to send. eg 0.1\n" "3. \"comment\" (string, optional) A comment used to store what the transaction is for. \n" " This is not part of the transaction, just kept in your wallet.\n" "4. \"comment-to\" (string, optional) A comment to store the name of the person or organization \n" " to which you're sending the transaction. This is not part of the \n" " transaction, just kept in your wallet.\n" "5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n" - " The recipient will receive less " + strprintf("%s",komodo_chainname()) + " than you enter in the amount field.\n" + " The recipient will receive less " + chainName.ToString() + " than you enter in the amount field.\n" "\nResult:\n" "\"transactionid\" (string) The transaction id.\n" "\nExamples:\n" @@ -534,9 +522,9 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) if ( ASSETCHAINS_PRIVATE != 0 && AmountFromValue(params[1]) > 0 ) { - if ( komodo_isnotaryvout((char *)params[0].get_str().c_str(),chainActive.LastTip()->nTime) == 0 ) + if ( komodo_isnotaryvout((char *)params[0].get_str().c_str(),chainActive.Tip()->nTime) == 0 ) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid " + strprintf("%s",komodo_chainname()) + " address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid " + chainName.ToString() + " address"); } } LOCK2(cs_main, pwalletMain->cs_wallet); @@ -569,34 +557,39 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) return wtx.GetHash().GetHex(); } -#include "komodo_defs.h" - +/* TODO: remove #define KOMODO_KVPROTECTED 1 #define KOMODO_KVBINARY 2 #define KOMODO_KVDURATION 1440 #define IGUANA_MAXSCRIPTSIZE 10001 -uint64_t PAX_fiatdest(uint64_t *seedp,int32_t tokomodo,char *destaddr,uint8_t pubkey37[37],char *coinaddr,int32_t height,char *base,int64_t fiatoshis); +#define CRYPTO777_KMDADDR "RXL3YXG2ceaB6C5hfJcN4fvmLH2C34knhA" +#include "komodo_defs.h"*/ + +/* +#define IGUANA_MAXSCRIPTSIZE 10001 int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen); #define CRYPTO777_KMDADDR "RXL3YXG2ceaB6C5hfJcN4fvmLH2C34knhA" -extern int32_t KOMODO_PAX; extern uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; -int32_t komodo_is_issuer(); int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); -int32_t komodo_isrealtime(int32_t *kmdheightp); -int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base); int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); -int32_t komodo_kvcmp(uint8_t *refvalue,uint16_t refvaluesize,uint8_t *value,uint16_t valuesize); uint64_t komodo_kvfee(uint32_t flags,int32_t opretlen,int32_t keylen); uint256 komodo_kvsig(uint8_t *buf,int32_t len,uint256 privkey); int32_t komodo_kvduration(uint32_t flags); uint256 komodo_kvprivkey(uint256 *pubkeyp,char *passphrase); int32_t komodo_kvsigverify(uint8_t *buf,int32_t len,uint256 _pubkey,uint256 sig); +*/ UniValue kvupdate(const UniValue& params, bool fHelp, const CPubKey& mypk) { static uint256 zeroes; CWalletTx wtx; UniValue ret(UniValue::VOBJ); - uint8_t keyvalue[IGUANA_MAXSCRIPTSIZE*8],opretbuf[IGUANA_MAXSCRIPTSIZE*8]; int32_t i,coresize,haveprivkey,duration,opretlen,height; uint16_t keylen=0,valuesize=0,refvaluesize=0; uint8_t *key,*value=0; uint32_t flags,tmpflags,n; struct komodo_kv *ptr; uint64_t fee; uint256 privkey,pubkey,refpubkey,sig; + uint8_t keyvalue[IGUANA_MAXSCRIPTSIZE*8],opretbuf[IGUANA_MAXSCRIPTSIZE*8]; + int32_t i,coresize,haveprivkey,duration,opretlen,height; + uint16_t keylen=0,valuesize=0,refvaluesize=0; + uint8_t *key,*value=0; + uint32_t flags,tmpflags,n; + uint64_t fee; + uint256 privkey,pubkey,refpubkey,sig; if (fHelp || params.size() < 3 ) throw runtime_error( "kvupdate key \"value\" days passphrase\n" @@ -625,7 +618,7 @@ UniValue kvupdate(const UniValue& params, bool fHelp, const CPubKey& mypk) ); if (!EnsureWalletIsAvailable(fHelp)) return 0; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) + if ( chainName.isKMD() ) return(0); haveprivkey = 0; memset(&sig,0,sizeof(sig)); @@ -658,7 +651,7 @@ UniValue kvupdate(const UniValue& params, bool fHelp, const CPubKey& mypk) valuesize = (int32_t)strlen(params[1].get_str().c_str()); } memcpy(keyvalue,key,keylen); - if ( (refvaluesize= komodo_kvsearch(&refpubkey,chainActive.LastTip()->nHeight,&tmpflags,&height,&keyvalue[keylen],key,keylen)) >= 0 ) + if ( (refvaluesize= komodo_kvsearch(&refpubkey,chainActive.Tip()->nHeight,&tmpflags,&height,&keyvalue[keylen],key,keylen)) >= 0 ) { if ( (tmpflags & KOMODO_KVPROTECTED) != 0 ) { @@ -676,14 +669,11 @@ UniValue kvupdate(const UniValue& params, bool fHelp, const CPubKey& mypk) ret.push_back(Pair("error",(char *)"error verifying sig, passphrase is probably wrong")); printf("VERIFY ERROR\n"); return ret; - } // else printf("verified immediately\n"); + } } } - //for (i=0; i<32; i++) - // printf("%02x",((uint8_t *)&sig)[i]); - //printf(" sig for keylen.%d + valuesize.%d\n",keylen,refvaluesize); - ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL))); - height = chainActive.LastTip()->nHeight; + ret.push_back(Pair("coin", chainName.ToString())); + height = chainActive.Tip()->nHeight; if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 ) ret.push_back(Pair("owner",refpubkey.GetHex())); ret.push_back(Pair("height", (int64_t)height)); @@ -734,87 +724,6 @@ UniValue kvupdate(const UniValue& params, bool fHelp, const CPubKey& mypk) return ret; } -UniValue paxdeposit(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - uint64_t available,deposited,issued,withdrawn,approved,redeemed,seed,komodoshis = 0; int32_t height; char destaddr[64]; uint8_t i,pubkey37[33]; - bool fSubtractFeeFromAmount = false; - if ( KOMODO_PAX == 0 ) - { - throw runtime_error("paxdeposit disabled without -pax"); - } - if ( komodo_is_issuer() != 0 ) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "paxdeposit only from KMD"); - if (!EnsureWalletIsAvailable(fHelp)) - throw runtime_error("paxdeposit needs wallet"); //return Value::null; - if (fHelp || params.size() != 3) - throw runtime_error("paxdeposit address fiatoshis base"); - LOCK2(cs_main, pwalletMain->cs_wallet); - CBitcoinAddress address(params[0].get_str()); - if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); - int64_t fiatoshis = atof(params[1].get_str().c_str()) * COIN; - std::string base = params[2].get_str(); - std::string dest; - height = chainActive.LastTip()->nHeight; - if ( pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,(char *)base.c_str()) != 0 || available < fiatoshis ) - { - fprintf(stderr,"available %llu vs fiatoshis %llu\n",(long long)available,(long long)fiatoshis); - throw runtime_error("paxdeposit not enough available inventory"); - } - komodoshis = PAX_fiatdest(&seed,0,destaddr,pubkey37,(char *)params[0].get_str().c_str(),height,(char *)base.c_str(),fiatoshis); - dest.append(destaddr); - CBitcoinAddress destaddress(CRYPTO777_KMDADDR); - if (!destaddress.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid dest Bitcoin address"); - for (i=0; i<33; i++) - fprintf(stderr,"%02x",pubkey37[i]); - fprintf(stderr," ht.%d srcaddr.(%s) %s fiatoshis.%lld -> dest.(%s) komodoshis.%llu seed.%llx\n",height,(char *)params[0].get_str().c_str(),(char *)base.c_str(),(long long)fiatoshis,destaddr,(long long)komodoshis,(long long)seed); - EnsureWalletIsUnlocked(); - CWalletTx wtx; - uint8_t opretbuf[64]; int32_t opretlen; uint64_t fee = komodoshis / 1000; - if ( fee < 10000 ) - fee = 10000; - iguana_rwnum(1,&pubkey37[33],sizeof(height),&height); - opretlen = komodo_opreturnscript(opretbuf,'D',pubkey37,37); - SendMoney(address.Get(),fee,fSubtractFeeFromAmount,wtx,opretbuf,opretlen,komodoshis); - return wtx.GetHash().GetHex(); -} - -UniValue paxwithdraw(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - CWalletTx wtx; std::string dest; int32_t kmdheight; uint64_t seed,komodoshis = 0; char destaddr[64]; uint8_t i,pubkey37[37]; bool fSubtractFeeFromAmount = false; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - return(0); - if (!EnsureWalletIsAvailable(fHelp)) - return 0; - throw runtime_error("paxwithdraw deprecated"); - if (fHelp || params.size() != 2) - throw runtime_error("paxwithdraw address fiatamount"); - if ( komodo_isrealtime(&kmdheight) == 0 ) - return(0); - LOCK2(cs_main, pwalletMain->cs_wallet); - CBitcoinAddress address(params[0].get_str()); - if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); - int64_t fiatoshis = atof(params[1].get_str().c_str()) * COIN; - komodoshis = PAX_fiatdest(&seed,1,destaddr,pubkey37,(char *)params[0].get_str().c_str(),kmdheight,ASSETCHAINS_SYMBOL,fiatoshis); - dest.append(destaddr); - CBitcoinAddress destaddress(CRYPTO777_KMDADDR); - if (!destaddress.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid dest Bitcoin address"); - for (i=0; i<33; i++) - printf("%02x",pubkey37[i]); - printf(" kmdheight.%d srcaddr.(%s) %s fiatoshis.%lld -> dest.(%s) komodoshis.%llu seed.%llx\n",kmdheight,(char *)params[0].get_str().c_str(),ASSETCHAINS_SYMBOL,(long long)fiatoshis,destaddr,(long long)komodoshis,(long long)seed); - EnsureWalletIsUnlocked(); - uint8_t opretbuf[64]; int32_t opretlen; uint64_t fee = fiatoshis / 1000; - if ( fee < 10000 ) - fee = 10000; - iguana_rwnum(1,&pubkey37[33],sizeof(kmdheight),&kmdheight); - opretlen = komodo_opreturnscript(opretbuf,'W',pubkey37,37); - SendMoney(destaddress.Get(),fee,fSubtractFeeFromAmount,wtx,opretbuf,opretlen,fiatoshis); - return wtx.GetHash().GetHex(); -} - UniValue listaddressgroupings(const UniValue& params, bool fHelp, const CPubKey& mypk) { if (!EnsureWalletIsAvailable(fHelp)) @@ -830,8 +739,8 @@ UniValue listaddressgroupings(const UniValue& params, bool fHelp, const CPubKey& "[\n" " [\n" " [\n" - " \"" + strprintf("%s",komodo_chainname()) + " address\", (string) The " + strprintf("%s",komodo_chainname()) + " address\n" - " amount, (numeric) The amount in " + strprintf("%s",komodo_chainname()) + "\n" + " \"" + chainName.ToString() + " address\", (string) The " + chainName.ToString() + " address\n" + " amount, (numeric) The amount in " + chainName.ToString() + "\n" " \"account\" (string, optional) The account (DEPRECATED)\n" " ]\n" " ,...\n" @@ -932,13 +841,13 @@ UniValue getreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( - "getreceivedbyaddress \"" + strprintf("%s",komodo_chainname()) + "_address\" ( minconf )\n" - "\nReturns the total amount received by the given " + strprintf("%s",komodo_chainname()) + " address in transactions with at least minconf confirmations.\n" + "getreceivedbyaddress \"" + chainName.ToString() + "_address\" ( minconf )\n" + "\nReturns the total amount received by the given " + chainName.ToString() + " address in transactions with at least minconf confirmations.\n" "\nArguments:\n" - "1. \"" + strprintf("%s",komodo_chainname()) + "_address\" (string, required) The " + strprintf("%s",komodo_chainname()) + " address for transactions.\n" + "1. \"" + chainName.ToString() + "_address\" (string, required) The " + chainName.ToString() + " address for transactions.\n" "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n" "\nResult:\n" - "amount (numeric) The total amount in " + strprintf("%s",komodo_chainname()) + " received at this address.\n" + "amount (numeric) The total amount in " + chainName.ToString() + " received at this address.\n" "\nExamples:\n" "\nThe amount from transactions with at least 1 confirmation\n" + HelpExampleCli("getreceivedbyaddress", "\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"") + @@ -1009,7 +918,7 @@ UniValue getreceivedbyaccount(const UniValue& params, bool fHelp, const CPubKey& "1. \"account\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n" "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n" "\nResult:\n" - "amount (numeric) The total amount in " + strprintf("%s",komodo_chainname()) + " received for this account.\n" + "amount (numeric) The total amount in " + chainName.ToString() + " received for this account.\n" "\nExamples:\n" "\nAmount received by the default account with at least 1 confirmation\n" + HelpExampleCli("getreceivedbyaccount", "\"\"") + @@ -1108,7 +1017,7 @@ UniValue cleanwallettransactions(const UniValue& params, bool fHelp, const CPubK "1. \"txid\" (string, optional) The transaction id to keep.\n" "\nResult:\n" "{\n" - " \"total_transactions\" : n, (numeric) Transactions in wallet of " + strprintf("%s",komodo_chainname()) + "\n" + " \"total_transactions\" : n, (numeric) Transactions in wallet of " + chainName.ToString() + "\n" " \"remaining_transactions\" : n, (numeric) Transactions in wallet after clean.\n" " \"removed_transactions\" : n, (numeric) The number of transactions removed.\n" "}\n" @@ -1211,7 +1120,7 @@ UniValue getbalance(const UniValue& params, bool fHelp, const CPubKey& mypk) "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n" "3. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress')\n" "\nResult:\n" - "amount (numeric) The total amount in " + strprintf("%s",komodo_chainname()) + " received for this account.\n" + "amount (numeric) The total amount in " + chainName.ToString() + " received for this account.\n" "\nExamples:\n" "\nThe total amount in the wallet\n" + HelpExampleCli("getbalance", "") + @@ -1307,15 +1216,15 @@ UniValue movecmd(const UniValue& params, bool fHelp, const CPubKey& mypk) "\nArguments:\n" "1. \"fromaccount\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n" "2. \"toaccount\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n" - "3. amount (numeric) Quantity of " + strprintf("%s",komodo_chainname()) + " to move between accounts.\n" + "3. amount (numeric) Quantity of " + chainName.ToString() + " to move between accounts.\n" "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n" "5. \"comment\" (string, optional) An optional comment, stored in the wallet only.\n" "\nResult:\n" "true|false (boolean) true if successful.\n" "\nExamples:\n" - "\nMove 0.01 " + strprintf("%s",komodo_chainname()) + " from the default account to the account named tabby\n" + "\nMove 0.01 " + chainName.ToString() + " from the default account to the account named tabby\n" + HelpExampleCli("move", "\"\" \"tabby\" 0.01") + - "\nMove 0.01 " + strprintf("%s",komodo_chainname()) + " timotei to akiko with a comment and funds have 6 confirmations\n" + "\nMove 0.01 " + chainName.ToString() + " timotei to akiko with a comment and funds have 6 confirmations\n" + HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") + "\nAs a json rpc call\n" + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"") @@ -1377,14 +1286,14 @@ UniValue sendfrom(const UniValue& params, bool fHelp, const CPubKey& mypk) if (fHelp || params.size() < 3 || params.size() > 6) throw runtime_error( - "sendfrom \"fromaccount\" \"to" + strprintf("%s",komodo_chainname()) + "address\" amount ( minconf \"comment\" \"comment-to\" )\n" - "\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a " + strprintf("%s",komodo_chainname()) + " address.\n" + "sendfrom \"fromaccount\" \"to" + chainName.ToString() + "address\" amount ( minconf \"comment\" \"comment-to\" )\n" + "\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a " + chainName.ToString() + " address.\n" "The amount is a real and is rounded to the nearest 0.00000001." + HelpRequiringPassphrase() + "\n" "\nArguments:\n" "1. \"fromaccount\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n" - "2. \"to" + strprintf("%s",komodo_chainname()) + "address\" (string, required) The " + strprintf("%s",komodo_chainname()) + " address to send funds to.\n" - "3. amount (numeric, required) The amount in " + strprintf("%s",komodo_chainname()) + " (transaction fee is added on top).\n" + "2. \"to" + chainName.ToString() + "address\" (string, required) The " + chainName.ToString() + " address to send funds to.\n" + "3. amount (numeric, required) The amount in " + chainName.ToString() + " (transaction fee is added on top).\n" "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n" "5. \"comment\" (string, optional) A comment used to store what the transaction is for. \n" " This is not part of the transaction, just kept in your wallet.\n" @@ -1394,7 +1303,7 @@ UniValue sendfrom(const UniValue& params, bool fHelp, const CPubKey& mypk) "\nResult:\n" "\"transactionid\" (string) The transaction id.\n" "\nExamples:\n" - "\nSend 0.01 " + strprintf("%s",komodo_chainname()) + " from the default account to the address, must have at least 1 confirmation\n" + "\nSend 0.01 " + chainName.ToString() + " from the default account to the address, must have at least 1 confirmation\n" + HelpExampleCli("sendfrom", "\"\" \"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.01") + "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n" + HelpExampleCli("sendfrom", "\"tabby\" \"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\" 0.01 6 \"donation\" \"seans outpost\"") + @@ -1452,14 +1361,14 @@ UniValue sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk) "1. \"fromaccount\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n" "2. \"amounts\" (string, required) A json object with addresses and amounts\n" " {\n" - " \"address\":amount (numeric) The " + strprintf("%s",komodo_chainname()) + " address is the key, the numeric amount in " + strprintf("%s",komodo_chainname()) + " is the value\n" + " \"address\":amount (numeric) The " + chainName.ToString() + " address is the key, the numeric amount in " + chainName.ToString() + " is the value\n" " ,...\n" " }\n" "3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n" "4. \"comment\" (string, optional) A comment\n" "5. subtractfeefromamount (string, optional) A json array with addresses.\n" " The fee will be equally deducted from the amount of each selected address.\n" - " Those recipients will receive less " + strprintf("%s",komodo_chainname()) + " than you enter in their corresponding amount field.\n" + " Those recipients will receive less " + chainName.ToString() + " than you enter in their corresponding amount field.\n" " If no addresses are specified here, the sender pays the fee.\n" " [\n" " \"address\" (string) Subtract fee from this address\n" @@ -1563,20 +1472,20 @@ UniValue addmultisigaddress(const UniValue& params, bool fHelp, const CPubKey& m { string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n" "\nAdd a nrequired-to-sign multisignature address to the wallet.\n" - "Each key is a " + strprintf("%s",komodo_chainname()) + " address or hex-encoded public key.\n" + "Each key is a " + chainName.ToString() + " address or hex-encoded public key.\n" "If 'account' is specified (DEPRECATED), assign address to that account.\n" "\nArguments:\n" "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n" - "2. \"keysobject\" (string, required) A json array of " + strprintf("%s",komodo_chainname()) + " addresses or hex-encoded public keys\n" + "2. \"keysobject\" (string, required) A json array of " + chainName.ToString() + " addresses or hex-encoded public keys\n" " [\n" - " \"address\" (string) " + strprintf("%s",komodo_chainname()) + " address or hex-encoded public key\n" + " \"address\" (string) " + chainName.ToString() + " address or hex-encoded public key\n" " ...,\n" " ]\n" "3. \"account\" (string, optional) DEPRECATED. If provided, MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n" "\nResult:\n" - "\"" + strprintf("%s",komodo_chainname()) + "_address\" (string) A " + strprintf("%s",komodo_chainname()) + " address associated with the keys.\n" + "\"" + chainName.ToString() + "_address\" (string) A " + chainName.ToString() + " address associated with the keys.\n" "\nExamples:\n" "\nAdd a multisig address from 2 addresses\n" @@ -1769,7 +1678,7 @@ UniValue listreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n" " \"address\" : \"receivingaddress\", (string) The receiving address\n" " \"account\" : \"accountname\", (string) DEPRECATED. The account of the receiving address. The default account is \"\".\n" - " \"amount\" : x.xxx, (numeric) The total amount in " + strprintf("%s",komodo_chainname()) + " received by the address\n" + " \"amount\" : x.xxx, (numeric) The total amount in " + chainName.ToString() + " received by the address\n" " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n" " }\n" " ,...\n" @@ -1951,17 +1860,17 @@ UniValue listtransactions(const UniValue& params, bool fHelp, const CPubKey& myp " {\n" " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. \n" " It will be \"\" for the default account.\n" - " \"address\":\"" + strprintf("%s",komodo_chainname()) + "_address\", (string) The " + strprintf("%s",komodo_chainname()) + " address of the transaction. Not present for \n" + " \"address\":\"" + chainName.ToString() + "_address\", (string) The " + chainName.ToString() + " address of the transaction. Not present for \n" " move transactions (category = move).\n" " \"category\":\"send|receive|move\", (string) The transaction category. 'move' is a local (off blockchain)\n" " transaction between accounts, and not associated with an address,\n" " transaction id or block. 'send' and 'receive' transactions are \n" " associated with an address, transaction id and block details\n" - " \"amount\": x.xxx, (numeric) The amount in " + strprintf("%s",komodo_chainname()) + ". This is negative for the 'send' category, and for the\n" + " \"amount\": x.xxx, (numeric) The amount in " + chainName.ToString() + ". This is negative for the 'send' category, and for the\n" " 'move' category for moves outbound. It is positive for the 'receive' category,\n" " and for the 'move' category for inbound funds.\n" " \"vout\" : n, (numeric) the vout value\n" - " \"fee\": x.xxx, (numeric) The amount of the fee in " + strprintf("%s",komodo_chainname()) + ". This is negative and only available for the \n" + " \"fee\": x.xxx, (numeric) The amount of the fee in " + chainName.ToString() + ". This is negative and only available for the \n" " 'send' category of transactions.\n" " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n" " 'receive' category of transactions.\n" @@ -2154,12 +2063,12 @@ UniValue listsinceblock(const UniValue& params, bool fHelp, const CPubKey& mypk) "{\n" " \"transactions\": [\n" " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. Will be \"\" for the default account.\n" - " \"address\":\"" + strprintf("%s",komodo_chainname()) + "_address\", (string) The " + strprintf("%s",komodo_chainname()) + " address of the transaction. Not present for move transactions (category = move).\n" + " \"address\":\"" + chainName.ToString() + "_address\", (string) The " + chainName.ToString() + " address of the transaction. Not present for move transactions (category = move).\n" " \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n" - " \"amount\": x.xxx, (numeric) The amount in " + strprintf("%s",komodo_chainname()) + ". This is negative for the 'send' category, and for the 'move' category for moves \n" + " \"amount\": x.xxx, (numeric) The amount in " + chainName.ToString() + ". This is negative for the 'send' category, and for the 'move' category for moves \n" " outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n" " \"vout\" : n, (numeric) the vout value\n" - " \"fee\": x.xxx, (numeric) The amount of the fee in " + strprintf("%s",komodo_chainname()) + ". This is negative and only available for the 'send' category of transactions.\n" + " \"fee\": x.xxx, (numeric) The amount of the fee in " + chainName.ToString() + ". This is negative and only available for the 'send' category of transactions.\n" " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n" " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n" " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n" @@ -2242,7 +2151,7 @@ UniValue gettransaction(const UniValue& params, bool fHelp, const CPubKey& mypk) "2. \"includeWatchonly\" (bool, optional, default=false) Whether to include watchonly addresses in balance calculation and details[]\n" "\nResult:\n" "{\n" - " \"amount\" : x.xxx, (numeric) The transaction amount in " + strprintf("%s",komodo_chainname()) + "\n" + " \"amount\" : x.xxx, (numeric) The transaction amount in " + chainName.ToString() + "\n" " \"confirmations\" : n, (numeric) The number of confirmations\n" " \"blockhash\" : \"hash\", (string) The block hash\n" " \"blockindex\" : xx, (numeric) The block index\n" @@ -2253,9 +2162,9 @@ UniValue gettransaction(const UniValue& params, bool fHelp, const CPubKey& mypk) " \"details\" : [\n" " {\n" " \"account\" : \"accountname\", (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n" - " \"address\" : \"" + strprintf("%s",komodo_chainname()) + "_address\", (string) The " + strprintf("%s",komodo_chainname()) + " address involved in the transaction\n" + " \"address\" : \"" + chainName.ToString() + "_address\", (string) The " + chainName.ToString() + " address involved in the transaction\n" " \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n" - " \"amount\" : x.xxx (numeric) The amount in " + strprintf("%s",komodo_chainname()) + "\n" + " \"amount\" : x.xxx (numeric) The amount in " + chainName.ToString() + "\n" " \"vout\" : n, (numeric) the vout value\n" " }\n" " ,...\n" @@ -2413,7 +2322,7 @@ UniValue walletpassphrase(const UniValue& params, bool fHelp, const CPubKey& myp throw runtime_error( "walletpassphrase \"passphrase\" timeout\n" "\nStores the wallet decryption key in memory for 'timeout' seconds.\n" - "This is needed prior to performing transactions related to private keys such as sending " + strprintf("%s",komodo_chainname()) + "\n" + "This is needed prior to performing transactions related to private keys such as sending " + chainName.ToString() + "\n" "\nArguments:\n" "1. \"passphrase\" (string, required) The wallet passphrase\n" "2. timeout (numeric, required) The time to keep the decryption key in seconds.\n" @@ -2558,7 +2467,7 @@ UniValue encryptwallet(const UniValue& params, bool fHelp, const CPubKey& mypk) return NullUniValue; string enableArg = "developerencryptwallet"; - int32_t flag = (komodo_acpublic(0) || ASSETCHAINS_SYMBOL[0] == 0); + int32_t flag = (komodo_acpublic(0) || chainName.isKMD() ); auto fEnableWalletEncryption = fExperimentalMode && GetBoolArg("-" + enableArg, flag); std::string strWalletEncryptionDisabledMsg = ""; @@ -2581,10 +2490,10 @@ UniValue encryptwallet(const UniValue& params, bool fHelp, const CPubKey& mypk) "\nExamples:\n" "\nEncrypt you wallet\n" + HelpExampleCli("encryptwallet", "\"my pass phrase\"") + - "\nNow set the passphrase to use the wallet, such as for signing or sending " + strprintf("%s",komodo_chainname()) + "\n" + "\nNow set the passphrase to use the wallet, such as for signing or sending " + chainName.ToString() + "\n" + HelpExampleCli("walletpassphrase", "\"my pass phrase\"") + "\nNow we can so something like sign\n" - + HelpExampleCli("signmessage", "\"" + strprintf("%s",komodo_chainname()) + "_address\" \"test message\"") + + + HelpExampleCli("signmessage", "\"" + chainName.ToString() + "_address\" \"test message\"") + "\nNow lock the wallet again by removing the passphrase\n" + HelpExampleCli("walletlock", "") + "\nAs a json rpc call\n" @@ -2632,7 +2541,7 @@ UniValue lockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk) "lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n" "\nUpdates list of temporarily unspendable outputs.\n" "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n" - "A locked transaction output will not be chosen by automatic coin selection, when spending " + strprintf("%s",komodo_chainname()) + ".\n" + "A locked transaction output will not be chosen by automatic coin selection, when spending " + chainName.ToString() + ".\n" "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n" "is always cleared (by virtue of process exit) when a node stops or fails.\n" "Also see the listunspent call\n" @@ -2765,7 +2674,7 @@ UniValue settxfee(const UniValue& params, bool fHelp, const CPubKey& mypk) "settxfee amount\n" "\nSet the transaction fee per kB.\n" "\nArguments:\n" - "1. amount (numeric, required) The transaction fee in " + strprintf("%s",komodo_chainname()) + "/kB rounded to the nearest 0.00000001\n" + "1. amount (numeric, required) The transaction fee in " + chainName.ToString() + "/kB rounded to the nearest 0.00000001\n" "\nResult\n" "true|false (boolean) Returns true if successful\n" "\nExamples:\n" @@ -2794,9 +2703,9 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) "\nResult:\n" "{\n" " \"walletversion\": xxxxx, (numeric) the wallet version\n" - " \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + strprintf("%s",komodo_chainname()) + "\n" - " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + strprintf("%s",komodo_chainname()) + "\n" - " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + strprintf("%s",komodo_chainname()) + "\n" + " \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + chainName.ToString() + "\n" + " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + chainName.ToString() + "\n" + " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + chainName.ToString() + "\n" " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n" " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n" " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n" @@ -2853,8 +2762,6 @@ UniValue resendwallettransactions(const UniValue& params, bool fHelp, const CPub return result; } -extern uint32_t komodo_segid32(char *coinaddr); - UniValue listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk) { if (!EnsureWalletIsAvailable(fHelp)) @@ -2871,9 +2778,9 @@ UniValue listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk) "\nArguments:\n" "1. minconf (numeric, optional, default=1) The minimum confirmations to filter\n" "2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n" - "3. \"addresses\" (string) A json array of " + strprintf("%s",komodo_chainname()) + " addresses to filter\n" + "3. \"addresses\" (string) A json array of " + chainName.ToString() + " addresses to filter\n" " [\n" - " \"address\" (string) " + strprintf("%s",komodo_chainname()) + " address\n" + " \"address\" (string) " + chainName.ToString() + " address\n" " ,...\n" " ]\n" "\nResult\n" @@ -2975,16 +2882,15 @@ UniValue listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk) BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); CBlockIndex *tipindex,*pindex = it->second; uint64_t interest; uint32_t locktime; - if ( pindex != 0 && (tipindex= chainActive.LastTip()) != 0 ) + if ( pindex != 0 && (tipindex= chainActive.Tip()) != 0 ) { interest = komodo_accrued_interest(&txheight,&locktime,out.tx->GetHash(),out.i,0,nValue,(int32_t)tipindex->nHeight); //interest = komodo_interest(txheight,nValue,out.tx->nLockTime,tipindex->nTime); entry.push_back(Pair("interest",ValueFromAmount(interest))); } - //fprintf(stderr,"nValue %.8f pindex.%p tipindex.%p locktime.%u txheight.%d pindexht.%d\n",(double)nValue/COIN,pindex,chainActive.LastTip(),locktime,txheight,pindex->nHeight); } - else if ( chainActive.LastTip() != 0 ) - txheight = (chainActive.LastTip()->nHeight - out.nDepth - 1); + else if ( chainActive.Tip() != 0 ) + txheight = (chainActive.Tip()->nHeight - out.nDepth - 1); entry.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()))); entry.push_back(Pair("rawconfirmations",out.nDepth)); entry.push_back(Pair("confirmations",komodo_dpowconfs(txheight,out.nDepth))); @@ -2994,12 +2900,18 @@ UniValue listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk) return results; } +/**** + * @note also sets globals KOMODO_INTERESTSUM and KOMODO_WALLETBALANCE used for the getinfo RPC call + * @returns amount of accrued interest in this wallet + */ uint64_t komodo_interestsum() { #ifdef ENABLE_WALLET - if ( ASSETCHAINS_SYMBOL[0] == 0 && GetBoolArg("-disablewallet", false) == 0 && KOMODO_NSPV_FULLNODE ) + if ( chainName.isKMD() && GetBoolArg("-disablewallet", false) == 0 && KOMODO_NSPV_FULLNODE ) { - uint64_t interest,sum = 0; int32_t txheight; uint32_t locktime; + uint64_t interest,sum = 0; + int32_t txheight; + uint32_t locktime; vector vecOutputs; assert(pwalletMain != NULL); LOCK2(cs_main, pwalletMain->cs_wallet); @@ -3011,10 +2923,9 @@ uint64_t komodo_interestsum() { BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); CBlockIndex *tipindex,*pindex = it->second; - if ( pindex != 0 && (tipindex= chainActive.LastTip()) != 0 ) + if ( pindex != 0 && (tipindex= chainActive.Tip()) != 0 ) { interest = komodo_accrued_interest(&txheight,&locktime,out.tx->GetHash(),out.i,0,nValue,(int32_t)tipindex->nHeight); - //interest = komodo_interest(pindex->nHeight,nValue,out.tx->nLockTime,tipindex->nTime); sum += interest; } } @@ -3744,7 +3655,7 @@ UniValue z_getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk if (!EnsureWalletIsAvailable(fHelp)) return NullUniValue; - bool allowSapling = (Params().GetConsensus().vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight <= chainActive.LastTip()->nHeight); + bool allowSapling = (Params().GetConsensus().vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight <= chainActive.Tip()->nHeight); std::string defaultType; if ( GetTime() < KOMODO_SAPLING_ACTIVATION ) @@ -3760,7 +3671,7 @@ UniValue z_getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk "1. \"type\" (string, optional, default=\"" + defaultType + "\") The type of address. One of [\"" + ADDR_TYPE_SPROUT + "\", \"" + ADDR_TYPE_SAPLING + "\"].\n" "\nResult:\n" - "\"" + strprintf("%s",komodo_chainname()) + "_address\" (string) The new shielded address.\n" + "\"" + chainName.ToString() + "_address\" (string) The new shielded address.\n" "\nExamples:\n" + HelpExampleCli("z_getnewaddress", "") + HelpExampleCli("z_getnewaddress", ADDR_TYPE_SAPLING) @@ -4507,8 +4418,6 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk) LOCK2(cs_main, pwalletMain->cs_wallet); - //THROW_IF_SYNCING(KOMODO_INSYNC); - // Check that the from address is valid. auto fromaddress = params[0].get_str(); bool fromTaddr = false; @@ -4592,7 +4501,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk) if ( fromSprout || toSprout ) throw JSONRPCError(RPC_INVALID_PARAMETER,"Sprout usage has expired"); } - if ( toSapling && ASSETCHAINS_SYMBOL[0] == 0 ) + if ( toSapling && chainName.isKMD() ) throw JSONRPCError(RPC_INVALID_PARAMETER,"Sprout usage will expire soon"); // If we are sending from a shielded address, all recipient @@ -4819,8 +4728,6 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& myp LOCK2(cs_main, pwalletMain->cs_wallet); - //THROW_IF_SYNCING(KOMODO_INSYNC); - // Validate the from address auto fromaddress = params[0].get_str(); bool isFromWildcard = fromaddress == "*"; @@ -4977,12 +4884,12 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& myp Params().GetConsensus(), nextBlockHeight, pwalletMain); // Contextual transaction we will build on - int blockHeight = chainActive.LastTip()->nHeight; + int blockHeight = chainActive.Tip()->nHeight; nextBlockHeight = blockHeight + 1; // (used if no Sapling addresses are involved) CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction( Params().GetConsensus(), nextBlockHeight); - contextualTx.nLockTime = chainActive.LastTip()->nHeight; + contextualTx.nLockTime = chainActive.Tip()->nHeight; if (contextualTx.nVersion == 1) { contextualTx.nVersion = 2; // Tx format should support vjoinsplits @@ -5081,8 +4988,6 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp LOCK2(cs_main, pwalletMain->cs_wallet); - //THROW_IF_SYNCING(KOMODO_INSYNC); - bool useAnyUTXO = false; bool useAnySprout = false; bool useAnySapling = false; @@ -5490,7 +5395,6 @@ UniValue z_listoperationids(const UniValue& params, bool fHelp, const CPubKey& m #include "script/sign.h" -extern std::string NOTARY_PUBKEY; /** * @brief Search for 10k sat. P2PK notary utxos and make proof tx (txNew) from it for further include in block. @@ -5581,10 +5485,8 @@ int32_t komodo_notaryvin(CMutableTransaction &txNew, uint8_t *notarypub33, const #include "../cc/CCchannels.h" #include "../cc/CCOracles.h" #include "../cc/CCGateways.h" -#include "../cc/CCPrices.h" #include "../cc/CCHeir.h" #include "../cc/CCPayments.h" -#include "../cc/CCPegs.h" int32_t ensure_CCrequirements(uint8_t evalcode) { @@ -6020,43 +5922,6 @@ UniValue oraclesaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) return(CCaddress(cp,(char *)"Oracles",pubkey)); } -UniValue pricesaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); struct CCcontract_info *cp,C,*assetscp,C2; std::vector pubkey; CPubKey pk,planpk,pricespk; char myaddr[64],houseaddr[64],exposureaddr[64]; - cp = CCinit(&C,EVAL_PRICES); - assetscp = CCinit(&C2,EVAL_PRICES); - if ( fHelp || params.size() > 1 ) - throw runtime_error("pricesaddress [pubkey]\n"); - if ( ensure_CCrequirements(cp->evalcode) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - if ( params.size() == 1 ) - pubkey = ParseHex(params[0].get_str().c_str()); - result = CCaddress(cp,(char *)"Prices",pubkey); - if (mypk.IsValid()) pk=mypk; - else pk = pubkey2pk(Mypubkey()); - pricespk = GetUnspendable(cp,0); - GetCCaddress(assetscp,myaddr,pk); - GetCCaddress1of2(assetscp,houseaddr,pricespk,planpk); - GetCCaddress1of2(assetscp,exposureaddr,pricespk,pricespk); - result.push_back(Pair("myaddr",myaddr)); // for holding my asssets - result.push_back(Pair("houseaddr",houseaddr)); // globally accessible house assets - result.push_back(Pair("exposureaddr",exposureaddr)); // tracking of exposure - return(result); -} - -UniValue pegsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - struct CCcontract_info *cp,C; std::vector pubkey; - cp = CCinit(&C,EVAL_PEGS); - if ( fHelp || params.size() > 1 ) - throw runtime_error("pegssaddress [pubkey]\n"); - if ( ensure_CCrequirements(cp->evalcode) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - if ( params.size() == 1 ) - pubkey = ParseHex(params[0].get_str().c_str()); - return(CCaddress(cp,(char *)"Pegs",pubkey)); -} - UniValue paymentsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) { struct CCcontract_info *cp,C; std::vector pubkey; @@ -7080,65 +6945,6 @@ UniValue faucetget(const UniValue& params, bool fHelp, const CPubKey& mypk) return(result); } -uint32_t pricesGetParam(UniValue param) { - uint32_t filter = 0; - if (STR_TOLOWER(param.get_str()) == "all") - filter = 0; - else if (STR_TOLOWER(param.get_str()) == "open") - filter = 1; - else if (STR_TOLOWER(param.get_str()) == "closed") - filter = 2; - else - throw runtime_error("incorrect parameter\n"); - return filter; -} - -UniValue priceslist(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - if ( fHelp || params.size() != 0 && params.size() != 1) - throw runtime_error("priceslist [all|open|closed]\n"); - if ( ensure_CCrequirements(EVAL_PRICES) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - uint32_t filter = 0; - if (params.size() == 1) - filter = pricesGetParam(params[0]); - - CPubKey emptypk; - - return(PricesList(filter, emptypk)); -} - -UniValue mypriceslist(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - if (fHelp || params.size() != 0 && params.size() != 1) - throw runtime_error("mypriceslist [all|open|closed]\n"); - if (ensure_CCrequirements(EVAL_PRICES) < 0) - throw runtime_error(CC_REQUIREMENTS_MSG); - - uint32_t filter = 0; - if (params.size() == 1) - filter = pricesGetParam(params[0]); - CPubKey pk; - if (mypk.IsValid()) pk=mypk; - else pk = pubkey2pk(Mypubkey()); - - return(PricesList(filter, pk)); -} - -UniValue pricesinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - uint256 bettxid; int32_t height; - if ( fHelp || params.size() != 1 && params.size() != 2) - throw runtime_error("pricesinfo bettxid [height]\n"); - if ( ensure_CCrequirements(EVAL_PRICES) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - bettxid = Parseuint256((char *)params[0].get_str().c_str()); - height = 0; - if (params.size() == 2) - height = atoi(params[1].get_str().c_str()); - return(PricesInfo(bettxid, height)); -} - UniValue dicefund(const UniValue& params, bool fHelp, const CPubKey& mypk) { UniValue result(UniValue::VOBJ); int64_t funds,minbet,maxbet,maxodds,timeoutblocks; std::string hex; char *name; @@ -8009,192 +7815,6 @@ UniValue heirlist(const UniValue& params, bool fHelp, const CPubKey& mypk) return (HeirList()); } -UniValue pegscreate(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); int32_t i; std::vector txids; - uint8_t N; uint256 txid; int64_t amount; - - if ( fHelp || params.size()<3) - throw runtime_error("pegscreate amount N bindtxid1 [bindtxid2 ...]\n"); - if ( ensure_CCrequirements(EVAL_PEGS) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - const CKeyStore& keystore = *pwalletMain; - Lock2NSPV(mypk); - amount = atof((char *)params[0].get_str().c_str()) * COIN + 0.00000000499999; - N = atoi((char *)params[1].get_str().c_str()); - if ( params.size() < N+1 ) - { - Unlock2NSPV(mypk); - throw runtime_error("not enough parameters for N pegscreate\n"); - } - for (i=0; i 0 ) - { - result.push_back(Pair("result", "success")); - } - Unlock2NSPV(mypk); - return(result); -} - -UniValue pegsfund(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); uint256 pegstxid,tokenid; int64_t amount; - - - if ( fHelp || params.size()!=3) - throw runtime_error("pegsfund pegstxid tokenid amount\n"); - if ( ensure_CCrequirements(EVAL_PEGS) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - const CKeyStore& keystore = *pwalletMain; - Lock2NSPV(mypk); - pegstxid = Parseuint256(params[0].get_str().c_str()); - tokenid = Parseuint256(params[1].get_str().c_str()); - amount = atof((char *)params[2].get_str().c_str()) * COIN + 0.00000000499999; - result = PegsFund(mypk,0,pegstxid,tokenid,amount); - if ( result[JSON_HEXTX].getValStr().size() > 0 ) - { - result.push_back(Pair("result", "success")); - } - Unlock2NSPV(mypk); - return(result); -} - -UniValue pegsget(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); uint256 pegstxid,tokenid; int64_t amount; - - if ( fHelp || params.size()!=3) - throw runtime_error("pegsget pegstxid tokenid amount\n"); - if ( ensure_CCrequirements(EVAL_PEGS) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - Lock2NSPV(mypk); - pegstxid = Parseuint256(params[0].get_str().c_str()); - tokenid = Parseuint256(params[1].get_str().c_str()); - amount = atof((char *)params[2].get_str().c_str()) * COIN + 0.00000000499999; - result = PegsGet(mypk,0,pegstxid,tokenid,amount); - if ( result[JSON_HEXTX].getValStr().size() > 0 ) - { - result.push_back(Pair("result", "success")); - } - Unlock2NSPV(mypk); - return(result); -} - -UniValue pegsredeem(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); uint256 pegstxid,tokenid; int64_t amount; - - if ( fHelp || params.size()!=2) - throw runtime_error("pegsredeem pegstxid tokenid\n"); - if ( ensure_CCrequirements(EVAL_PEGS) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - Lock2NSPV(mypk); - pegstxid = Parseuint256(params[0].get_str().c_str()); - tokenid = Parseuint256(params[1].get_str().c_str()); - result = PegsRedeem(mypk,0,pegstxid,tokenid); - if ( result[JSON_HEXTX].getValStr().size() > 0 ) - { - result.push_back(Pair("result", "success")); - } - Unlock2NSPV(mypk); - return(result); -} - -UniValue pegsliquidate(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); uint256 pegstxid,tokenid,accounttxid; - - if ( fHelp || params.size()!=3) - throw runtime_error("pegsliquidate pegstxid tokenid accounttxid\n"); - if ( ensure_CCrequirements(EVAL_PEGS) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - Lock2NSPV(mypk); - pegstxid = Parseuint256(params[0].get_str().c_str()); - tokenid = Parseuint256(params[1].get_str().c_str()); - accounttxid = Parseuint256(params[2].get_str().c_str()); - result = PegsLiquidate(mypk,0,pegstxid,tokenid,accounttxid); - if ( result[JSON_HEXTX].getValStr().size() > 0 ) - { - result.push_back(Pair("result", "success")); - } - Unlock2NSPV(mypk); - return(result); -} - -UniValue pegsexchange(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); uint256 pegstxid,tokenid,accounttxid; int64_t amount; - - if ( fHelp || params.size()!=3) - throw runtime_error("pegsexchange pegstxid tokenid amount\n"); - if ( ensure_CCrequirements(EVAL_PEGS) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - Lock2NSPV(mypk); - pegstxid = Parseuint256(params[0].get_str().c_str()); - tokenid = Parseuint256(params[1].get_str().c_str()); - amount = atof((char *)params[2].get_str().c_str()) * COIN + 0.00000000499999; - result = PegsExchange(mypk,0,pegstxid,tokenid,amount); - if ( result[JSON_HEXTX].getValStr().size() > 0 ) - { - result.push_back(Pair("result", "success")); - } - Unlock2NSPV(mypk); - return(result); -} - -UniValue pegsaccounthistory(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - uint256 pegstxid; - - if ( fHelp || params.size() != 1 ) - throw runtime_error("pegsaccounthistory pegstxid\n"); - if ( ensure_CCrequirements(EVAL_GATEWAYS) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - pegstxid = Parseuint256((char *)params[0].get_str().c_str()); - return(PegsAccountHistory(mypk,pegstxid)); -} - -UniValue pegsaccountinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - uint256 pegstxid; - - if ( fHelp || params.size() != 1 ) - throw runtime_error("pegsaccountinfo pegstxid\n"); - if ( ensure_CCrequirements(EVAL_GATEWAYS) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - pegstxid = Parseuint256((char *)params[0].get_str().c_str()); - return(PegsAccountInfo(mypk,pegstxid)); -} - -UniValue pegsworstaccounts(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - uint256 pegstxid; - - if ( fHelp || params.size() != 1 ) - throw runtime_error("pegsworstaccounts pegstxid\n"); - if ( ensure_CCrequirements(EVAL_GATEWAYS) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - pegstxid = Parseuint256((char *)params[0].get_str().c_str()); - return(PegsWorstAccounts(pegstxid)); -} - -UniValue pegsinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - uint256 pegstxid; - - if ( fHelp || params.size() != 1 ) - throw runtime_error("pegsinfo pegstxid\n"); - if ( ensure_CCrequirements(EVAL_GATEWAYS) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - pegstxid = Parseuint256((char *)params[0].get_str().c_str()); - return(PegsInfo(pegstxid)); -} - extern UniValue dumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp extern UniValue convertpassphrase(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue importprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h index 7739e94a2e2..8dc0e4044da 100644 --- a/src/wallet/rpcwallet.h +++ b/src/wallet/rpcwallet.h @@ -23,5 +23,18 @@ class CRPCTable; void RegisterWalletRPCCommands(CRPCTable &tableRPC); +uint64_t komodo_interestsum(); +int32_t ensure_CCrequirements(uint8_t evalcode); +/** + * @brief Search for 10k sat. P2PK notary utxos and make proof tx (txNew) from it for further include in block. + * opretIn should be empty script before december hardfork, and contains prepared opret script after. + * + * @param txNew - out: signed notary proof tx + * @param notarypub33 - notary node compressed pubkey to search 10k sat. P2PK utxos in the wallet (wallet should be unlocked) + * @param opretIn - after nDecemberHardforkHeight, prepared in advance opret script, before nDecemberHardforkHeight should be empty script + * @param nLockTimeIn - nLockTime that will be set for notary proof tx in-case of after nDecemberHardforkHeight + * @return int32_t - signature length of vin[0] in resulted notary proof tx, actually > 0 if txNew is correct, and 0 in-case of any error + */ +int32_t komodo_notaryvin(CMutableTransaction &txNew, uint8_t *notarypub33, const CScript &opretIn, uint32_t nLockTimeIn); #endif //BITCOIN_WALLET_RPCWALLET_H diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index e69e67c231a..f5707a14313 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -39,6 +39,11 @@ #include "coins.h" #include "zcash/zip32.h" #include "cc/CCinclude.h" +#include "komodo_utils.h" +#include "komodo_bitcoind.h" +#include "komodo_notary.h" +#include "komodo_interest.h" +#include "komodo_globals.h" #include @@ -60,10 +65,10 @@ bool fSendFreeTransactions = false; bool fPayAtLeastCustomFee = true; #include "komodo_defs.h" -CBlockIndex *komodo_chainactive(int32_t height); -extern std::string DONATION_PUBKEY; -int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); -int tx_height( const uint256 &hash ); +// TODO: remove +//CBlockIndex *komodo_chainactive(int32_t height); +//extern std::string DONATION_PUBKEY; +//int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); /** * Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) @@ -771,12 +776,12 @@ set CWallet::GetConflicts(const uint256& txid) const void CWallet::Flush(bool shutdown) { - bitdb.Flush(shutdown); + bitdb->Flush(shutdown); } bool CWallet::Verify(const string& walletFile, string& warningString, string& errorString) { - if (!bitdb.Open(GetDataDir())) + if (!bitdb->Open(GetDataDir())) { // try moving the database env out of the way boost::filesystem::path pathDatabase = GetDataDir() / "database"; @@ -789,7 +794,7 @@ bool CWallet::Verify(const string& walletFile, string& warningString, string& er } // try again - if (!bitdb.Open(GetDataDir())) { + if (!bitdb->Open(GetDataDir())) { // if it still fails, it probably means we can't even create the database env string msg = strprintf(_("Error initializing wallet database environment %s!"), GetDataDir()); errorString += msg; @@ -800,13 +805,13 @@ bool CWallet::Verify(const string& walletFile, string& warningString, string& er if (GetBoolArg("-salvagewallet", false)) { // Recover readable keypairs: - if (!CWalletDB::Recover(bitdb, walletFile, true)) + if (!CWalletDB::Recover(*bitdb, walletFile, true)) return false; } if (boost::filesystem::exists(GetDataDir() / walletFile)) { - CDBEnv::VerifyResult r = bitdb.Verify(walletFile, CWalletDB::Recover); + CDBEnv::VerifyResult r = bitdb->Verify(walletFile, CWalletDB::Recover); if (r == CDBEnv::RECOVER_OK) { warningString += strprintf(_("Warning: wallet.dat corrupt, data salvaged!" @@ -1138,8 +1143,6 @@ void CWallet::IncrementNoteWitnesses(const CBlockIndex* pindex, template bool DecrementNoteWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize) { - extern int32_t KOMODO_REWIND; - for (auto& item : noteDataMap) { auto* nd = &(item.second); // Only decrement witnesses that are not above the current height @@ -2500,45 +2503,6 @@ int64_t CWalletTx::GetTxTime() const return n ? n : nTimeReceived; } -int CWalletTx::GetRequestCount() const -{ - // Returns -1 if it wasn't being tracked - int nRequests = -1; - { - LOCK(pwallet->cs_wallet); - if (IsCoinBase()) - { - // Generated block - if (!hashBlock.IsNull()) - { - map::const_iterator mi = pwallet->mapRequestCount.find(hashBlock); - if (mi != pwallet->mapRequestCount.end()) - nRequests = (*mi).second; - } - } - else - { - // Did anyone request this transaction? - map::const_iterator mi = pwallet->mapRequestCount.find(GetHash()); - if (mi != pwallet->mapRequestCount.end()) - { - nRequests = (*mi).second; - - // How about the block it's in? - if (nRequests == 0 && !hashBlock.IsNull()) - { - map::const_iterator mi = pwallet->mapRequestCount.find(hashBlock); - if (mi != pwallet->mapRequestCount.end()) - nRequests = (*mi).second; - else - nRequests = 1; // If it's in someone else's block it must have got out - } - } - } - } - return nRequests; -} - // GetAmounts will determine the transparent debits and credits for a given wallet tx. void CWalletTx::GetAmounts(list& listReceived, list& listSent, CAmount& nFee, string& strSentAccount, const isminefilter& filter) const @@ -2788,7 +2752,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup double dProgressStart = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex, false); - double dProgressTip = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.LastTip(), false); + double dProgressTip = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip(), false); while (pindex) { if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0) @@ -3281,9 +3245,6 @@ CAmount CWallet::GetImmatureWatchOnlyBalance() const /** * populate vCoins with vector of available COutputs. */ -uint64_t komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); -uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); - void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl, bool fIncludeZeroValue, bool fIncludeCoinBase) const { uint64_t interest,*ptr; @@ -3322,25 +3283,21 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const if ( !IS_MODE_EXCHANGEWALLET ) { uint32_t locktime; int32_t txheight; CBlockIndex *tipindex; - if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.LastTip() != 0 && chainActive.LastTip()->nHeight >= 60000 ) + if ( chainName.isKMD() && chainActive.Tip() != 0 && chainActive.Tip()->nHeight >= 60000 ) { if ( pcoin->vout[i].nValue >= 10*COIN ) { - if ( (tipindex= chainActive.LastTip()) != 0 ) + if ( (tipindex= chainActive.Tip()) != 0 ) { komodo_accrued_interest(&txheight,&locktime,wtxid,i,0,pcoin->vout[i].nValue,(int32_t)tipindex->nHeight); interest = komodo_interestnew(txheight,pcoin->vout[i].nValue,locktime,tipindex->nTime); - } else interest = 0; - //interest = komodo_interestnew(chainActive.LastTip()->nHeight+1,pcoin->vout[i].nValue,pcoin->nLockTime,chainActive.LastTip()->nTime); + } + else + interest = 0; if ( interest != 0 ) { - //printf("wallet nValueRet %.8f += interest %.8f ht.%d lock.%u/%u tip.%u\n",(double)pcoin->vout[i].nValue/COIN,(double)interest/COIN,txheight,locktime,pcoin->nLockTime,tipindex->nTime); - //fprintf(stderr,"wallet nValueRet %.8f += interest %.8f ht.%d lock.%u tip.%u\n",(double)pcoin->vout[i].nValue/COIN,(double)interest/COIN,chainActive.LastTip()->nHeight+1,pcoin->nLockTime,chainActive.LastTip()->nTime); - //ptr = (uint64_t *)&pcoin->vout[i].nValue; - //(*ptr) += interest; ptr = (uint64_t *)&pcoin->vout[i].interest; (*ptr) = interest; - //pcoin->vout[i].nValue += interest; } else { @@ -3517,7 +3474,9 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int return true; } -bool CWallet::SelectCoins(const CAmount& nTargetValue, set >& setCoinsRet, CAmount& nValueRet, bool& fOnlyCoinbaseCoinsRet, bool& fNeedCoinbaseCoinsRet, const CCoinControl* coinControl) const +bool CWallet::SelectCoins(const CAmount& nTargetValue, set >& setCoinsRet, + CAmount& nValueRet, bool& fOnlyCoinbaseCoinsRet, bool& fNeedCoinbaseCoinsRet, + const CCoinControl* coinControl) const { // Output parameter fOnlyCoinbaseCoinsRet is set to true when the only available coins are coinbase utxos. uint64_t tmp; int32_t retval; @@ -3614,7 +3573,16 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set vecSend; @@ -3658,8 +3626,20 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nC return true; } -bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, - int& nChangePosRet, std::string& strFailReason, const CCoinControl* coinControl, bool sign) +/***** + * @brief create a transaction + * @param vecSend who to send to + * @param wtxNew wallet transaction + * @param reservekey + * @param nFeeRet + * @param nChangePosRet + * @param strFailReason + * @param coinControl + * @param sign true to sign inputs + */ +bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, + CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason, const CCoinControl* coinControl, + bool sign) { uint64_t interest2 = 0; CAmount nValue = 0; unsigned int nSubtractFeeFromAmount = 0; BOOST_FOREACH (const CRecipient& recipient, vecSend) @@ -3685,12 +3665,12 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt int nextBlockHeight = chainActive.Height() + 1; CMutableTransaction txNew = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextBlockHeight); - if (IS_MODE_EXCHANGEWALLET && ASSETCHAINS_SYMBOL[0] == 0) + if (IS_MODE_EXCHANGEWALLET && chainName.isKMD()) txNew.nLockTime = 0; else { - if ( !komodo_hardfork_active((uint32_t)chainActive.LastTip()->nTime) ) - txNew.nLockTime = (uint32_t)chainActive.LastTip()->nTime + 1; // set to a time close to now + if ( !komodo_hardfork_active((uint32_t)chainActive.Tip()->nTime) ) + txNew.nLockTime = (uint32_t)chainActive.Tip()->nTime + 1; // set to a time close to now else txNew.nLockTime = (uint32_t)chainActive.Tip()->GetMedianTimePast(); } @@ -3804,7 +3784,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt //a chance at a free transaction. //But mempool inputs might still be in the mempool, so their age stays 0 //fprintf(stderr,"nCredit %.8f interest %.8f\n",(double)nCredit/COIN,(double)pcoin.first->vout[pcoin.second].interest/COIN); - if ( !IS_MODE_EXCHANGEWALLET && ASSETCHAINS_SYMBOL[0] == 0 ) + if ( !IS_MODE_EXCHANGEWALLET && chainName.isKMD() ) { interest2 += pcoin.first->vout[pcoin.second].interest; //fprintf(stderr,"%.8f ",(double)pcoin.first->vout[pcoin.second].interest/COIN); @@ -3814,7 +3794,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt age += 1; dPriority += (double)nCredit * age; } - if ( ASSETCHAINS_SYMBOL[0] == 0 && DONATION_PUBKEY.size() == 66 && interest2 > 5000 ) + if ( chainName.isKMD() && DONATION_PUBKEY.size() == 66 && interest2 > 5000 ) { CScript scriptDonation = CScript() << ParseHex(DONATION_PUBKEY) << OP_CHECKSIG; CTxOut newTxOut(interest2,scriptDonation); @@ -3851,7 +3831,6 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt // Reserve a new key pair from key pool CPubKey vchPubKey; - extern int32_t USE_EXTERNAL_PUBKEY; extern std::string NOTARY_PUBKEY; if ( USE_EXTERNAL_PUBKEY == 0 ) { bool ret; @@ -3916,7 +3895,6 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt // Check mempooltxinputlimit to avoid creating a transaction which the local mempool rejects size_t limit = (size_t)GetArg("-mempooltxinputlimit", 0); { - LOCK(cs_main); if (NetworkUpgradeActive(chainActive.Height() + 1, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) { limit = 0; } @@ -4049,9 +4027,6 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) delete pwalletdb; } - // Track how many getdata requests our transaction gets - mapRequestCount[wtxNew.GetHash()] = 0; - if (fBroadcastTransactions) { // Broadcast @@ -4091,27 +4066,12 @@ CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarge return nFeeNeeded; } - -void komodo_prefetch(FILE *fp); - DBErrors CWallet::LoadWallet(bool& fFirstRunRet) { if (!fFileBacked) return DB_LOAD_OK; fFirstRunRet = false; - if ( 0 ) // doesnt help - { - fprintf(stderr,"loading wallet %s %u\n",strWalletFile.c_str(),(uint32_t)time(NULL)); - FILE *fp; - if ( (fp= fopen(strWalletFile.c_str(),"rb")) != 0 ) - { - komodo_prefetch(fp); - fclose(fp); - } - } - //fprintf(stderr,"prefetched wallet %s %u\n",strWalletFile.c_str(),(uint32_t)time(NULL)); DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this); - //fprintf(stderr,"loaded wallet %s %u\n",strWalletFile.c_str(),(uint32_t)time(NULL)); if (nLoadWalletRet == DB_NEED_REWRITE) { if (CDB::Rewrite(strWalletFile, "\x04pool")) @@ -4875,15 +4835,13 @@ int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet) const int CMerkleTx::GetBlocksToMaturity() const { - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - COINBASE_MATURITY = _COINBASE_MATURITY; if (!IsCoinBase()) return 0; int32_t depth = GetDepthInMainChain(); int32_t ut = UnlockTime(0); int32_t toMaturity = (ut - chainActive.Height()) < 0 ? 0 : ut - chainActive.Height(); //printf("depth.%i, unlockTime.%i, toMaturity.%i\n", depth, ut, toMaturity); - ut = (COINBASE_MATURITY - depth) < 0 ? 0 : COINBASE_MATURITY - depth; + ut = (Params().CoinbaseMaturity() - depth) < 0 ? 0 : Params().CoinbaseMaturity() - depth; return(ut < toMaturity ? toMaturity : ut); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index b1e5b66b82a..ac45158daa8 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -602,7 +602,6 @@ class CWalletTx : public CMerkleTx bool WriteToDisk(CWalletDB *pwalletdb); int64_t GetTxTime() const; - int GetRequestCount() const; bool RelayWalletTransaction(); @@ -747,6 +746,8 @@ class CAccountingEntry */ class CWallet : public CCryptoKeyStore, public CValidationInterface { +protected: + bool fBroadcastTransactions; private: bool SelectCoins(const CAmount& nTargetValue, std::set >& setCoinsRet, CAmount& nValueRet, bool& fOnlyCoinbaseCoinsRet, bool& fNeedCoinbaseCoinsRet, const CCoinControl *coinControl = NULL) const; @@ -760,7 +761,6 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface int64_t nNextResend; int64_t nLastResend; - bool fBroadcastTransactions; template using TxSpendMap = std::multimap; @@ -976,7 +976,6 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface std::map mapWallet; int64_t nOrderPosNext; - std::map mapRequestCount; std::map mapAddressBook; @@ -1226,16 +1225,6 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface void UpdatedTransaction(const uint256 &hashTx); - void Inventory(const uint256 &hash) - { - { - LOCK(cs_wallet); - std::map::iterator mi = mapRequestCount.find(hash); - if (mi != mapRequestCount.end()) - (*mi).second++; - } - } - unsigned int GetKeyPoolSize() { AssertLockHeld(cs_wallet); // setKeyPool diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index da1f07871c7..003c7ca0379 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -31,6 +31,7 @@ #include "wallet/wallet.h" #include "zcash/Proof.hpp" #include "komodo_defs.h" +#include "komodo_bitcoind.h" #include #include @@ -41,7 +42,6 @@ using namespace std; static uint64_t nAccountingEntryNumber = 0; static list deadTxns; -extern CBlockIndex *komodo_blockindex(uint256 hash); // // CWalletDB @@ -1139,13 +1139,13 @@ void ThreadFlushWalletDB(const string& strFile) if (nLastFlushed != nWalletDBUpdated && GetTime() - nLastWalletUpdate >= 2) { - TRY_LOCK(bitdb.cs_db,lockDb); + TRY_LOCK(bitdb->cs_db,lockDb); if (lockDb) { // Don't do this if any databases are in use int nRefCount = 0; - map::iterator mi = bitdb.mapFileUseCount.begin(); - while (mi != bitdb.mapFileUseCount.end()) + map::iterator mi = bitdb->mapFileUseCount.begin(); + while (mi != bitdb->mapFileUseCount.end()) { nRefCount += (*mi).second; mi++; @@ -1154,18 +1154,18 @@ void ThreadFlushWalletDB(const string& strFile) if (nRefCount == 0) { boost::this_thread::interruption_point(); - map::iterator mi = bitdb.mapFileUseCount.find(strFile); - if (mi != bitdb.mapFileUseCount.end()) + map::iterator mi = bitdb->mapFileUseCount.find(strFile); + if (mi != bitdb->mapFileUseCount.end()) { LogPrint("db", "Flushing wallet.dat\n"); nLastFlushed = nWalletDBUpdated; int64_t nStart = GetTimeMillis(); // Flush wallet.dat so it's self contained - bitdb.CloseDb(strFile); - bitdb.CheckpointLSN(strFile); + bitdb->CloseDb(strFile); + bitdb->CheckpointLSN(strFile); - bitdb.mapFileUseCount.erase(mi++); + bitdb->mapFileUseCount.erase(mi++); LogPrint("db", "Flushed wallet.dat %dms\n", GetTimeMillis() - nStart); } } @@ -1181,13 +1181,13 @@ bool BackupWallet(const CWallet& wallet, const string& strDest) while (true) { { - LOCK(bitdb.cs_db); - if (!bitdb.mapFileUseCount.count(wallet.strWalletFile) || bitdb.mapFileUseCount[wallet.strWalletFile] == 0) + LOCK(bitdb->cs_db); + if (!bitdb->mapFileUseCount.count(wallet.strWalletFile) || bitdb->mapFileUseCount[wallet.strWalletFile] == 0) { // Flush log data to the dat file - bitdb.CloseDb(wallet.strWalletFile); - bitdb.CheckpointLSN(wallet.strWalletFile); - bitdb.mapFileUseCount.erase(wallet.strWalletFile); + bitdb->CloseDb(wallet.strWalletFile); + bitdb->CheckpointLSN(wallet.strWalletFile); + bitdb->mapFileUseCount.erase(wallet.strWalletFile); // Copy wallet.dat boost::filesystem::path pathSrc = GetDataDir() / wallet.strWalletFile; diff --git a/src/zcash/CreateJoinSplit.cpp b/src/zcash/CreateJoinSplit.cpp index 06b76bb9b6a..9a4e45688f1 100644 --- a/src/zcash/CreateJoinSplit.cpp +++ b/src/zcash/CreateJoinSplit.cpp @@ -8,7 +8,6 @@ #include "libsnark/common/profiling.hpp" #include "komodo_defs.h" -char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; uint16_t BITCOIND_RPCPORT = 7771; uint32_t ASSETCHAINS_CC = 0; diff --git a/src/zcbenchmarks.cpp b/src/zcbenchmarks.cpp index 0a272c8a1d8..702686b21e1 100644 --- a/src/zcbenchmarks.cpp +++ b/src/zcbenchmarks.cpp @@ -53,7 +53,7 @@ void pre_wallet_load() UnregisterValidationInterface(pwalletMain); delete pwalletMain; pwalletMain = NULL; - bitdb.Reset(); + bitdb->Reset(); RegisterNodeSignals(GetNodeSignals()); LogPrintf("%s: done\n", __func__); } diff --git a/zcutil/build-mac-dtest.sh b/zcutil/build-mac-dtest.sh index 8104c720009..06171305bdd 100755 --- a/zcutil/build-mac-dtest.sh +++ b/zcutil/build-mac-dtest.sh @@ -18,11 +18,13 @@ Usage: $0 --help Show this help message and exit. -$0 [ --enable-lcov ] [ MAKEARGS... ] - Build Zcash and most of its transitive dependencies from - source. MAKEARGS are applied to both dependencies and Zcash itself. If - --enable-lcov is passed, Zcash is configured to add coverage +$0 [ --enable-lcov ] [ --enable-debug ] [ MAKEARGS... ] + Build Komodo and most of its transitive dependencies from + source. MAKEARGS are applied to both dependencies and Komodo itself. + If --enable-lcov is passed, Komodo is configured to add coverage instrumentation, thus enabling "make cov" to work. + If --enable-debug is passed, Komodo is built with debugging information. It + must be passed after the previous arguments, if present. EOF exit 0 fi @@ -37,22 +39,25 @@ then shift fi +# If --enable-debug is the next argument, enable debugging +DEBUGGING_ARG='' +if [ "x${1:-}" = 'x--enable-debug' ] +then + DEBUG=1 + export DEBUG + DEBUGGING_ARG='--enable-debug' + shift +fi + TRIPLET=`./depends/config.guess` PREFIX="$(pwd)/depends/$TRIPLET" make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 -#BUILD CCLIB - -WD=$PWD -cd src/cc -echo $PWD -./makecustom -cd $WD - ./autogen.sh + CPPFLAGS="-I$PREFIX/include -arch x86_64 -DTESTMODE" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ -CXXFLAGS='-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup' \ -./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" +CXXFLAGS="-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup" \ +./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" "$DEBUGGING_ARG" -make "$@" V=1 NO_GTEST=1 STATIC=1 +make "$@" NO_GTEST=1 STATIC=1 diff --git a/zcutil/build-mac.sh b/zcutil/build-mac.sh index ea03242cc71..77a5e764ecf 100755 --- a/zcutil/build-mac.sh +++ b/zcutil/build-mac.sh @@ -18,11 +18,13 @@ Usage: $0 --help Show this help message and exit. -$0 [ --enable-lcov ] [ MAKEARGS... ] - Build Zcash and most of its transitive dependencies from - source. MAKEARGS are applied to both dependencies and Zcash itself. If - --enable-lcov is passed, Zcash is configured to add coverage +$0 [ --enable-lcov ] [ --enable-debug ] [ MAKEARGS... ] + Build Komodo and most of its transitive dependencies from + source. MAKEARGS are applied to both dependencies and Komodo itself. + If --enable-lcov is passed, Komodo is configured to add coverage instrumentation, thus enabling "make cov" to work. + If --enable-debug is passed, Komodo is built with debugging information. It + must be passed after the previous arguments, if present. EOF exit 0 fi @@ -37,22 +39,25 @@ then shift fi +# If --enable-debug is the next argument, enable debugging +DEBUGGING_ARG='' +if [ "x${1:-}" = 'x--enable-debug' ] +then + DEBUG=1 + export DEBUG + DEBUGGING_ARG='--enable-debug' + shift +fi + TRIPLET=`./depends/config.guess` PREFIX="$(pwd)/depends/$TRIPLET" make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 -#BUILD CCLIB - -WD=$PWD -cd src/cc -echo $PWD -./makecustom -cd $WD - ./autogen.sh + CPPFLAGS="-I$PREFIX/include -arch x86_64" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ -CXXFLAGS='-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup' \ -./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" +CXXFLAGS="-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup" \ +./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" "$DEBUGGING_ARG" -make "$@" V=1 NO_GTEST=1 STATIC=1 +make "$@" NO_GTEST=1 STATIC=1 diff --git a/zcutil/build-win-dtest.sh b/zcutil/build-win-dtest.sh index 00a64de5bf7..94bed448bde 100755 --- a/zcutil/build-win-dtest.sh +++ b/zcutil/build-win-dtest.sh @@ -2,23 +2,24 @@ export HOST=x86_64-w64-mingw32 CXX=x86_64-w64-mingw32-g++-posix CC=x86_64-w64-mingw32-gcc-posix -PREFIX="$(pwd)/depends/$HOST" set -eu -o pipefail - set -x -cd "$(dirname "$(readlink -f "$0")")/.." -cd depends/ && make HOST=$HOST V=1 NO_QT=1 -cd ../ -WD=$PWD -cd src/cc -echo $PWD -./makecustom -cd $WD +UTIL_DIR="$(dirname "$(readlink -f "$0")")" +BASE_DIR="$(dirname "$(readlink -f "$UTIL_DIR")")" +PREFIX="$BASE_DIR/depends/$HOST" + +cd $BASE_DIR/depends +make HOST=$HOST NO_QT=1 "$@" +cd $BASE_DIR ./autogen.sh CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread" CPPFLAGS=-DTESTMODE ./configure --prefix="${PREFIX}" --host=x86_64-w64-mingw32 --enable-static --disable-shared sed -i 's/-lboost_system-mt /-lboost_system-mt-s /' configure -cd src/ -CC="${CC} -g " CXX="${CXX} -g " make V=1 komodod.exe komodo-cli.exe komodo-tx.exe + +cd $BASE_DIR/src/cryptoconditions +CC="${CC} -g " CXX="${CXX} -g " make V=1 +cd $BASE_DIR + +CC="${CC} -g " CXX="${CXX} -g " make V=1 src/komodod.exe src/komodo-cli.exe src/komodo-tx.exe diff --git a/zcutil/build-win.sh b/zcutil/build-win.sh index e8c0465d98b..ffd01134074 100755 --- a/zcutil/build-win.sh +++ b/zcutil/build-win.sh @@ -2,23 +2,19 @@ export HOST=x86_64-w64-mingw32 CXX=x86_64-w64-mingw32-g++-posix CC=x86_64-w64-mingw32-gcc-posix -PREFIX="$(pwd)/depends/$HOST" set -eu -o pipefail -set -x -cd "$(dirname "$(readlink -f "$0")")/.." +UTIL_DIR="$(dirname "$(readlink -f "$0")")" +BASE_DIR="$(dirname "$(readlink -f "$UTIL_DIR")")" +PREFIX="$BASE_DIR/depends/$HOST" -cd depends/ && make HOST=$HOST V=1 NO_QT=1 -cd ../ -WD=$PWD -cd src/cc -echo $PWD -./makecustom -cd $WD +cd $BASE_DIR/depends +make HOST=$HOST NO_QT=1 "$@" +cd $BASE_DIR ./autogen.sh -CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread" ./configure --prefix="${PREFIX}" --host=x86_64-w64-mingw32 --enable-static --disable-shared +CONFIG_SITE=$BASE_DIR/depends/$HOST/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread" ./configure --prefix=$PREFIX --host=$HOST --enable-static --disable-shared sed -i 's/-lboost_system-mt /-lboost_system-mt-s /' configure -cd src/ -CC="${CC} -g " CXX="${CXX} -g " make V=1 komodod.exe komodo-cli.exe komodo-tx.exe + +make "$@" diff --git a/zcutil/build.sh b/zcutil/build.sh index 6f625b185aa..7b6da0d701f 100755 --- a/zcutil/build.sh +++ b/zcutil/build.sh @@ -44,23 +44,23 @@ then Usage: $0 --help Show this help message and exit. -$0 [ --enable-lcov || --disable-tests ] [ --disable-mining ] [ --enable-proton ] [ --disable-libs ] [ MAKEARGS... ] - Build Zcash and most of its transitive dependencies from - source. MAKEARGS are applied to both dependencies and Zcash itself. - If --enable-lcov is passed, Zcash is configured to add coverage +$0 [ --enable-lcov || --disable-tests ] [ --disable-mining ] [ --enable-proton ] [ --disable-libs ] [ --enable-debug ] [ MAKEARGS... ] + Build Komodo and most of its transitive dependencies from + source. MAKEARGS are applied to both dependencies and Komodo itself. + If --enable-lcov is passed, Komodo is configured to add coverage instrumentation, thus enabling "make cov" to work. - If --disable-tests is passed instead, the Zcash tests are not built. - If --disable-mining is passed, Zcash is configured to not build any mining + If --disable-tests is passed instead, the Komodo tests are not built. + If --disable-mining is passed, Komodo is configured to not build any mining code. It must be passed after the test arguments, if present. - If --enable-proton is passed, Zcash is configured to build the Apache Qpid Proton + If --enable-proton is passed, Komodo is configured to build the Apache Qpid Proton library required for AMQP support. This library is not built by default. It must be passed after the test/mining arguments, if present. + If --enable-debug is passed, Komodo is built with debugging information. It + must be passed after the previous arguments, if present. EOF exit 0 fi -set -x - # If --enable-lcov is the first argument, enable lcov coverage support: LCOV_ARG='' HARDENING_ARG='--enable-hardening' @@ -92,24 +92,26 @@ then shift fi -eval "$MAKE" --version -as --version -ld -v - -HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ V=1 -./autogen.sh - -CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$CONFIGURE_FLAGS" CXXFLAGS='-g' - -#BUILD CCLIB +# If --enable-debug is the next argument, enable debugging +DEBUGGING_ARG='' +if [ "x${1:-}" = 'x--enable-debug' ] +then + DEBUG=1 + export DEBUG + DEBUGGING_ARG='--enable-debug' + shift +fi -WD=$PWD +if [[ -z "${VERBOSE-}" ]]; then + VERBOSITY="--enable-silent-rules" +else + VERBOSITY="--disable-silent-rules" +fi -cd src/cc -echo $PWD -./makecustom +HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ +./autogen.sh -cd $WD +CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$DEBUGGING_ARG" "$CONFIGURE_FLAGS" -"$MAKE" "$@" V=1 +"$MAKE" "$@"