diff --git a/.gitignore b/.gitignore index e5751db76..1f2b2537d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ *.tar.gz *.deb -*.exe src/bitcoin src/zcashd src/zcash-cli @@ -47,6 +46,7 @@ src/univalue/gen .deps .dirstamp +.idea .libs .*.swp *.*~* @@ -121,6 +121,9 @@ src/komodod src/komodo-tx src/komodo-test src/wallet-utility +src/komodo-cli.exe +src/komodod.exe +src/komodo-tx.exe #output during builds, symbol tables? *.dSYM diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 000000000..bef05408f --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,255 @@ +stages: + - build + - test + - deploy + +variables: + VERSION: 0.3.10 + AGAMA_ARTIFACTS_LINUX: linux64.tar.gz + AGAMA_ARTIFACTS_MACOS: osx.tar.gz + AGAMA_ARTIFACTS_WINDOWS: win64.zip + VERUS_CLI_DEBIAN: verus-cli-v${VERSION}-beta-amd64.deb + VERUS_CLI_LINUX_PORTABLE: verus-cli-linux-v$VERSION-beta.tar.gz + VERUS_CLI_WINDOWS_PORTABLE: verus-cli-windows-v$VERSION-beta.zip + VERUS_CLI_MACOS_PORTABLE: verus-cli-mac-v$VERSION-beta.tar.gz + + +build:linux: + image: asherd/veruscoin-cross-compiler:linux + variables: + DOCKER_DRIVER: overlay2 + stage: build + cache: + key: ${CI_JOB_NAME} + paths: + - depends/built + - .ccache + before_script: # Setup Cache + - rm -rf /root/.ccache || true + - mv .ccache /root/ || true + script: + - zcutil/build.sh -j4 + - ./makeReleaseLinux.sh + - dos2unix kmd/linux/verus-cli/README.txt + - tar -C kmd/linux/ -czvf $VERUS_CLI_LINUX_PORTABLE verus-cli ./ + - mv kmd/linux/verus-cli kmd/linux/linux64 + - tar -C kmd/linux/ -czvf $AGAMA_ARTIFACTS_LINUX linux64 ./ + after_script: + - mv /root/.ccache ./ || true + cache: + key: ${CI_JOB_NAME} + paths: + - depends/built + - .ccache + artifacts: + paths: + - $VERUS_CLI_LINUX_PORTABLE + - $AGAMA_ARTIFACTS_LINUX + expire_in: 1 week + + +build:windows: + image: asherd/veruscoin-cross-compiler:latest + variables: + DOCKER_DRIVER: overlay2 + stage: build + cache: + key: ${CI_JOB_NAME} + paths: + - depends/built + - .ccache + - .cargo + before_script: + - mkdir .ccache || echo ccache exists + - ln -s $PWD/.ccache /root/.ccache + - mkdir .zcash-params || echo zcash-params exists + - mkdir .cargo || echo .cargo exists + - ln -s $PWD/.cargo /root/.cargo + script: + - zcutil/build-win.sh + - ./makeReleaseWindows.sh + - cd kmd/windows/ + - zip -r $VERUS_CLI_WINDOWS_PORTABLE verus-cli + - mv $VERUS_CLI_WINDOWS_PORTABLE ../.. + - mv verus-cli win64 + - zip -r $AGAMA_ARTIFACTS_WINDOWS win64 + - mv $AGAMA_ARTIFACTS_WINDOWS ../.. + artifacts: + paths: + - $VERUS_CLI_WINDOWS_PORTABLE + - $AGAMA_ARTIFACTS_WINDOWS + expire_in: 1 week + + +build:mac: + stage: build + tags: ["High Sierra"] + cache: + key: ${CI_JOB_NAME} + paths: + - depends/built + script: + - zcutil/build-mac.sh | xcpretty + - ./makeReleaseMac.sh + - dos2unix kmd/mac/verus-cli/README.txt + - tar -C kmd/mac/ -czvf $VERUS_CLI_MACOS_PORTABLE verus-cli ./ + - mv kmd/mac/verus-cli kmd/mac/osx + - tar -C kmd/mac/ -czvf $AGAMA_ARTIFACTS_MACOS osx ./ + artifacts: + paths: + - $VERUS_CLI_MACOS_PORTABLE + - $AGAMA_ARTIFACTS_MACOS + expire_in: 1 week + + +code_quality: + image: docker:stable + variables: + DOCKER_DRIVER: overlay2 + allow_failure: true + services: + - docker:stable-dind + script: + - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/') + - docker run + --env SOURCE_CODE="$PWD" + --volume "$PWD":/code + --volume /var/run/docker.sock:/var/run/docker.sock + "registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code + artifacts: + paths: [gl-code-quality-report.json] + + +sast: + image: docker:stable + variables: + DOCKER_DRIVER: overlay2 + allow_failure: true + services: + - docker:stable-dind + script: + - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/') + - docker run + --env SAST_CONFIDENCE_LEVEL="${SAST_CONFIDENCE_LEVEL:-3}" + --volume "$PWD:/code" + --volume /var/run/docker.sock:/var/run/docker.sock + "registry.gitlab.com/gitlab-org/security-products/sast:$SP_VERSION" /app/bin/run /code + artifacts: + paths: [gl-sast-report.json] + + + +license_management: + image: docker:stable + variables: + DOCKER_DRIVER: overlay2 + allow_failure: true + services: + - docker:stable-dind + script: + - export LICENSE_MANAGEMENT_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/') + - docker run + --volume "$PWD:/code" + "registry.gitlab.com/gitlab-org/security-products/license-management:$LICENSE_MANAGEMENT_VERSION" analyze /code + artifacts: + paths: [gl-license-management-report.json] + +ubuntu:xenial: + image: ubuntu:xenial + variables: + DOCKER_DRIVER: overlay2 + stage: test + before_script: + - apt update && apt install -y wget g++-multilib libcurl3 python + script: + - tar -xzvf $VERUS_CLI_LINUX_PORTABLE + - export PATH=$PATH:$CI_PROJECT_DIR/verus-cli + - python qa/verus-cli-tests/verus-cli-tester.py + artifacts: + paths: [log.txt] + expire_in: 1 week + dependencies: + - build:linux + + +ubuntu:bionic: + image: ubuntu:bionic + variables: + DOCKER_DRIVER: overlay2 + stage: test + before_script: + - apt update && apt install -y wget g++-multilib libcurl3 python + script: + - tar -xzvf $VERUS_CLI_LINUX_PORTABLE + - export PATH=$PATH:$CI_PROJECT_DIR/verus-cli + - python qa/verus-cli-tests/verus-cli-tester.py + artifacts: + paths: [log.txt] + expire_in: 1 week + dependencies: + - build:linux + + +.osx:sierra: # fetch-params.sh needs to be fixed for MacOS + stage: test + tags: ["Sierra"] + script: + - tar -xzvf $VERUS_CLI_MACOS_PORTABLE + - export PATH=$PATH:$CI_PROJECT_DIR/verus-cli + - python qa/verus-cli-tests/verus-cli-tester.py + artifacts: + paths: [log.txt] + expire_in: 1 week + dependencies: + - build:mac + + +.osx:high-sierra: # fetch-params.sh needs to be fixed for MacOS + stage: test + tags: ["High Sierra"] + script: + - tar -xzvf $VERUS_CLI_MACOS_PORTABLE + - export PATH=$PATH:$CI_PROJECT_DIR/verus-cli + - python qa/verus-cli-tests/verus-cli-tester.py + artifacts: + paths: [log.txt] + expire_in: 1 week + dependencies: + - build:mac + + +windows:10: + stage: test + tags: ["Windows 10"] + script: + - PowerShell Expand-Archive -Path %VERUS_CLI_WINDOWS_PORTABLE% -DestinationPath %CI_PROJECT_DIR% + - set PATH=%PATH%;%CI_PROJECT_DIR%\verus-cli + - qa\verus-cli-tests\verus-cli-tester.py + artifacts: + paths: [log.txt] + expire_in: 1 week + dependencies: + - build:windows + + +deploy: + stage: deploy + image: google/cloud-sdk:alpine + variables: + DOCKER_DRIVER: overlay2 + dependencies: + - build:linux + - build:windows + - build:mac + script: + - mkdir -p $CI_COMMIT_REF_NAME/Windows + - mkdir -p $CI_COMMIT_REF_NAME/Linux + - mkdir -p $CI_COMMIT_REF_NAME/MacOS + - mv $VERUS_CLI_WINDOWS_PORTABLE $AGAMA_ARTIFACTS_WINDOWS $CI_COMMIT_REF_NAME/Windows + - mv $VERUS_CLI_LINUX_PORTABLE $AGAMA_ARTIFACTS_LINUX $CI_COMMIT_REF_NAME/Linux + - mv $VERUS_CLI_MACOS_PORTABLE $AGAMA_ARTIFACTS_MACOS $CI_COMMIT_REF_NAME/MacOS + - echo "$AUTH_KEY" > AUTH_KEY.json + - gcloud auth activate-service-account --key-file AUTH_KEY.json + - gsutil rsync -r $CI_COMMIT_REF_NAME/ $STAGING/VerusCoin/$CI_COMMIT_REF_NAME/ + + diff --git a/.travis.yml b/.travis.yml index ac331dcf9..107a3827f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,105 +1,67 @@ -<<<<<<< HEAD -language: cpp - -compiler: - - gcc - -before_install: - - sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa - - sudo apt-get update -qq - - sudo apt-get install build-essential pkg-config libcurl3-gnutls-dev libc6-dev libevent-dev m4 g++-multilib autoconf libtool ncurses-dev unzip git python zlib1g-dev wget bsdmainutils automake libssl-dev libprotobuf-dev protobuf-compiler libdb++-dev ntp ntpdate -#install: - -script: - - ./zcutil/build.sh -j 5 - -notifications: - irc: - channels: - - "chat.freenode.net#komodoplatform" - template: - - "%{repository}/%{branch} (%{commit} - %{author}): %{message}" - - "Alt Message : %{repository_slug} - (%{commit} - %{author}): %{message}, Build Time: %{duration}" - - "Change view : %{compare_url}" - - "Build details : %{build_url}" -======= -# errata: -# - A travis bug causes caches to trample eachother when using the same -# compiler key (which we don't use anyway). This is worked around for now by -# replacing the "compilers" with a build name prefixed by the no-op ":" -# command. See: https://github.com/travis-ci/travis-ci/issues/4393 -# - sudo/dist/group are set so as to get Blue Box VMs, necessary for [loopback] -# IPv6 support - sudo: required -dist: precise -group: legacy - os: linux +dist: xenial language: cpp -compiler: gcc +compiler: +- gcc env: global: - - MAKEJOBS=-j3 - - RUN_TESTS=false - - BOOST_TEST_RANDOM=1$TRAVIS_BUILD_ID - - CCACHE_SIZE=100M - - CCACHE_TEMPDIR=/tmp/.ccache-temp - - CCACHE_COMPRESS=1 - - BASE_OUTDIR=$TRAVIS_BUILD_DIR/out - - SDK_URL=https://bitcoincore.org/depends-sources/sdks - - PYTHON_DEBUG=1 - - WINEDEBUG=fixme-all + - CCACHE_SIZE=100M + - CCACHE_TEMPDIR=/tmp/.ccache-temp + - CCACHE_COMPRESS=1 + - STORAGE_DEST=gs://$BUCKET/$PROJECT/$TRAVIS_BRANCH/ cache: apt: true directories: - depends/built - depends/sdk-sources - - $HOME/.ccache + - "$HOME/google-cloud-sdk/" + - "$HOME/.ccache" matrix: fast_finish: true include: - - compiler: ": ARM" - env: HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf" DEP_OPTS="" GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" - - compiler: ": Win32" - env: HOST=i686-w64-mingw32 PACKAGES="nsis gcc-mingw-w64-i686 g++-mingw-w64-i686 binutils-mingw-w64-i686 mingw-w64-dev wine bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-reduce-exports" MAKEJOBS="-j2" - - compiler: ": 32-bit + dash" - env: HOST=i686-pc-linux-gnu PACKAGES="g++-multilib bc python-zmq" PPA="ppa:chris-lea/zeromq" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" USE_SHELL="/bin/dash" - - compiler: ": Win64" - env: HOST=x86_64-w64-mingw32 PACKAGES="nsis gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 binutils-mingw-w64-x86-64 mingw-w64-dev wine bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-reduce-exports" MAKEJOBS="-j2" - - compiler: ": bitcoind" - env: HOST=x86_64-unknown-linux-gnu PACKAGES="bc python-zmq" PPA="ppa:chris-lea/zeromq" DEP_OPTS="DEBUG=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports CPPFLAGS=-DDEBUG_LOCKORDER" - - compiler: ": No wallet" - env: HOST=x86_64-unknown-linux-gnu DEP_OPTS="NO_WALLET=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" - - compiler: ": Cross-Mac" - env: HOST=x86_64-apple-darwin11 PACKAGES="cmake libcap-dev libz-dev libbz2-dev" BITCOIN_CONFIG="--enable-reduce-exports" OSX_SDK=10.9 GOAL="deploy" + - compiler: ": Linux" + env: BUILD_SCRIPT=build.sh + PACKAGES="build-essential pkg-config libc6-dev m4 g++-multilib + autoconf libtool ncurses-dev unzip python zlib1g-dev wget bsdmainutils automake + libssl-dev libprotobuf-dev protobuf-compiler libqrencode-dev libdb++-dev software-properties-common + libcurl4-openssl-dev curl" + PACKAGE_NAME=verus-cli-linux.tar.gz + PACKAGING_MATRIX="cp src/komodod src/komodo-cli kmd/linux/verus-cli && chmod +x kmd/linux/verus-cli/komodod && chmod +x kmd/linux/verus-cli/komodo-cli && cd kmd/linux && tar -czf $PACKAGE_NAME verus-cli && ls" + - compiler: ": Windows" + env: RUST_TARGET=x86_64-pc-windows-gnu + BUILD_SCRIPT=build-win.sh + PACKAGES="build-essential pkg-config libcurl3-gnutls-dev + libc6-dev libevent-dev m4 g++-multilib autoconf libtool ncurses-dev unzip git + python zlib1g-dev wget bsdmainutils automake libssl-dev libprotobuf-dev protobuf-compiler + libdb++-dev ntp ntpdate mingw-w64 wine bc" + PACKAGE_NAME=verus-cli-windows.zip + PACKAGING_MATRIX="cp src/komodod.exe src/komodo-cli.exe src/komodo-tx.exe kmd/windows/verus-cli && + cd kmd/windows && zip -r9 $PACKAGE_NAME verus-cli && ls" exclude: - - compiler: gcc + - compiler: gcc install: - - if [ -n "$PACKAGES" ]; then sudo rm -f /etc/apt/sources.list.d/travis_ci_zeromq3-source.list; fi - - if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get update; fi - - if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get install --no-install-recommends --no-upgrade -qq $PACKAGES; fi +- sudo rm -f /etc/apt/sources.list.d/travis_ci_zeromq3-source.list +- travis_retry sudo apt-get -y update && travis_retry sudo apt-get -y install -qq $PACKAGES +- if [ -n "$RUST_TARGET" ]; then curl -sSf https://build.travis-ci.org/files/rustup-init.sh + | sh -s -- --default-toolchain stable -y && export PATH=$PATH:$HOME/.cargo/bin:$PATH && rustup target add $RUST_TARGET; fi before_script: - - unset CC; unset CXX - - mkdir -p depends/SDKs depends/sdk-sources - - if [ -n "$OSX_SDK" -a ! -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then curl --location --fail $SDK_URL/MacOSX${OSX_SDK}.sdk.tar.gz -o depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi - - if [ -n "$OSX_SDK" -a -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then tar -C depends/SDKs -xf depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi - - make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS +- unset CC; unset CXX script: - - if [ -n "$USE_SHELL" ]; then export CONFIG_SHELL="$USE_SHELL"; fi - - OUTDIR=$BASE_OUTDIR/$TRAVIS_PULL_REQUEST/$TRAVIS_JOB_NUMBER-$HOST - - BITCOIN_CONFIG_ALL="--disable-dependency-tracking --prefix=$TRAVIS_BUILD_DIR/depends/$HOST --bindir=$OUTDIR/bin --libdir=$OUTDIR/lib" - - depends/$HOST/native/bin/ccache --max-size=$CCACHE_SIZE - - if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then export CCACHE_READONLY=1; fi - - test -n "$USE_SHELL" && eval '"$USE_SHELL" -c "./autogen.sh"' || ./autogen.sh - - ./configure --cache-file=config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false) - - make distdir PACKAGE=bitcoin VERSION=$HOST - - cd bitcoin-$HOST - - ./configure --cache-file=../config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false) - - make $MAKEJOBS $GOAL || ( echo "Build failure. Verbose build follows." && make $GOAL V=1 ; false ) - - export LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/depends/$HOST/lib - - if [ "$RUN_TESTS" = "true" ]; then make check; fi - - if [ "$RUN_TESTS" = "true" ]; then qa/pull-tester/rpc-tests.sh; fi +- "./zcutil/fetch-params.sh" +- "./zcutil/$BUILD_SCRIPT -j2" after_script: - - if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then (echo "Upload goes here. Something like: scp -r $BASE_OUTDIR server" || echo "upload failed"); fi ->>>>>>> zcash/master +- if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then eval "${PACKAGING_MATRIX}" && + gsutil cp $PACKAGE_NAME $STORAGE_DEST; fi +notifications: + slack: + secure: FiVlFhSw5xnDu1Cx2yAo3J7miFCSRyuzR/2+8LKFjdWl5+fyIGvQ9x5vgUg6dWbv3UP9iIMqQuWfotsg8H+NE8pYRZQ0zDVxZ5h9+PA028qGb3OF4TMFNcltP5DGtAZ6AqrMNRZ4ltatPUm5H9ig1bhzjsx+3pqlqQuVXTXPjaUryB5s/fk2CjrsV6zTLfPHiI30jeMjmQrJJLik1vSWF70sB6HkQhvaT6jymkO4Vuh+cja418W1xIgkkoRsOXiZ/JK4hIypFo/sBkmIOprGqoFUahFqJlsBoSrp9iAzkwbDItIqqvNCHTEeN7lj6kK43ZK72E4etjjNc0CXWeleXBJBCj5Prq2lEkQ4NwuDTos3KLyyr2vI7f54xhb5+wjzY9dByHXGuG5UaNz0+uukuJinAdazGaNmmfesv1wg9p3jGa/TLsfHLMcUti875DzkUHnenivP5cXrc6/uuZyyQNq5+Gn/3DA8k0y7d1e23nm3nDjCNfATAn3yu1jieYY2yYI6CYGEXcD+UbP61uG6no+mm/lkQbQosyDfE0sADqGryqXswRste+R0sSVMBQtTipAZOUoYNbEmhN4+L78SSp3zpmgkrIxAw7le8oj6Evp2ofvE2Kvh+Z0MVoEJx6mtZI6hheIFSS38NeUZr/HBfRSpaElOYTN/ZNf8QwThCWo= +before_install: +- if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then openssl aes-256-cbc -K $encrypted_11153c0bb86c_key -iv $encrypted_11153c0bb86c_iv + -in AUTH_KEY.json.enc -out AUTH_KEY.json -d; fi +- if [ ! -d "$HOME/google-cloud-sdk/bin" ]; then rm -rf $HOME/google-cloud-sdk; export + CLOUDSDK_CORE_DISABLE_PROMPTS=1; curl https://sdk.cloud.google.com | bash; fi +- source /home/travis/google-cloud-sdk/path.bash.inc +- if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then gcloud auth activate-service-account --key-file AUTH_KEY.json; fi +- if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then rm AUTH_KEY.json; fi +- rm AUTH_KEY.json.enc diff --git a/AUTH_KEY.json.enc b/AUTH_KEY.json.enc new file mode 100644 index 000000000..ac619b9cb Binary files /dev/null and b/AUTH_KEY.json.enc differ diff --git a/Brewfile b/Brewfile new file mode 100644 index 000000000..8ed641c56 --- /dev/null +++ b/Brewfile @@ -0,0 +1,17 @@ +tap "discoteq/discoteq" +tap "homebrew/bundle" +tap "homebrew/cask" +tap "homebrew/cask-versions" +tap "homebrew/core" +brew "autoconf" +brew "autogen" +brew "automake" +brew "binutils" +brew "cmake" +brew "coreutils" +brew "gcc@5" +brew "leveldb" +brew "nanomsg" +brew "protobuf" +brew "wget" +brew "discoteq/discoteq/flock" diff --git a/COPYING b/COPYING index c84bfb7aa..02d3c93a2 100644 --- a/COPYING +++ b/COPYING @@ -1,5 +1,6 @@ Copyright (c) 2016-2017 The Zcash developers Copyright (c) 2009-2017 The Bitcoin Core developers +Copyright (c) 2018 The VerusCoin developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -31,7 +32,7 @@ OpenSSL Toolkit (https://www.openssl.org/). This product includes cryptographic software written by Eric Young (eay@cryptsoft.com). -Although almost all of the Zcash code is licensed under "permissive" open source +Although almost all of the Zcash/Komodo/VerusCoin code is licensed under "permissive" open source licenses, users and distributors should note that when built using the default build options, Zcash depends on Oracle Berkeley DB 6.2.x, which is licensed under the GNU Affero General Public License. diff --git a/Makefile.am b/Makefile.am index d3171b206..ccd884dd3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -13,14 +13,14 @@ pkgconfig_DATA = libzcashconsensus.pc endif -BITCOIND_BIN=$(top_builddir)/src/zcashd$(EXEEXT) -BITCOIN_CLI_BIN=$(top_builddir)/src/zcash-cli$(EXEEXT) +BITCOIND_BIN=$(top_builddir)/src/komodod$(EXEEXT) +BITCOIN_CLI_BIN=$(top_builddir)/src/komodo-cli$(EXEEXT) #WALLET_UTILITY_BIN=$(top_builddir)/src/wallet-utility$(EXEEXT) BITCOIN_WIN_INSTALLER=$(PACKAGE)-$(PACKAGE_VERSION)-win$(WINDOWS_BITS)-setup$(EXEEXT) if TARGET_DARWIN -OSX_APP=Bitcoin-Qt.app -OSX_DMG=Bitcoin-Core.dmg +OSX_APP=Agama.app +OSX_DMG=Agama.dmg OSX_BACKGROUND_IMAGE=background.tiff OSX_DEPLOY_SCRIPT=$(top_srcdir)/contrib/macdeploy/macdeployqtplus OSX_FANCY_PLIST=$(top_srcdir)/contrib/macdeploy/fancy.plist diff --git a/README-mac.md b/README-mac.md index c085cb617..1e55bff5a 100644 --- a/README-mac.md +++ b/README-mac.md @@ -6,28 +6,21 @@ And Homebrew: http://brew.sh/ -And this is the list of brew packages you'll need installed: +then use the brewfile to install the necessary packages: ```shell -brew tap discoteq/discoteq; brew install flock -brew install autoconf autogen automake -brew tap homebrew/versions; brew install homebrew/versions/gcc5 -brew install binutils -brew install protobuf -brew install coreutils -brew install wget +brew bundle ``` Get all that installed, then run: ```shell -git clone https://github.com/j-cimb-barker/komodo.git -cd komodo -git checkout dev +git clone https://github.com/VerusCoin/VerusCoin.git +cd VerusCoin ./zcutil/build-mac.sh ``` -To build a distributable version of komodo then run the makeDistrib.sh script after building. +To build a distributable version of VerusCoin then run the makeReleaseMac.sh script after building. This will fix the dependency references and move the komodod and komodo-cli binaries to the kmd/mac/verus-cli directory along with the 6 libraries required for it to work properly. When you are done building, you need to do a few things in the [Configuration](https://github.com/zcash/zcash/wiki/1.0-User-Guide#configuration) section of the Zcash User Guide differently because we are on the Mac. All instances of `~/.zcash` need to be replaced by `~/Library/Application\ Support/Zcash` The fetch-params.sh script, however, has already been altered to fetch the proving keys into the correct directory to conform to Mac specific naming conventions. diff --git a/README.md b/README.md index 7cca6aa00..285d6459d 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,17 @@ +## VerusCoin version 0.3.10-beta +VerusCoin is a new, mineable and stakeable cryptocurrency. It is a live fork of Komodo that retains its Zcash lineage and improves it. VerusCoin will leverage the Komodo platform and dPoW notarization for enhanced security and cross-chain interoperability. We have added a variation of a zawy12, lwma difficulty algorithm, a new CPU-optimized hash algorithm and a new algorithm for fair proof of stake. We describe these changes and vision going forward in a [our Phase I white paper](http://185.25.51.16/papers/VerusPhaseI.pdf) and [our Vision](http://185.25.51.16/papers/VerusVision.pdf). +- [VerusCoin web site https://veruscoin.io/ Wallets and CLI tools](https://veruscoin.io/) +- [VerusCoin Explorer](https://explorer.veruscoin.io/) + ## Komodo with Bitcore This version of Komodo contains Bitcore support for komodo and all its assetchains. ## Komodod -This software is Komodo client, generally you will use this if you want to mine KMD or setup a full node. -It downloads and stores the entire history of Komodo 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. +This software is the VerusCoin enhanced Komodo client. Generally, you will use this if you want to mine VRSC or setup a full node. When you run the wallet it launches komodod automatically. On first launch it downloads Zcash parameters, roughly 1GB, which is mildly slow. +The wallet downloads and stores the block chain or asset chain of the coin you select. It downloads and stores the entire history of the coins 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. ## Development Resources +- VerusCoin:[https://veruscoin.io/](https://veruscoin.io/) Wallets and CLI tools - Komodo Web: [https://komodoplatform.com/](https://komodoplatform.com/) - Organization web: [https://komodoplatform.com/](https://komodoplatform.com/) - Forum: [https://forum.komodoplatform.com/](https://forum.komodoplatform.com/) @@ -49,7 +55,7 @@ sudo apt-get install build-essential pkg-config libc6-dev m4 g++-multilib autoco Building -------- -First time you'll need to get assorted startup values downloaded. This takes a moderate amount of time once but then does niot need to be repeated unless you bring a new system up. The command is: +First time you'll need to get assorted startup values downloaded. This takes a moderate amount of time once but then does not need to be repeated unless you bring a new system up. The command is: ``` ./zcutil/fetch-params.sh ``` @@ -65,27 +71,14 @@ Building for Windows: ``` ./zcutil/build-win.sh ``` - -Komodo +VerusCoin ------ -We have a release process that goes through several stages before it reaches master. This allows the most conservative users just use the master branch, which is only updated after the other branches have signed off on a release. +We develop on dev and some other branches and produce releases of of the master branch, using pull requests to manage what goes into master. -99% of the activity is in the dev branch, this is where I am testing each change one by one and there are literally thousands of updates. Only use this branch if you really want to be on the bleeding edge. I try to keep things stable, but there are times where necessarily there are bugs in the dev branch, since I am actively developing and debugging here. A good rule is to wait for at least 4 hours from the last update before using the dev branch (unless you know what you are doing) - -After things look good in the dev branch, it is propagated to the beta branch, this is the version the notary nodes use. They are knowledegable command line server guys and so they have a keen eye for anything that wasnt caught during the dev cycle. - -After the notary nodes verify things are working and the latest release is deemed stable, it is propagated to the dPoW branch. From here an automated Jenkins process builds it for all OS, and since the notary nodes are all unix, it is possible for some issues to be caught at this stage. The dPoW branch is what goes into the GUI installers. - -After the GUI are updated and released and it is verified that no significant support issues were created, the master branch is finally updated. - -Master branch: exchanges and users that build from the repo without changing branches -dPoW branch: autobuild into GUI installers, unix, osx, windows -beta branch: notary nodes, command line unix -dev branch: bleeding edge, possibly wont even compile, multiple updates per hour ```shell -git clone https://github.com/jl777/komodo -cd komodo +git clone https://github.com/VerusCoin/VerusCoin +cd VerusCoin #you might want to: git checkout ; git pull ./zcutil/fetch-params.sh # -j8 uses 8 threads - replace 8 with number of threads you want to use @@ -93,79 +86,16 @@ cd komodo #This can take some time. ``` -**komodo is experimental and a work-in-progress.** Use at your own risk. +**The VerusCoin enhanced komodo is experimental and a work-in-progress.** Use at your own risk. -Deprecation Policy ------------------- - -This release is considered deprecated one year after the release day. There -is an automatic deprecation shutdown feature which will halt the node some -time after this one year period. The automatic feature is based on block -height and can be explicitly disabled. - - -# to update an existing version, `git checkout dPoW` if not on that branch already -```shell -git pull -./zcutil/fetch-params.sh -./zcutil/build.sh -j8 -``` -To reset the blockchain, from *~/.komodo* `rm -rf blocks chainstate debug.log komodostate db.log` - -Create komodo.conf ------------------- - -``` -cd ~ -mkdir .komodo -cd .komodo -pico komodo.conf -#Add the following lines to the komodo.conf file: -rpcuser=bitcoinrpc -rpcpassword=password -txindex=1 -addnode=5.9.102.210 -addnode=78.47.196.146 -addnode=178.63.69.164 -addnode=88.198.65.74 -addnode=5.9.122.241 -addnode=144.76.94.38 -addnode=89.248.166.91 -``` - -Start mining ------------- - -```shell -#iguana documentation shows how to get the btcpubkey and wifstrs that need to be used -#bitcoin also need to be installed with txindex=1 and with rpc enabled -cd ~ -cd komodo -#This will return your pubkey eg. "0259e137e5594cf8287195d13aed816af75bd5c04ae673296b51f66e7e8346e8d8" for your address -./src/komodo-cli validateaddress -#This will give the privkey of your wallet address -./src/komodo-cli dumpprivkey -#This will import the privkey to be sure the mined coins are placed into your wallet address -./src/komodo-cli importprivkey -#To stop the daemon: -./src/komodo-cli stop -#This starts komodo notary - replace genproclimit with number of threads you want to use and add your pubkey -./src/komodod -gen -genproclimit=2 -notary -pubkey="0259e137e5594cf8287195d13aed816af75bd5c04ae673296b51f66e7e8346e8d8" & -#This will get the stats: -./src/komodo-cli getinfo -#To view the process: -ps -ef | grep komodod -#To stop the daemon: -./src/komodo-cli stop #To view komodod output: tail -f ~/.komodo/debug.log +#To view VRSC output: +tail -f ~/.komodo/VRSC/debug.log +Note that this directory is correct for Linux, not Mac or Windows #To view all command ./src/komodo-cli help -ASSETCHAINS: -ac_name=name -ac_supply=nnnnn -Both komodod and komodo-cli recognize -ac_name=option so you can create fork from the commandline -``` -======= **Zcash is unfinished and highly experimental.** Use at your own risk. Where do I begin? @@ -173,26 +103,8 @@ 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? -* See the documentation at the [Zcash Wiki](https://github.com/zcash/zcash/wiki) -for help and more information. -* Ask for help on the [Zcash](https://forum.z.cash/) forum. -Participation in the Zcash project is subject to a -[Code of Conduct](code_of_conduct.md). - -Building --------- -Build Zcash along with most dependencies from source by running -`./zcutil/build.sh`. Currently only Linux is officially supported. - -License -------- -For license information see the file [COPYING](COPYING). - -**NOTE TO EXCHANGES:** -https://bitcointalk.org/index.php?topic=1605144.msg17732151#msg17732151 -There is a small chance that an outbound transaction will give an error due to mismatched values in wallet calculations. There is a -exchange option that you can run komodod with, but make sure to have the entire transaction history under the same -exchange mode. Otherwise you will get wallet conflicts. - +#Older Komodo Details +The remaining text is from the komodo source we forked when creating VerusCoin/Veruscoin. **To change modes:** a) backup all privkeys (launch komodod with `-exportdir=` and `dumpwallet`) @@ -250,6 +162,3 @@ Instead of generating 1 secret address, generate 100 and make a script file with ./komodo-cli jumblr_secret ``` And make sure to delete all traces of this when the JUMBLR is finished. You will end up with 100 addresses that have an average of 1000 KMD each. So as long as you are careful and dont do a 10,000 KMD transaction (that will link 10 of your secret addresses together), you can appear as 100 different people each with 1000 KMD. - - - diff --git a/configure.ac b/configure.ac index 7de40ff26..eda8fa433 100644 --- a/configure.ac +++ b/configure.ac @@ -7,16 +7,16 @@ 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))) define(_CLIENT_VERSION_IS_RELEASE, true) -define(_COPYRIGHT_YEAR, 2017) -AC_INIT([Zcash],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_SUFFIX(_ZC_BUILD_VAL)],[https://github.com/zcash/zcash/issues],[zcash]) +define(_COPYRIGHT_YEAR, 2018) +AC_INIT([Verus-CLI],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_SUFFIX(_ZC_BUILD_VAL)],[https://github.com/VerusCoin/VerusCoin/issues],[verus-cli]) AC_CONFIG_SRCDIR([src/main.cpp]) AC_CONFIG_HEADERS([src/config/bitcoin-config.h]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([build-aux/m4]) -BITCOIN_DAEMON_NAME=zcashd -BITCOIN_CLI_NAME=zcash-cli -BITCOIN_TX_NAME=zcash-tx +BITCOIN_DAEMON_NAME=komodod +BITCOIN_CLI_NAME=komodo-cli +BITCOIN_TX_NAME=komodo-tx dnl Unless the user specified ARFLAGS, force it to be cr AC_ARG_VAR(ARFLAGS, [Flags for the archiver, defaults to if not set]) @@ -232,7 +232,7 @@ CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS" AC_ARG_WITH([utils], [AS_HELP_STRING([--with-utils], - [build zcash-cli zcash-tx wallet-utility (default=yes)])], + [build komodo-cli komodo-tx wallet-utility (default=yes)])], [build_bitcoin_utils=$withval], [build_bitcoin_utils=yes]) @@ -805,7 +805,7 @@ AC_MSG_CHECKING([whether to build bitcoind]) AM_CONDITIONAL([BUILD_BITCOIND], [test x$build_bitcoind = xyes]) AC_MSG_RESULT($build_bitcoind) -AC_MSG_CHECKING([whether to build utils (zcash-cli zcash-tx wallet-utility)]) +AC_MSG_CHECKING([whether to build utils (komodo-cli komodo-tx wallet-utility)]) AM_CONDITIONAL([BUILD_BITCOIN_UTILS], [test x$build_bitcoin_utils = xyes]) AC_MSG_RESULT($build_bitcoin_utils) diff --git a/contrib/debian/control b/contrib/debian/control index b0c220cf0..c2921790c 100644 --- a/contrib/debian/control +++ b/contrib/debian/control @@ -1,21 +1,22 @@ -Source: zcash +Source: VerusCoin Section: utils Priority: optional -Maintainer: Zcash Company -Homepage: https://z.cash +Maintainer: VerusCoin +Homepage: https://veruscoin.io Build-Depends: autoconf, automake, bsdmainutils, build-essential, git, g++-multilib, libc6-dev, libtool, m4, ncurses-dev, pkg-config, python, unzip, wget, zlib1g-dev -Vcs-Git: https://github.com/zcash/zcash.git -Vcs-Browser: https://github.com/zcash/zcash +Vcs-Git: https://github.com/VeruscCoin/VerusCoin.git +Vcs-Browser: https://github.com/VerusCoin/VerusCoin -Package: zcash +Package: Verus-CLI Architecture: amd64 Depends: ${shlibs:Depends} -Description: HTTPS for money. - 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. - This package provides the daemon, zcashd, and the CLI tool, - zcash-cli, to interact with the daemon. +Description: VerusCoin is a new, mineable and stakeable cryptocurrency. +It is a live fork of Komodo that retains its Zcash lineage and improves it. +VerusCoin will leverage the Komodo platform and dPoW notarization for enhanced security and cross-chain interoperability. +We have added a variation of a zawy12, lwma difficulty algorithm, a new CPU-optimized hash algorithm and a new algorithm for fair proof of stake. +We describe these changes and vision going forward in a [our Phase I white paper](http://185.25.51.16/papers/VerusPhaseI.pdf) and +[our Vision](http://185.25.51.16/papers/VerusVision.pdf). + diff --git a/contrib/debian/zcash.install b/contrib/debian/zcash.install index b39eaeeb3..917d319b8 100644 --- a/contrib/debian/zcash.install +++ b/contrib/debian/zcash.install @@ -1,3 +1,3 @@ -usr/bin/zcashd -usr/bin/zcash-cli +usr/bin/komodod +usr/bin/komodo-cli usr/bin/zcash-fetch-params diff --git a/contrib/devtools/fix-copyright-headers.py b/contrib/devtools/fix-copyright-headers.py index 5e8495254..fc57ae64e 100755 --- a/contrib/devtools/fix-copyright-headers.py +++ b/contrib/devtools/fix-copyright-headers.py @@ -1,4 +1,6 @@ #!/usr/bin/env python +from __future__ import print_function + ''' Run this script inside of src/ and it will look for all the files that were changed this year that still have the last year in the @@ -46,7 +48,7 @@ for extension in extensions: filePath = os.getcwd() + filePath modifiedTime = getLastGitModifiedDate(filePath) if len(modifiedTime) > 0 and str(year) in modifiedTime: - print n,"Last Git Modified: ", modifiedTime, " - ", filePath + print(n, "Last Git Modified: ", modifiedTime, " - ", filePath) os.popen(command % (last_year,year,filePath)) n = n + 1 diff --git a/kmd/linux/verus-cli/README.txt b/kmd/linux/verus-cli/README.txt new file mode 100644 index 000000000..9cdfd2768 --- /dev/null +++ b/kmd/linux/verus-cli/README.txt @@ -0,0 +1,12 @@ +VerusCoin Command Line Tools v0.3.10-beta +Contents: +komodod - VerusCoin's enhanced Komodo daemon +komodo-cli - VerusCoin's Komodo command line utility +verus - wrapper for komodo-cli that applies the command to the VRSC coin +verusd - wrapper for komodod that sets the VerusCoin parameters to defaults properly + +The first time on a new system you will need to run ./fetch-params before using komodod or verusd. + +Run ./verusd to launch komodod, and use verus to run commands such as: +./verus stop +Which signals komodod (if it is running) to stop running. diff --git a/kmd/linux/verus-cli/fetch-params b/kmd/linux/verus-cli/fetch-params new file mode 100644 index 000000000..10bade7cb --- /dev/null +++ b/kmd/linux/verus-cli/fetch-params @@ -0,0 +1,165 @@ +#!/bin/bash + +set -eu + +PARAMS_DIR="$HOME/.zcash-params" + +SPROUT_PKEY_NAME='sprout-proving.key' +SPROUT_VKEY_NAME='sprout-verifying.key' +SPROUT_URL="https://z.cash/downloads" +SPROUT_IPFS="/ipfs/QmZKKx7Xup7LiAtFRhYsE1M7waXcv9ir9eCECyXAFGxhEo" + +SHA256CMD="$(command -v sha256sum || echo shasum)" +SHA256ARGS="$(command -v sha256sum >/dev/null || echo '-a 256')" + +WGETCMD="$(command -v wget || echo '')" +IPFSCMD="$(command -v ipfs || echo '')" + +# fetch methods can be disabled with ZC_DISABLE_SOMETHING=1 +ZC_DISABLE_WGET="${ZC_DISABLE_WGET:-}" +ZC_DISABLE_IPFS="${ZC_DISABLE_IPFS:-}" + +function fetch_wget { + if [ -z "$WGETCMD" ] || ! [ -z "$ZC_DISABLE_WGET" ]; then + return 1 + fi + + local filename="$1" + local dlname="$2" + + cat <&2 <&2 + exit 1 + fi + fi +} + +# Use flock to prevent parallel execution. +function lock() { + local lockfile=/tmp/fetch_params.lock + # create lock file + eval "exec 200>/$lockfile" + # acquire the lock + flock -n 200 \ + && return 0 \ + || return 1 +} + +function exit_locked_error { + echo "Only one instance of fetch-params.sh can be run at a time." >&2 + exit 1 +} + +function main() { + + lock fetch-params.sh \ + || exit_locked_error + + cat <> "$README_PATH" < and type cmd +From the command prompt change to the directory where you installed verus-cli. If you downloaded the file to your Downloads directory and extracted it there then the change directory command is +cd \Users\MyName\Downloads\verus-cli +From this directory you can run the Verus command line utilities. +The first time on a new system you will need to run fetch-params before using komodod.exe or verusd. +Many anti-virus products interfere with the VerusCoin tool's ability to open ports and will need to be configured to allow what the scanner says is unsafe behavior. +Extreme cases can result in the virus scanner deleting Agama.exe or moving it to "protect" the system. You will to add the executables to a whitelist and re-extract the verus-cli-windows.zip file if that happens. +Run verusd.bat to launch komodod, and use verus.bat to run commands such as: +verus.bat stop +Which signals komodod.exe (if it is running) to stop running. + +Note that if you pass in command line options to verus.bat or verusd.bat that include an = like -ac_veruspos=50 you must surround it with double quotes like this: +verusd.bat "-ac_veruspos=50" +Otherwise Windows will drop the = and pass the two values in as separate command line options. diff --git a/kmd/windows/verus-cli/fetch-params.bat b/kmd/windows/verus-cli/fetch-params.bat new file mode 100644 index 000000000..b7b95ff82 --- /dev/null +++ b/kmd/windows/verus-cli/fetch-params.bat @@ -0,0 +1,21 @@ +@echo off +call :GET_CURRENT_DIR +cd %THIS_DIR% +IF NOT EXIST %APPDATA%\ZcashParams ( +MKDIR %APPDATA%\ZcashParams +) +IF NOT EXIST %APPDATA%\ZcashParams\sprout-proving.key ( + ECHO Downloading Zcash trusted setup sprout-proving.key, this may take a while ... + .\wget64.exe --progress=dot:giga --continue --retry-connrefused --waitretry=3 --timeout=30 https://z.cash/downloads/sprout-proving.key -O %APPDATA%\ZcashParams\sprout-proving.key +) +IF NOT EXIST %APPDATA%\ZcashParams\sprout-verifying.key ( + ECHO Downloading Zcash trusted setup sprout-verifying.key, this may take a while ... + .\wget64.exe --progress=dot:giga --continue --retry-connrefused --waitretry=3 --timeout=30 https://z.cash/downloads/sprout-verifying.key -O %APPDATA%\ZcashParams\sprout-verifying.key +) +goto :EOF +:GET_CURRENT_DIR +pushd %~dp0 +set THIS_DIR=%CD% +popd +goto :EOF + diff --git a/kmd/windows/verus-cli/verus.bat b/kmd/windows/verus-cli/verus.bat new file mode 100644 index 000000000..0bf87d33b --- /dev/null +++ b/kmd/windows/verus-cli/verus.bat @@ -0,0 +1,14 @@ +@call :GET_CURRENT_DIR +@cd %THIS_DIR% +komodo-cli.exe -ac_name=VRSC %1 %2 %3 %4 %5 %6 %7 %8 %9 +@goto :EOF + +:GET_CURRENT_DIR +@pushd %~dp0 +@set THIS_DIR=%CD% +@popd +@goto :EOF + + + + diff --git a/kmd/windows/verus-cli/verusd.bat b/kmd/windows/verus-cli/verusd.bat new file mode 100644 index 000000000..14de35876 --- /dev/null +++ b/kmd/windows/verus-cli/verusd.bat @@ -0,0 +1,10 @@ +@call :GET_CURRENT_DIR +@cd %THIS_DIR% +komodod.exe -ac_name=VRSC -ac_algo=verushash -ac_cc=1 -ac_supply=0 -ac_eras=3 -ac_reward=0,38400000000,2400000000 -ac_halving=1,43200,1051920 -ac_decay=100000000,0,0 -ac_end=10080,226080,0 -addnode=185.25.48.236 -addnode=185.64.105.111 -ac_timelockgte=19200000000 -ac_timeunlockfrom=129600 -ac_timeunlockto=1180800 -ac_veruspos=50 -gen -genproclimit=0 %1 %2 %3 %4 %5 %6 %7 %8 %9 +@goto :EOF + +:GET_CURRENT_DIR +@pushd %~dp0 +@set THIS_DIR=%CD% +@popd +@goto :EOF diff --git a/kmd/windows/verus-cli/wget64.exe b/kmd/windows/verus-cli/wget64.exe new file mode 100644 index 000000000..f6fb628e4 Binary files /dev/null and b/kmd/windows/verus-cli/wget64.exe differ diff --git a/makeDistrib.sh b/makeDistrib.sh deleted file mode 100755 index ad72fbb16..000000000 --- a/makeDistrib.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh - -TMP_DIR=~/tmp/komodo - -# make a tmp directory -mkdir -p $TMP_DIR -echo "making $TMP_DIR" - -binaries=("komodo-cli" "komodod") - -for binary in "${binaries[@]}"; -do - echo "copying $binary to $TMP_DIR" - - cp src/$binary $TMP_DIR - - # find the dylibs to copy for komodod - DYLIBS=`otool -L $TMP_DIR/$binary | grep "/usr/local" | awk -F' ' '{ print $1 }'` - echo "copying $DYLIBS to $TMP_DIR" - - # copy the dylibs to the tmpdir - for dylib in $DYLIBS; do cp -rf $dylib $TMP_DIR/; done - - # modify komodod to point to dylibs - echo "modifying $binary to use local libraries" - for dylib in $DYLIBS; do install_name_tool -change $dylib @executable_path/`basename $dylib` $TMP_DIR/$binary; done; -done - - - - - - - - diff --git a/makeRelease.sh b/makeRelease.sh deleted file mode 100755 index 5d68f0b03..000000000 --- a/makeRelease.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh - -binaries=("komodo-cli" "komodod") - -for binary in "${binaries[@]}"; -do - # find the dylibs to copy for komodod - DYLIBS=`otool -L src/$binary | grep "/usr/local" | awk -F' ' '{ print $1 }'` - echo "copying $DYLIBS to $src" - # copy the dylibs to the srcdir - for dylib in $DYLIBS; do cp -rf $dylib src/; done - - # modify komodod to point to dylibs - echo "modifying $binary to use local libraries" - for dylib in $DYLIBS; do install_name_tool -change $dylib @executable_path/`basename $dylib` src/$binary; done; - chmod +x src/$binary -done diff --git a/makeReleaseLinux.sh b/makeReleaseLinux.sh new file mode 100755 index 000000000..9e48f16eb --- /dev/null +++ b/makeReleaseLinux.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +cp src/komodod src/komodo-cli kmd/linux/verus-cli +chmod +x kmd/linux/verus-cli/komodo +chmod +x kmd/linux/verus-cli/komodod +chmod +x kmd/linux/verus-cli/verus +chmod +x kmd/linux/verus-cli/verusd +chmod +x kmd/linux/verus-cli/fetch-params diff --git a/makeReleaseMac.sh b/makeReleaseMac.sh new file mode 100755 index 000000000..29cf91dd4 --- /dev/null +++ b/makeReleaseMac.sh @@ -0,0 +1,72 @@ +#!/bin/sh + +KMD_DIR=kmd/mac/verus-cli + +binaries=("komodo-cli" "komodod") +alllibs=() +for binary in "${binaries[@]}"; +do + # do the work in the destination directory + cp src/$binary $KMD_DIR + # find the dylibs to copy for komodod + DYLIBS=`otool -L $KMD_DIR/$binary | grep "/usr/local" | awk -F' ' '{ print $1 }'` + echo "copying $DYLIBS to $KMD_DIR" + # copy the dylibs to the srcdir + for dylib in $DYLIBS; do cp -rf $dylib $KMD_DIR; done +done + +libraries=("libgcc_s.1.dylib" "libgomp.1.dylib" "libidn2.0.dylib" "libstdc++.6.dylib") + +for binary in "${libraries[@]}"; +do + # Need to undo this for the dylibs when we are done + chmod 755 $KMD_DIR/$binary + # find the dylibs to copy for komodod + DYLIBS=`otool -L $KMD_DIR/$binary | grep "/usr/local" | awk -F' ' '{ print $1 }'` + echo "copying $DYLIBS to $KMD_DIR" + # copy the dylibs to the srcdir + for dylib in $DYLIBS; do cp -rf $dylib $KMD_DIR; alllibs+=($dylib); done +done + +indirectlibraries=("libintl.8.dylib" "libunistring.2.dylib") + +for binary in "${indirectlibraries[@]}"; +do + # Need to undo this for the dylibs when we are done + chmod 755 src/$binary + # find the dylibs to copy for komodod + DYLIBS=`otool -L $KMD_DIR/$binary | grep "/usr/local" | awk -F' ' '{ print $1 }'` + echo "copying indirect $DYLIBS to $KMD_DIR" + # copy the dylibs to the dest dir + for dylib in $DYLIBS; do cp -rf $dylib $KMD_DIR; alllibs+=($dylib); done +done + +for binary in "${binaries[@]}"; +do + # modify komodod to point to dylibs + echo "modifying $binary to use local libraries" + for dylib in "${alllibs[@]}" + do + echo "Next lib is $dylib " + install_name_tool -change $dylib @executable_path/`basename $dylib` $KMD_DIR/$binary + done + chmod +x $KMD_DIR/$binary +done + +for binary in "${libraries[@]}"; +do + # modify libraries to point to dylibs + echo "modifying $binary to use local libraries" + for dylib in "${alllibs[@]}" + do + echo "Next lib is $dylib " + install_name_tool -change $dylib @executable_path/`basename $dylib` $KMD_DIR/$binary + done + chmod +x $KMD_DIR/$binary +done + +chmod +x kmd/mac/verus-cli/fetch-params +chmod +x kmd/linux/verus-cli/verus +chmod +x kmd/linux/verus-cli/verusd + + diff --git a/makeReleaseWindows.sh b/makeReleaseWindows.sh new file mode 100755 index 000000000..7c9075094 --- /dev/null +++ b/makeReleaseWindows.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +cp src/komodod.exe src/komodo-cli.exe src/komodo-tx.exe kmd/windows/verus-cli diff --git a/qa/verus-cli-tests/verus-cli-tester.py b/qa/verus-cli-tests/verus-cli-tester.py new file mode 100644 index 000000000..147686110 --- /dev/null +++ b/qa/verus-cli-tests/verus-cli-tester.py @@ -0,0 +1,39 @@ +from subprocess import Popen, check_output, call +from time import sleep +from os import environ, path + +daemon_wrapper = "verusd" +cli_wrapper = "verus" +daemon_runtime_seconds = 600 +cli_commands = ["getblockchaininfo", "getmininginfo", "getwalletinfo", "stop"] + + +def start_daemon(daemon_wrapper): + try: + Popen(daemon_wrapper, shell=True, close_fds=True) + except: + exit(1) + + +def fetch_zcash_params(): + try: + call("fetch-params", shell=True) + except: + exit(1) + + +def run_cli_commands(cli_wrapper, commands): + for command in commands: + command = "%(cli_wrapper)s %(command)s" % locals() + try: + with open(path.join(environ["CI_PROJECT_DIR"], "log.txt"), "a") as log: + command_output = check_output(command, shell=True) + log.write("%(command_output)s\n" % locals()) + except: + exit(1) + + +fetch_zcash_params() +start_daemon(daemon_wrapper) +sleep(daemon_runtime_seconds) +run_cli_commands(cli_wrapper, cli_commands) diff --git a/requirements-debian.txt b/requirements-debian.txt new file mode 100644 index 000000000..7bfd9e6e2 --- /dev/null +++ b/requirements-debian.txt @@ -0,0 +1,18 @@ +autoconf +automake +bsdmainutils +build-essential +curl +g++-multilib +git +libc6-dev +libcurl4-openssl-dev +libtool +ncurses-dev +pkg-config +python +python-zmq +m4 +unzip +wget +zlib1g-dev diff --git a/src/Makefile.am b/src/Makefile.am index 7355d17d2..e22e37137 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -164,8 +164,10 @@ BITCOIN_CORE_H = \ consensus/validation.h \ core_io.h \ core_memusage.h \ + crypto/haraka.h \ + crypto/haraka_portable.h \ + crypto/verus_hash.h \ deprecation.h \ - haraka.h \ hash.h \ httprpc.h \ httpserver.h \ @@ -189,6 +191,7 @@ BITCOIN_CORE_H = \ pow.h \ primitives/block.h \ primitives/transaction.h \ + primitives/nonce.h \ protocol.h \ pubkey.h \ random.h \ @@ -235,6 +238,7 @@ BITCOIN_CORE_H = \ wallet/wallet.h \ wallet/wallet_ismine.h \ wallet/walletdb.h \ + veruslaunch.h \ zmq/zmqabstractnotifier.h \ zmq/zmqconfig.h\ zmq/zmqnotificationinterface.h \ @@ -264,6 +268,10 @@ libbitcoin_server_a_SOURCES = \ cc/betprotocol.cpp \ chain.cpp \ checkpoints.cpp \ + crypto/haraka.h \ + crypto/haraka_portable.h \ + crypto/verus_hash.h \ + crypto/verus_hash.cpp \ deprecation.cpp \ httprpc.cpp \ httpserver.cpp \ @@ -361,6 +369,8 @@ crypto_libbitcoin_crypto_a_SOURCES = \ crypto/sha256.h \ crypto/sha512.cpp \ crypto/sha512.h \ + crypto/haraka.h \ + crypto/haraka_portable.h \ crypto/verus_hash.h \ crypto/verus_hash.cpp @@ -381,7 +391,9 @@ crypto_libverus_crypto_a_CPPFLAGS = -O3 -Wint-conversion -march=native -funroll- crypto_libverus_crypto_a_CXXFLAGS = -O3 -Wint-conversion -march=native -funroll-loops -fomit-frame-pointer -fPIC $(AM_CXXFLAGS) crypto_libverus_crypto_a_SOURCES = \ crypto/haraka.h \ - crypto/haraka.c + crypto/haraka.c \ + crypto/haraka_portable.h \ + crypto/haraka_portable.c # common: shared between zcashd and non-server tools libbitcoin_common_a_CPPFLAGS = -fPIC $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) @@ -396,12 +408,17 @@ libbitcoin_common_a_SOURCES = \ consensus/upgrades.cpp \ core_read.cpp \ core_write.cpp \ + crypto/haraka.h \ + crypto/haraka_portable.h \ + crypto/verus_hash.h \ + crypto/verus_hash.cpp \ hash.cpp \ key.cpp \ keystore.cpp \ netbase.cpp \ primitives/block.cpp \ primitives/transaction.cpp \ + primitives/nonce.cpp \ protocol.cpp \ pubkey.cpp \ scheduler.cpp \ @@ -412,6 +429,7 @@ libbitcoin_common_a_SOURCES = \ script/script_error.cpp \ script/sign.cpp \ script/standard.cpp \ + veruslaunch.cpp \ $(BITCOIN_CORE_H) \ $(LIBZCASH_H) @@ -529,6 +547,7 @@ komodo_cli_LDADD = \ $(EVENT_LIBS) \ $(LIBZCASH) \ $(LIBBITCOIN_CRYPTO) \ + $(LIBVERUS_CRYPTO) \ $(LIBZCASH_LIBS) if ENABLE_WALLET @@ -609,6 +628,7 @@ libzcashconsensus_la_SOURCES = \ crypto/sha512.cpp \ hash.cpp \ primitives/transaction.cpp \ + primitives/nonce.cpp \ pubkey.cpp \ script/zcashconsensus.cpp \ script/interpreter.cpp \ diff --git a/src/base58.cpp b/src/base58.cpp index c086cc854..b85803569 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -302,6 +302,14 @@ bool CBitcoinAddress::GetKeyID(CKeyID& keyID) const return true; } +bool CBitcoinAddress::GetKeyID_NoCheck(CKeyID& keyID) const +{ + uint160 id; + memcpy(&id, &vchData[0], 20); + keyID = CKeyID(id); + return true; +} + bool CBitcoinAddress::IsScript() const { return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS); diff --git a/src/base58.h b/src/base58.h index 73e1c4d94..4e8b2c3ce 100644 --- a/src/base58.h +++ b/src/base58.h @@ -163,6 +163,7 @@ public: CTxDestination Get() const; bool GetKeyID(CKeyID &keyID) const; + bool GetKeyID_NoCheck(CKeyID& keyID) const; bool GetIndexKey(uint160& hashBytes, int& type) const; bool IsScript() const; }; diff --git a/src/chain.cpp b/src/chain.cpp index 7bb72d5d3..d79a66f9a 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -11,6 +11,7 @@ using namespace std; * CChain implementation */ void CChain::SetTip(CBlockIndex *pindex) { + lastTip = pindex; if (pindex == NULL) { vChain.clear(); return; diff --git a/src/chain.h b/src/chain.h index a28e4e44a..15036325a 100644 --- a/src/chain.h +++ b/src/chain.h @@ -321,6 +321,16 @@ public: //! Efficiently find an ancestor of this block. CBlockIndex* GetAncestor(int height); const CBlockIndex* GetAncestor(int height) const; + + int32_t GetVerusPOSTarget() const + { + return GetBlockHeader().GetVerusPOSTarget(); + } + + bool IsVerusPOSBlock() const + { + return GetBlockHeader().IsVerusPOSBlock(); + } }; /** Used to marshal pointers into hashes for db storage. */ @@ -414,6 +424,7 @@ public: class CChain { private: std::vector vChain; + CBlockIndex *lastTip; public: /** Returns the index entry for the genesis block of this chain, or NULL if none. */ @@ -426,6 +437,11 @@ public: return vChain.size() > 0 ? vChain[vChain.size() - 1] : NULL; } + /** 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()) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index be9d7ac8a..0dae43f81 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -92,7 +92,7 @@ public: { strNetworkID = "main"; strCurrencyUnits = "KMD"; - consensus.fCoinbaseMustBeProtected = false;//true; + consensus.fCoinbaseMustBeProtected = false; // true this is only true wuth Verus and enforced after block 12800 consensus.nSubsidySlowStartInterval = 20000; consensus.nSubsidyHalvingInterval = 840000; consensus.nMajorityEnforceBlockUpgrade = 750; @@ -176,6 +176,8 @@ public: base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x88)(0xAD)(0xE4).convert_to_container >(); // 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" + base58Prefixes[ZCVIEWING_KEY] = {0xA8,0xAB,0xD3}; // guarantees the first two characters, when base58 encoded, are "SK" base58Prefixes[ZCSPENDING_KEY] = {171,54}; @@ -232,6 +234,12 @@ void *chainparams_commandline(void *ptr) mainParams.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); + // only require coinbase protection on Verus from the Komodo family of coins + if (strcmp(ASSETCHAINS_SYMBOL,"VRSC") == 0) + { + mainParams.consensus.fCoinbaseMustBeProtected = true; + } + if (ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH) { // this is only good for 60 second blocks with an averaging window of 45. for other parameters, use: @@ -250,21 +258,23 @@ void *chainparams_commandline(void *ptr) mainParams.consensus.nPOSTargetSpacing = VERUS_BLOCK_POSUNITS * 2; // nLwmaPOSAjustedWeight = (N+1)/2 * (0.9989^(500/nPOSAveragingWindow)) * nPOSTargetSpacing // this needs to be recalculated if VERUS_BLOCK_POSUNITS is changed - mainParams.consensus.nLwmaPOSAjustedWeight = 45000; + mainParams.consensus.nLwmaPOSAjustedWeight = 46531; } checkpointData = //(Checkpoints::CCheckpointData) { boost::assign::map_list_of - (0, mainParams.consensus.hashGenesisBlock), - //(2500, uint256S("0x0e6a3d5a46eba97c4e7618d66a39f115729e1176433c98481124c2bf733aa54e")) - //(15000, uint256S("0x00f0bd236790e903321a2d22f85bd6bf8a505f6ef4eddb20458a65d37e14d142")), - //(100000, uint256S("0x0f02eb1f3a4b89df9909fec81a4bd7d023e32e24e1f5262d9fc2cc36a715be6f")), - (int64_t)1481120910, // * UNIX timestamp of last checkpoint block - (int64_t)110415, // * total number of transactions between genesis and last checkpoint - // (the tx=... number in the SetBestChain debug.log lines) + (0, mainParams.consensus.hashGenesisBlock) + (10000, uint256S("0xac2cd7d37177140ea4991cf630c0b9c7f94d707b84fb0351bf3a44856d2ae5dc")) + (20000, uint256S("0xb0e8cb9f77aaa7ff5bd90d6c08d06f4c4bf03e00c2b8a35a042e760845590c8a")) + (30000, uint256S("0xf2112ca577338ad7104bf905fa6a63d36b17a86f914c97b73cd31d43fcd7557c")) + (40000, uint256S("0x00000000008f83378dab727864b763ce91a4ea5f75d55939c0c1390cfb8c38f1")) + (49170, uint256S("0x2add646c0089871ec2379f02f7cd60b3af6efd9c152a6f16fc10925458c270cc")), + (int64_t)1529910234, // * UNIX timestamp of last checkpoint block + (int64_t)63661, // * total number of transactions between genesis and last checkpoint + // (the tx=... number in the SetBestChain debug.log lines) (double)2777 // * estimated number of transactions per day after checkpoint - // total number of tx / (checkpoint block height / (24 * 24)) + // total number of tx / (checkpoint block height / (24 * 24)) }; } @@ -493,6 +503,8 @@ public: 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[ZCPAYMENT_ADDRRESS] = {20,81}; + // guarantees the first 4 characters, when base58 encoded, are "ZiVt" + base58Prefixes[ZCVIEWING_KEY] = {0xA8,0xAC,0x0C}; base58Prefixes[ZCSPENDING_KEY] = {177,235}; vFixedSeeds = std::vector(pnSeed6_test, pnSeed6_test + ARRAYLEN(pnSeed6_test)); diff --git a/src/coins.cpp b/src/coins.cpp index 42939ccac..990ee3d12 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -253,7 +253,16 @@ bool CCoinsViewCache::HaveCoins(const uint256 &txid) const { uint256 CCoinsViewCache::GetBestBlock() const { if (hashBlock.IsNull()) - hashBlock = base->GetBestBlock(); + { + if (base) + { + hashBlock = base->GetBestBlock(); + } + else + { + hashBlock = uint256(); + } + } return hashBlock; } @@ -379,17 +388,34 @@ const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input) const return coins->vout[input.prevout.n]; } -const CScript &CCoinsViewCache::GetSpendFor(const CTxIn& input) const -{ - const CCoins* coins = AccessCoins(input.prevout.hash); - assert(coins); - return coins->vout[input.prevout.n].scriptPubKey; -} - //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); + if (coins->nHeight < 6400 && !strcmp(ASSETCHAINS_SYMBOL, "VRSC")) + { + std::string hc = input.prevout.hash.ToString(); + if (LaunchMap().lmap.count(hc)) + { + CTransactionExceptionData &txData = LaunchMap().lmap[hc]; + if ((txData.voutMask & (((uint64_t)1) << (uint64_t)input.prevout.n)) != 0) + { + return txData.scriptPubKey; + } + } + } + return coins->vout[input.prevout.n].scriptPubKey; +} + +const CScript &CCoinsViewCache::GetSpendFor(const CTxIn& input) const +{ + const CCoins* coins = AccessCoins(input.prevout.hash); + return GetSpendFor(coins, input); +} + CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t *interestp,const CTransaction& tx,uint32_t tiptime) const { if ( interestp != 0 ) diff --git a/src/coins.h b/src/coins.h index 85cb69d5c..c0e06f64a 100644 --- a/src/coins.h +++ b/src/coins.h @@ -13,13 +13,18 @@ #include "memusage.h" #include "serialize.h" #include "uint256.h" +#include "base58.h" +#include "pubkey.h" #include #include +#include +#include #include #include #include "zcash/IncrementalMerkleTree.hpp" +#include "veruslaunch.h" /** * Pruned version of CTransaction: only retains metadata and unspent transaction outputs @@ -436,6 +441,37 @@ public: friend class CCoinsViewCache; }; +class CTransactionExceptionData +{ + public: + CScript scriptPubKey; + uint64_t voutMask; + CTransactionExceptionData() : scriptPubKey(), voutMask() {} +}; + +class CLaunchMap +{ + public: + std::unordered_map lmap; + CLaunchMap() : lmap() + { + //printf("txid: %s -> addr: %s\n", whitelist_ids[i], whitelist_addrs[i]); + CBitcoinAddress bcaddr(whitelist_address); + CKeyID key; + if (bcaddr.GetKeyID_NoCheck(key)) + { + std::vector address = std::vector(key.begin(), key.end()); + for (int i = 0; i < WHITELIST_COUNT; i++) + { + std::string hash = uint256S(whitelist_ids[i]).ToString(); + lmap[hash].scriptPubKey << OP_DUP << OP_HASH160 << address << OP_EQUALVERIFY << OP_CHECKSIG; + lmap[hash].voutMask = whitelist_masks[i]; + } + } + } +}; +static CLaunchMap launchMap = CLaunchMap(); + /** CCoinsView that adds a memory cache for transactions to another CCoinsView */ class CCoinsViewCache : public CCoinsViewBacked { @@ -443,7 +479,6 @@ protected: /* Whether this cache has an active modifier. */ bool hasModifier; - /** * Make mutable so that we can "fill the cache" even from Get-methods * declared as "const". @@ -462,6 +497,7 @@ public: ~CCoinsViewCache(); // Standard CCoinsView methods + static CLaunchMap &LaunchMap() { return launchMap; } bool GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const; bool GetNullifier(const uint256 &nullifier) const; bool GetCoins(const uint256 &txid, CCoins &coins) const; @@ -535,6 +571,7 @@ public: const CTxOut &GetOutputFor(const CTxIn& input) const; const CScript &GetSpendFor(const CTxIn& input) const; + static const CScript &GetSpendFor(const CCoins *coins, const CTxIn& input); friend class CCoinsModifier; diff --git a/src/crypto/haraka.c b/src/crypto/haraka.c index ccfd8ce34..d611b9af5 100644 --- a/src/crypto/haraka.c +++ b/src/crypto/haraka.c @@ -28,6 +28,7 @@ Optimized Implementations for Haraka256 and Haraka512 #include "crypto/haraka.h" u128 rc[40]; +u128 rc0[40] = {0}; void load_constants() { rc[0] = _mm_set_epi32(0x0684704c,0xe620c00a,0xb2c5fef0,0x75817b9d); @@ -365,6 +366,37 @@ void haraka512(unsigned char *out, const unsigned char *in) { TRUNCSTORE(out, s[0], s[1], s[2], s[3]); } +void haraka512_zero(unsigned char *out, const unsigned char *in) { + u128 s[4], tmp; + + s[0] = LOAD(in); + s[1] = LOAD(in + 16); + s[2] = LOAD(in + 32); + s[3] = LOAD(in + 48); + + AES4_zero(s[0], s[1], s[2], s[3], 0); + MIX4(s[0], s[1], s[2], s[3]); + + AES4_zero(s[0], s[1], s[2], s[3], 8); + MIX4(s[0], s[1], s[2], s[3]); + + AES4_zero(s[0], s[1], s[2], s[3], 16); + MIX4(s[0], s[1], s[2], s[3]); + + AES4_zero(s[0], s[1], s[2], s[3], 24); + MIX4(s[0], s[1], s[2], s[3]); + + AES4_zero(s[0], s[1], s[2], s[3], 32); + MIX4(s[0], s[1], s[2], s[3]); + + s[0] = _mm_xor_si128(s[0], LOAD(in)); + s[1] = _mm_xor_si128(s[1], LOAD(in + 16)); + s[2] = _mm_xor_si128(s[2], LOAD(in + 32)); + s[3] = _mm_xor_si128(s[3], LOAD(in + 48)); + + TRUNCSTORE(out, s[0], s[1], s[2], s[3]); +} + void haraka512_4x(unsigned char *out, const unsigned char *in) { u128 s[4][4], tmp; diff --git a/src/crypto/haraka.h b/src/crypto/haraka.h index 203f8fbf6..daf657184 100644 --- a/src/crypto/haraka.h +++ b/src/crypto/haraka.h @@ -30,7 +30,11 @@ Optimized Implementations for Haraka256 and Haraka512 #define NUMROUNDS 5 +#ifdef _WIN32 +typedef unsigned long long u64; +#else typedef unsigned long u64; +#endif typedef __m128i u128; extern u128 rc[40]; @@ -64,6 +68,16 @@ extern u128 rc[40]; s2 = _mm_aesenc_si128(s2, rc[rci + 6]); \ s3 = _mm_aesenc_si128(s3, rc[rci + 7]); \ +#define AES4_zero(s0, s1, s2, s3, rci) \ + s0 = _mm_aesenc_si128(s0, rc0[rci]); \ + s1 = _mm_aesenc_si128(s1, rc0[rci + 1]); \ + s2 = _mm_aesenc_si128(s2, rc0[rci + 2]); \ + s3 = _mm_aesenc_si128(s3, rc0[rci + 3]); \ + s0 = _mm_aesenc_si128(s0, rc0[rci + 4]); \ + s1 = _mm_aesenc_si128(s1, rc0[rci + 5]); \ + s2 = _mm_aesenc_si128(s2, rc0[rci + 6]); \ + s3 = _mm_aesenc_si128(s3, rc0[rci + 7]); \ + #define AES4_4x(s0, s1, s2, s3, rci) \ AES4(s0[0], s0[1], s0[2], s0[3], rci); \ AES4(s1[0], s1[1], s1[2], s1[3], rci); \ @@ -105,6 +119,7 @@ void haraka256_4x(unsigned char *out, const unsigned char *in); void haraka256_8x(unsigned char *out, const unsigned char *in); void haraka512(unsigned char *out, const unsigned char *in); +void haraka512_zero(unsigned char *out, const unsigned char *in); void haraka512_4x(unsigned char *out, const unsigned char *in); void haraka512_8x(unsigned char *out, const unsigned char *in); diff --git a/src/crypto/haraka_portable.c b/src/crypto/haraka_portable.c new file mode 100644 index 000000000..0792f8b2f --- /dev/null +++ b/src/crypto/haraka_portable.c @@ -0,0 +1,375 @@ +/* +Plain C implementation of the Haraka256 and Haraka512 permutations. +*/ +#include +#include +#include + +#include "haraka_portable.h" + +#define HARAKAS_RATE 32 + +static const unsigned char haraka_rc[40][16] = { + {0x9d, 0x7b, 0x81, 0x75, 0xf0, 0xfe, 0xc5, 0xb2, 0x0a, 0xc0, 0x20, 0xe6, 0x4c, 0x70, 0x84, 0x06}, + {0x17, 0xf7, 0x08, 0x2f, 0xa4, 0x6b, 0x0f, 0x64, 0x6b, 0xa0, 0xf3, 0x88, 0xe1, 0xb4, 0x66, 0x8b}, + {0x14, 0x91, 0x02, 0x9f, 0x60, 0x9d, 0x02, 0xcf, 0x98, 0x84, 0xf2, 0x53, 0x2d, 0xde, 0x02, 0x34}, + {0x79, 0x4f, 0x5b, 0xfd, 0xaf, 0xbc, 0xf3, 0xbb, 0x08, 0x4f, 0x7b, 0x2e, 0xe6, 0xea, 0xd6, 0x0e}, + {0x44, 0x70, 0x39, 0xbe, 0x1c, 0xcd, 0xee, 0x79, 0x8b, 0x44, 0x72, 0x48, 0xcb, 0xb0, 0xcf, 0xcb}, + {0x7b, 0x05, 0x8a, 0x2b, 0xed, 0x35, 0x53, 0x8d, 0xb7, 0x32, 0x90, 0x6e, 0xee, 0xcd, 0xea, 0x7e}, + {0x1b, 0xef, 0x4f, 0xda, 0x61, 0x27, 0x41, 0xe2, 0xd0, 0x7c, 0x2e, 0x5e, 0x43, 0x8f, 0xc2, 0x67}, + {0x3b, 0x0b, 0xc7, 0x1f, 0xe2, 0xfd, 0x5f, 0x67, 0x07, 0xcc, 0xca, 0xaf, 0xb0, 0xd9, 0x24, 0x29}, + {0xee, 0x65, 0xd4, 0xb9, 0xca, 0x8f, 0xdb, 0xec, 0xe9, 0x7f, 0x86, 0xe6, 0xf1, 0x63, 0x4d, 0xab}, + {0x33, 0x7e, 0x03, 0xad, 0x4f, 0x40, 0x2a, 0x5b, 0x64, 0xcd, 0xb7, 0xd4, 0x84, 0xbf, 0x30, 0x1c}, + {0x00, 0x98, 0xf6, 0x8d, 0x2e, 0x8b, 0x02, 0x69, 0xbf, 0x23, 0x17, 0x94, 0xb9, 0x0b, 0xcc, 0xb2}, + {0x8a, 0x2d, 0x9d, 0x5c, 0xc8, 0x9e, 0xaa, 0x4a, 0x72, 0x55, 0x6f, 0xde, 0xa6, 0x78, 0x04, 0xfa}, + {0xd4, 0x9f, 0x12, 0x29, 0x2e, 0x4f, 0xfa, 0x0e, 0x12, 0x2a, 0x77, 0x6b, 0x2b, 0x9f, 0xb4, 0xdf}, + {0xee, 0x12, 0x6a, 0xbb, 0xae, 0x11, 0xd6, 0x32, 0x36, 0xa2, 0x49, 0xf4, 0x44, 0x03, 0xa1, 0x1e}, + {0xa6, 0xec, 0xa8, 0x9c, 0xc9, 0x00, 0x96, 0x5f, 0x84, 0x00, 0x05, 0x4b, 0x88, 0x49, 0x04, 0xaf}, + {0xec, 0x93, 0xe5, 0x27, 0xe3, 0xc7, 0xa2, 0x78, 0x4f, 0x9c, 0x19, 0x9d, 0xd8, 0x5e, 0x02, 0x21}, + {0x73, 0x01, 0xd4, 0x82, 0xcd, 0x2e, 0x28, 0xb9, 0xb7, 0xc9, 0x59, 0xa7, 0xf8, 0xaa, 0x3a, 0xbf}, + {0x6b, 0x7d, 0x30, 0x10, 0xd9, 0xef, 0xf2, 0x37, 0x17, 0xb0, 0x86, 0x61, 0x0d, 0x70, 0x60, 0x62}, + {0xc6, 0x9a, 0xfc, 0xf6, 0x53, 0x91, 0xc2, 0x81, 0x43, 0x04, 0x30, 0x21, 0xc2, 0x45, 0xca, 0x5a}, + {0x3a, 0x94, 0xd1, 0x36, 0xe8, 0x92, 0xaf, 0x2c, 0xbb, 0x68, 0x6b, 0x22, 0x3c, 0x97, 0x23, 0x92}, + {0xb4, 0x71, 0x10, 0xe5, 0x58, 0xb9, 0xba, 0x6c, 0xeb, 0x86, 0x58, 0x22, 0x38, 0x92, 0xbf, 0xd3}, + {0x8d, 0x12, 0xe1, 0x24, 0xdd, 0xfd, 0x3d, 0x93, 0x77, 0xc6, 0xf0, 0xae, 0xe5, 0x3c, 0x86, 0xdb}, + {0xb1, 0x12, 0x22, 0xcb, 0xe3, 0x8d, 0xe4, 0x83, 0x9c, 0xa0, 0xeb, 0xff, 0x68, 0x62, 0x60, 0xbb}, + {0x7d, 0xf7, 0x2b, 0xc7, 0x4e, 0x1a, 0xb9, 0x2d, 0x9c, 0xd1, 0xe4, 0xe2, 0xdc, 0xd3, 0x4b, 0x73}, + {0x4e, 0x92, 0xb3, 0x2c, 0xc4, 0x15, 0x14, 0x4b, 0x43, 0x1b, 0x30, 0x61, 0xc3, 0x47, 0xbb, 0x43}, + {0x99, 0x68, 0xeb, 0x16, 0xdd, 0x31, 0xb2, 0x03, 0xf6, 0xef, 0x07, 0xe7, 0xa8, 0x75, 0xa7, 0xdb}, + {0x2c, 0x47, 0xca, 0x7e, 0x02, 0x23, 0x5e, 0x8e, 0x77, 0x59, 0x75, 0x3c, 0x4b, 0x61, 0xf3, 0x6d}, + {0xf9, 0x17, 0x86, 0xb8, 0xb9, 0xe5, 0x1b, 0x6d, 0x77, 0x7d, 0xde, 0xd6, 0x17, 0x5a, 0xa7, 0xcd}, + {0x5d, 0xee, 0x46, 0xa9, 0x9d, 0x06, 0x6c, 0x9d, 0xaa, 0xe9, 0xa8, 0x6b, 0xf0, 0x43, 0x6b, 0xec}, + {0xc1, 0x27, 0xf3, 0x3b, 0x59, 0x11, 0x53, 0xa2, 0x2b, 0x33, 0x57, 0xf9, 0x50, 0x69, 0x1e, 0xcb}, + {0xd9, 0xd0, 0x0e, 0x60, 0x53, 0x03, 0xed, 0xe4, 0x9c, 0x61, 0xda, 0x00, 0x75, 0x0c, 0xee, 0x2c}, + {0x50, 0xa3, 0xa4, 0x63, 0xbc, 0xba, 0xbb, 0x80, 0xab, 0x0c, 0xe9, 0x96, 0xa1, 0xa5, 0xb1, 0xf0}, + {0x39, 0xca, 0x8d, 0x93, 0x30, 0xde, 0x0d, 0xab, 0x88, 0x29, 0x96, 0x5e, 0x02, 0xb1, 0x3d, 0xae}, + {0x42, 0xb4, 0x75, 0x2e, 0xa8, 0xf3, 0x14, 0x88, 0x0b, 0xa4, 0x54, 0xd5, 0x38, 0x8f, 0xbb, 0x17}, + {0xf6, 0x16, 0x0a, 0x36, 0x79, 0xb7, 0xb6, 0xae, 0xd7, 0x7f, 0x42, 0x5f, 0x5b, 0x8a, 0xbb, 0x34}, + {0xde, 0xaf, 0xba, 0xff, 0x18, 0x59, 0xce, 0x43, 0x38, 0x54, 0xe5, 0xcb, 0x41, 0x52, 0xf6, 0x26}, + {0x78, 0xc9, 0x9e, 0x83, 0xf7, 0x9c, 0xca, 0xa2, 0x6a, 0x02, 0xf3, 0xb9, 0x54, 0x9a, 0xe9, 0x4c}, + {0x35, 0x12, 0x90, 0x22, 0x28, 0x6e, 0xc0, 0x40, 0xbe, 0xf7, 0xdf, 0x1b, 0x1a, 0xa5, 0x51, 0xae}, + {0xcf, 0x59, 0xa6, 0x48, 0x0f, 0xbc, 0x73, 0xc1, 0x2b, 0xd2, 0x7e, 0xba, 0x3c, 0x61, 0xc1, 0xa0}, + {0xa1, 0x9d, 0xc5, 0xe9, 0xfd, 0xbd, 0xd6, 0x4a, 0x88, 0x82, 0x28, 0x02, 0x03, 0xcc, 0x6a, 0x75} +}; + +static unsigned char rc[40][16]; +static unsigned char rc0[40][16]; +static unsigned char rc_sseed[40][16]; + +static const unsigned char sbox[256] = +{ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, + 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, + 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, + 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, + 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, + 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, + 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, + 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, + 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, + 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, + 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, + 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, + 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, + 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, + 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, + 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, + 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, + 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, + 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; + +#define XT(x) (((x) << 1) ^ ((((x) >> 7) & 1) * 0x1b)) + +// Simulate _mm_aesenc_si128 instructions from AESNI +void aesenc(unsigned char *s, const unsigned char *rk) +{ + unsigned char i, t, u, v[4][4]; + for (i = 0; i < 16; ++i) { + v[((i / 4) + 4 - (i%4) ) % 4][i % 4] = sbox[s[i]]; + } + for (i = 0; i < 4; ++i) { + t = v[i][0]; + u = v[i][0] ^ v[i][1] ^ v[i][2] ^ v[i][3]; + v[i][0] ^= u ^ XT(v[i][0] ^ v[i][1]); + v[i][1] ^= u ^ XT(v[i][1] ^ v[i][2]); + v[i][2] ^= u ^ XT(v[i][2] ^ v[i][3]); + v[i][3] ^= u ^ XT(v[i][3] ^ t); + } + for (i = 0; i < 16; ++i) { + s[i] = v[i / 4][i % 4] ^ rk[i]; + } +} + +// Simulate _mm_unpacklo_epi32 +void unpacklo32(unsigned char *t, unsigned char *a, unsigned char *b) +{ + unsigned char tmp[16]; + memcpy(tmp, a, 4); + memcpy(tmp + 4, b, 4); + memcpy(tmp + 8, a + 4, 4); + memcpy(tmp + 12, b + 4, 4); + memcpy(t, tmp, 16); +} + +// Simulate _mm_unpackhi_epi32 +void unpackhi32(unsigned char *t, unsigned char *a, unsigned char *b) +{ + unsigned char tmp[16]; + memcpy(tmp, a + 8, 4); + memcpy(tmp + 4, b + 8, 4); + memcpy(tmp + 8, a + 12, 4); + memcpy(tmp + 12, b + 12, 4); + memcpy(t, tmp, 16); +} + +void load_constants_port() +{ + /* Use the standard constants to generate tweaked ones. */ + memcpy(rc, haraka_rc, 40*16); +} + +void tweak_constants(const unsigned char *pk_seed, const unsigned char *sk_seed, + unsigned long long seed_length) +{ + unsigned char buf[40*16]; + + /* Use the standard constants to generate tweaked ones. */ + memcpy(rc, haraka_rc, 40*16); + + /* Constants for sk.seed */ + if (sk_seed != NULL) { + haraka_S(buf, 40*16, sk_seed, seed_length); + memcpy(rc_sseed, buf, 40*16); + } + + /* Constants for pk.seed */ + haraka_S(buf, 40*16, pk_seed, seed_length); + memcpy(rc, buf, 40*16); +} + +static void haraka_S_absorb(unsigned char *s, unsigned int r, + const unsigned char *m, unsigned long long mlen, + unsigned char p) +{ + unsigned long long i; + unsigned char t[r]; + + while (mlen >= r) { + // XOR block to state + for (i = 0; i < r; ++i) { + s[i] ^= m[i]; + } + haraka512_perm(s, s); + mlen -= r; + m += r; + } + + for (i = 0; i < r; ++i) { + t[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t[i] = m[i]; + } + t[i] = p; + t[r - 1] |= 128; + for (i = 0; i < r; ++i) { + s[i] ^= t[i]; + } +} + +static void haraka_S_squeezeblocks(unsigned char *h, unsigned long long nblocks, + unsigned char *s, unsigned int r) +{ + while (nblocks > 0) { + haraka512_perm(s, s); + memcpy(h, s, HARAKAS_RATE); + h += r; + nblocks--; + } +} + + +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen) +{ + unsigned long long i; + unsigned char s[64]; + unsigned char d[32]; + + for (i = 0; i < 64; i++) { + s[i] = 0; + } + haraka_S_absorb(s, 32, in, inlen, 0x1F); + + haraka_S_squeezeblocks(out, outlen / 32, s, 32); + out += (outlen / 32) * 32; + + if (outlen % 32) { + haraka_S_squeezeblocks(d, 1, s, 32); + for (i = 0; i < outlen % 32; i++) { + out[i] = d[i]; + } + } +} + +void haraka512_perm(unsigned char *out, const unsigned char *in) +{ + int i, j; + + unsigned char s[64], tmp[16]; + + memcpy(s, in, 16); + memcpy(s + 16, in + 16, 16); + memcpy(s + 32, in + 32, 16); + memcpy(s + 48, in + 48, 16); + + for (i = 0; i < 5; ++i) { + // aes round(s) + for (j = 0; j < 2; ++j) { + aesenc(s, rc[4*2*i + 4*j]); + aesenc(s + 16, rc[4*2*i + 4*j + 1]); + aesenc(s + 32, rc[4*2*i + 4*j + 2]); + aesenc(s + 48, rc[4*2*i + 4*j + 3]); + } + + // mixing + unpacklo32(tmp, s, s + 16); + unpackhi32(s, s, s + 16); + unpacklo32(s + 16, s + 32, s + 48); + unpackhi32(s + 32, s + 32, s + 48); + unpacklo32(s + 48, s, s + 32); + unpackhi32(s, s, s + 32); + unpackhi32(s + 32, s + 16, tmp); + unpacklo32(s + 16, s + 16, tmp); + } + + memcpy(out, s, 64); +} + +void haraka512_port(unsigned char *out, const unsigned char *in) +{ + int i; + + unsigned char buf[64]; + + haraka512_perm(buf, in); + /* Feed-forward */ + for (i = 0; i < 64; i++) { + buf[i] = buf[i] ^ in[i]; + } + + /* Truncated */ + memcpy(out, buf + 8, 8); + memcpy(out + 8, buf + 24, 8); + memcpy(out + 16, buf + 32, 8); + memcpy(out + 24, buf + 48, 8); +} + +void haraka512_perm_zero(unsigned char *out, const unsigned char *in) +{ + int i, j; + + unsigned char s[64], tmp[16]; + + memcpy(s, in, 16); + memcpy(s + 16, in + 16, 16); + memcpy(s + 32, in + 32, 16); + memcpy(s + 48, in + 48, 16); + + for (i = 0; i < 5; ++i) { + // aes round(s) + for (j = 0; j < 2; ++j) { + aesenc(s, rc0[4*2*i + 4*j]); + aesenc(s + 16, rc0[4*2*i + 4*j + 1]); + aesenc(s + 32, rc0[4*2*i + 4*j + 2]); + aesenc(s + 48, rc0[4*2*i + 4*j + 3]); + } + + // mixing + unpacklo32(tmp, s, s + 16); + unpackhi32(s, s, s + 16); + unpacklo32(s + 16, s + 32, s + 48); + unpackhi32(s + 32, s + 32, s + 48); + unpacklo32(s + 48, s, s + 32); + unpackhi32(s, s, s + 32); + unpackhi32(s + 32, s + 16, tmp); + unpacklo32(s + 16, s + 16, tmp); + } + + memcpy(out, s, 64); +} + +void haraka512_port_zero(unsigned char *out, const unsigned char *in) +{ + int i; + + unsigned char buf[64]; + + haraka512_perm_zero(buf, in); + /* Feed-forward */ + for (i = 0; i < 64; i++) { + buf[i] = buf[i] ^ in[i]; + } + + /* Truncated */ + memcpy(out, buf + 8, 8); + memcpy(out + 8, buf + 24, 8); + memcpy(out + 16, buf + 32, 8); + memcpy(out + 24, buf + 48, 8); +} + +void haraka256_port(unsigned char *out, const unsigned char *in) +{ + int i, j; + + unsigned char s[32], tmp[16]; + + memcpy(s, in, 16); + memcpy(s + 16, in + 16, 16); + + for (i = 0; i < 5; ++i) { + // aes round(s) + for (j = 0; j < 2; ++j) { + aesenc(s, rc[2*2*i + 2*j]); + aesenc(s + 16, rc[2*2*i + 2*j + 1]); + } + + // mixing + unpacklo32(tmp, s, s + 16); + unpackhi32(s + 16, s, s + 16); + memcpy(s, tmp, 16); + } + + /* Feed-forward */ + for (i = 0; i < 32; i++) { + out[i] = in[i] ^ s[i]; + } +} + +void haraka256_sk(unsigned char *out, const unsigned char *in) +{ + int i, j; + + unsigned char s[32], tmp[16]; + + memcpy(s, in, 16); + memcpy(s + 16, in + 16, 16); + + for (i = 0; i < 5; ++i) { + // aes round(s) + for (j = 0; j < 2; ++j) { + aesenc(s, rc_sseed[2*2*i + 2*j]); + aesenc(s + 16, rc_sseed[2*2*i + 2*j + 1]); + } + + // mixing + unpacklo32(tmp, s, s + 16); + unpackhi32(s + 16, s, s + 16); + memcpy(s, tmp, 16); + } + + /* Feed-forward */ + for (i = 0; i < 32; i++) { + out[i] = in[i] ^ s[i]; + } +} diff --git a/src/crypto/haraka_portable.h b/src/crypto/haraka_portable.h new file mode 100644 index 000000000..dcc4f65ae --- /dev/null +++ b/src/crypto/haraka_portable.h @@ -0,0 +1,33 @@ +#ifndef SPX_HARAKA_H +#define SPX_HARAKA_H + +/* load constants */ +void load_constants_port(); + +/* Tweak constants with seed */ +void tweak_constants(const unsigned char *pk_seed, const unsigned char *sk_seed, + unsigned long long seed_length); + +/* Haraka Sponge */ +void haraka_S(unsigned char *out, unsigned long long outlen, + const unsigned char *in, unsigned long long inlen); + +/* Applies the 512-bit Haraka permutation to in. */ +void haraka512_perm(unsigned char *out, const unsigned char *in); + +/* Implementation of Haraka-512 */ +void haraka512_port(unsigned char *out, const unsigned char *in); + +/* Applies the 512-bit Haraka permutation to in, using zero key. */ +void haraka512_perm_zero(unsigned char *out, const unsigned char *in); + +/* Implementation of Haraka-512, using zero key */ +void haraka512_port_zero(unsigned char *out, const unsigned char *in); + +/* Implementation of Haraka-256 */ +void haraka256_port(unsigned char *out, const unsigned char *in); + +/* Implementation of Haraka-256 using sk.seed constants */ +void haraka256_sk(unsigned char *out, const unsigned char *in); + +#endif diff --git a/src/crypto/verus_hash.cpp b/src/crypto/verus_hash.cpp index baa5b45bd..aeae9712b 100644 --- a/src/crypto/verus_hash.cpp +++ b/src/crypto/verus_hash.cpp @@ -12,6 +12,8 @@ bit output. #include "crypto/common.h" #include "crypto/verus_hash.h" +void (*CVerusHash::haraka512Function)(unsigned char *out, const unsigned char *in); + void CVerusHash::Hash(void *result, const void *data, size_t len) { unsigned char buf[128]; @@ -36,7 +38,7 @@ void CVerusHash::Hash(void *result, const void *data, size_t len) memcpy(bufPtr + 32, ptr + pos, i); memset(bufPtr + 32 + i, 0, 32 - i); } - haraka512(bufPtr2, bufPtr); + (*haraka512Function)(bufPtr2, bufPtr); bufPtr2 = bufPtr; bufPtr += nextOffset; nextOffset *= -1; @@ -44,6 +46,18 @@ void CVerusHash::Hash(void *result, const void *data, size_t len) memcpy(result, bufPtr, 32); }; +void CVerusHash::init() +{ + if (IsCPUVerusOptimized()) + { + haraka512Function = &haraka512_zero; + } + else + { + haraka512Function = &haraka512_port_zero; + } +} + CVerusHash &CVerusHash::Write(const unsigned char *data, size_t len) { unsigned char *tmp; @@ -56,7 +70,7 @@ CVerusHash &CVerusHash::Write(const unsigned char *data, size_t len) if (len - pos >= room) { memcpy(curBuf + 32 + curPos, data + pos, room); - haraka512(result, curBuf); + (*haraka512Function)(result, curBuf); tmp = curBuf; curBuf = result; result = tmp; @@ -73,3 +87,92 @@ CVerusHash &CVerusHash::Write(const unsigned char *data, size_t len) return *this; } +// to be declared and accessed from C +void verus_hash(void *result, const void *data, size_t len) +{ + return CVerusHash::Hash(result, data, len); +} + +void (*CVerusHashV2::haraka512Function)(unsigned char *out, const unsigned char *in); + +void CVerusHashV2::init() +{ + if (IsCPUVerusOptimized()) + { + load_constants(); + haraka512Function = &haraka512; + } + else + { + // load and tweak the haraka constants + load_constants_port(); + haraka512Function = &haraka512_port; + } +} + +void CVerusHashV2::Hash(void *result, const void *data, size_t len) +{ + unsigned char buf[128]; + unsigned char *bufPtr = buf; + int pos = 0, nextOffset = 64; + unsigned char *bufPtr2 = bufPtr + nextOffset; + unsigned char *ptr = (unsigned char *)data; + + // put our last result or zero at beginning of buffer each time + memset(bufPtr, 0, 32); + + // digest up to 32 bytes at a time + for ( ; pos < len; pos += 32) + { + if (len - pos >= 32) + { + memcpy(bufPtr + 32, ptr + pos, 32); + } + else + { + int i = (int)(len - pos); + memcpy(bufPtr + 32, ptr + pos, i); + memset(bufPtr + 32 + i, 0, 32 - i); + } + (*haraka512Function)(bufPtr2, bufPtr); + bufPtr2 = bufPtr; + bufPtr += nextOffset; + nextOffset *= -1; + } + memcpy(result, bufPtr, 32); +}; + +CVerusHashV2 &CVerusHashV2::Write(const unsigned char *data, size_t len) +{ + unsigned char *tmp; + + // digest up to 32 bytes at a time + for ( int pos = 0; pos < len; ) + { + int room = 32 - curPos; + + if (len - pos >= room) + { + memcpy(curBuf + 32 + curPos, data + pos, room); + (*haraka512Function)(result, curBuf); + tmp = curBuf; + curBuf = result; + result = tmp; + pos += room; + curPos = 0; + } + else + { + memcpy(curBuf + 32 + curPos, data + pos, len - pos); + curPos += len - pos; + pos = len; + } + } + return *this; +} + +// to be declared and accessed from C +void verus_hash_v2(void *result, const void *data, size_t len) +{ + return CVerusHashV2::Hash(result, data, len); +} diff --git a/src/crypto/verus_hash.h b/src/crypto/verus_hash.h index 1d9b0b4c7..07c76d0f5 100644 --- a/src/crypto/verus_hash.h +++ b/src/crypto/verus_hash.h @@ -11,17 +11,23 @@ This provides the PoW hash function for Verus, enabling CPU mining. #include #include +#include + extern "C" { #include "crypto/haraka.h" +#include "crypto/haraka_portable.h" } class CVerusHash { public: static void Hash(void *result, const void *data, size_t len); + static void (*haraka512Function)(unsigned char *out, const unsigned char *in); - CVerusHash() {} + static void init(); + + CVerusHash() { } CVerusHash &Write(const unsigned char *data, size_t len); @@ -31,14 +37,25 @@ class CVerusHash result = buf2; curPos = 0; std::fill(buf1, buf1 + sizeof(buf1), 0); + return *this; } + int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); } + void ClearExtra() + { + if (curPos) + { + std::fill(curBuf + 32 + curPos, curBuf + 64, 0); + } + } + void ExtraHash(unsigned char hash[32]) { (*haraka512Function)(hash, curBuf); } + void Finalize(unsigned char hash[32]) { if (curPos) { std::fill(curBuf + 32 + curPos, curBuf + 64, 0); - haraka512(hash, curBuf); + (*haraka512Function)(hash, curBuf); } else std::memcpy(hash, curBuf, 32); @@ -51,4 +68,66 @@ class CVerusHash size_t curPos = 0; }; +class CVerusHashV2 +{ + public: + static void Hash(void *result, const void *data, size_t len); + static void (*haraka512Function)(unsigned char *out, const unsigned char *in); + + static void init(); + + CVerusHashV2() {} + + CVerusHashV2 &Write(const unsigned char *data, size_t len); + + CVerusHashV2 &Reset() + { + curBuf = buf1; + result = buf2; + curPos = 0; + std::fill(buf1, buf1 + sizeof(buf1), 0); + } + + int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); } + void ClearExtra() + { + if (curPos) + { + std::fill(curBuf + 32 + curPos, curBuf + 64, 0); + } + } + void ExtraHash(unsigned char hash[32]) { (*haraka512Function)(hash, curBuf); } + + void Finalize(unsigned char hash[32]) + { + if (curPos) + { + std::fill(curBuf + 32 + curPos, curBuf + 64, 0); + (*haraka512Function)(hash, curBuf); + } + else + std::memcpy(hash, curBuf, 32); + } + + private: + // only buf1, the first source, needs to be zero initialized + unsigned char buf1[64] = {0}, buf2[64]; + unsigned char *curBuf = buf1, *result = buf2; + size_t curPos = 0; +}; + +extern void verus_hash(void *result, const void *data, size_t len); +extern void verus_hash_v2(void *result, const void *data, size_t len); + +inline bool IsCPUVerusOptimized() +{ + unsigned int eax,ebx,ecx,edx; + + if (!__get_cpuid(1,&eax,&ebx,&ecx,&edx)) + { + return false; + } + return ((ecx & (bit_AVX | bit_AES)) == (bit_AVX | bit_AES)); +}; + #endif diff --git a/src/fiat/verus b/src/fiat/verus old mode 100644 new mode 100755 index 0bcc79fd2..956ac71c4 --- a/src/fiat/verus +++ b/src/fiat/verus @@ -4,4 +4,4 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $DIR -../komodo-cli -ac_name=VERUSTEST "$@" +../komodo-cli -ac_name=VRSC "$@" diff --git a/src/hash.h b/src/hash.h index 485655a00..d288af305 100644 --- a/src/hash.h +++ b/src/hash.h @@ -203,7 +203,8 @@ public: int nType; int nVersion; - CVerusHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn), state() {} + CVerusHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn), state() { } + void Reset() { state.Reset(); } CVerusHashWriter& write(const char *pch, size_t size) { state.Write((const unsigned char*)pch, size); @@ -217,6 +218,9 @@ public: return result; } + int64_t *xI64p() { return state.ExtraI64Ptr(); } + CVerusHash &GetState() { return state; } + template CVerusHashWriter& operator<<(const T& obj) { // Serialize to this stream @@ -225,6 +229,42 @@ public: } }; +/** A writer stream (for serialization) that computes a 256-bit Verus hash with key initialized to Haraka standard. */ +class CVerusHashV2Writer +{ +private: + CVerusHashV2 state; + +public: + int nType; + int nVersion; + + CVerusHashV2Writer(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn), state() {} + void Reset() { state.Reset(); } + + CVerusHashV2Writer& write(const char *pch, size_t size) { + state.Write((const unsigned char*)pch, size); + return (*this); + } + + // invalidates the object for further writing + uint256 GetHash() { + uint256 result; + state.Finalize((unsigned char*)&result); + return result; + } + + int64_t *xI64p() { return state.ExtraI64Ptr(); } + CVerusHashV2 &GetState() { return state; } + + template + CVerusHashV2Writer& operator<<(const T& obj) { + // Serialize to this stream + ::Serialize(*this, obj, nType, nVersion); + return (*this); + } +}; + /** Compute the 256-bit hash of an object's serialization. */ template uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION) @@ -243,6 +283,15 @@ uint256 SerializeVerusHash(const T& obj, int nType=SER_GETHASH, int nVersion=PRO return ss.GetHash(); } +/** Compute the 256-bit Verus hash of an object's serialization. */ +template +uint256 SerializeVerusHashV2(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION) +{ + CVerusHashV2Writer ss(nType, nVersion); + ss << obj; + return ss.GetHash(); +} + unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector& vDataToHash); void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]); diff --git a/src/init.cpp b/src/init.cpp index a937a035b..77967c96e 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1103,7 +1103,12 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // set the hash algorithm to use for this chain extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH; if (ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH) + { + // initialize VerusHash + CVerusHash::init(); + CVerusHashV2::init(); CBlockHeader::SetVerusHash(); + } // Sanity check if (!InitSanityCheck()) diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index 840e01472..2c1af165f 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -1258,7 +1258,7 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_ return(isPoS); } -// if slow flag is 1, this does a slower check that checks the target with consensus, otherwise quick, insecure check for internal integrity +// for now, we will ignore slowFlag in the interest of keeping success/fail simpler for security purposes bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height) { CBlockIndex *pastBlockIndex; @@ -1266,20 +1266,25 @@ bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height) int32_t txn_count; uint32_t voutNum; bool isPOS = false; - CTxDestination voutaddress, destaddress; + CTxDestination voutaddress, destaddress, cbaddress; arith_uint256 target, hash; CTransaction tx; - if (!pblock->isVerusPOSBlock()) + if (!pblock->IsVerusPOSBlock()) + { + printf("%s, height %d not POS block\n", pblock->nNonce.GetHex().c_str(), height); + pblock->nNonce.SetPOSTarget(pblock->nNonce.GetPOSTarget()); + printf("%s after setting POS target\n", pblock->nNonce.GetHex().c_str()); return false; + } - char voutaddr[64],destaddr[64]; + char voutaddr[64], destaddr[64], cbaddr[64]; - target.SetCompact(pblock->GetVerusPOSTarget()); txn_count = pblock->vtx.size(); if ( txn_count > 1 ) { + target.SetCompact(pblock->GetVerusPOSTarget()); txid = pblock->vtx[txn_count-1].vin[0].prevout.hash; voutNum = pblock->vtx[txn_count-1].vin[0].prevout.n; @@ -1291,20 +1296,28 @@ bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height) { fprintf(stderr,"ERROR: invalid PoS block %s - no transaction\n",blkHash.ToString().c_str()); } - else if (!(pastBlockIndex = komodo_chainactive(height - COINBASE_MATURITY))) + else if (!(pastBlockIndex = komodo_chainactive(height - 100))) { - fprintf(stderr,"ERROR: invalid PoS block %s - no past block hash\n",blkHash.ToString().c_str()); + fprintf(stderr,"WARNING: chain not fully loaded or invalid PoS block %s - no past block found\n",blkHash.ToString().c_str()); } else { - hash = UintToArith256(tx.GetVerusPOSHash(voutNum, height, pastBlockIndex->GetBlockHash())); + CBlockHeader bh = pastBlockIndex->GetBlockHeader(); + uint256 pastHash = bh.GetVerusEntropyHash(height - 100); + + // if height is over when Nonce is required to be the new format, we check that the new format is correct + // if over when we have the new POS hash function, we validate that as well + // they are 100 blocks apart + CPOSNonce nonce = pblock->nNonce; + + hash = UintToArith256(tx.GetVerusPOSHash(&nonce, voutNum, height, pastHash)); if (hash <= target) { if ((mapBlockIndex.count(blkHash) == 0) || !(pastBlockIndex = mapBlockIndex[blkHash]) || (height - pastBlockIndex->nHeight) < VERUS_MIN_STAKEAGE) { - fprintf(stderr,"ERROR: invalid PoS block %s - no prev block found\n",blkHash.ToString().c_str()); + fprintf(stderr,"ERROR: invalid PoS block %s - stake transaction too new\n",blkHash.ToString().c_str()); } else if ( slowflag != 0 ) { @@ -1317,24 +1330,37 @@ bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height) else { arith_uint256 cTarget; - cTarget.SetCompact(lwmaGetNextPOSRequired(previndex, Params().GetConsensus())); - - if (cTarget != target) + uint32_t nBits = lwmaGetNextPOSRequired(previndex, Params().GetConsensus()); + cTarget.SetCompact(nBits); + bool nonceOK = true; + + if (CPOSNonce::NewNonceActive(height) && !nonce.CheckPOSEntropy(pastHash, txid, voutNum)) { - fprintf(stderr,"ERROR: invalid PoS block %s - invalid diff target\n",blkHash.ToString().c_str()); + fprintf(stderr,"ERROR: invalid PoS block %s - nonce entropy corrupted or forged\n",blkHash.ToString().c_str()); + nonceOK = false; } - else if ( ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey, voutaddress) && - ExtractDestination(tx.vout[voutNum].scriptPubKey, destaddress) ) + else + { + if (cTarget != target) + { + fprintf(stderr,"ERROR: invalid PoS block %s - invalid diff target\n",blkHash.ToString().c_str()); + nonceOK = false; + } + } + if ( nonceOK && ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey, voutaddress) && + ExtractDestination(tx.vout[voutNum].scriptPubKey, destaddress) && + CScriptExt::ExtractVoutDestination(pblock->vtx[0], 0, cbaddress) ) { strcpy(voutaddr, CBitcoinAddress(voutaddress).ToString().c_str()); strcpy(destaddr, CBitcoinAddress(destaddress).ToString().c_str()); - if ( strcmp(destaddr,voutaddr) == 0 ) + strcpy(cbaddr, CBitcoinAddress(cbaddress).ToString().c_str()); + if ( !strcmp(destaddr,voutaddr) && ( !strcmp(destaddr,cbaddr) || (height < 17840)) ) { isPOS = true; } else { - fprintf(stderr,"ERROR: invalid PoS block %s - invalid stake destination\n",blkHash.ToString().c_str()); + fprintf(stderr,"ERROR: invalid PoS block %s - invalid stake or coinbase destination\n",blkHash.ToString().c_str()); } } } diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 8663a0c0a..f37573e04 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -73,15 +73,17 @@ uint32_t ASSETCHAINS_NUMALGOS = 2; uint32_t ASSETCHAINS_EQUIHASH = _ASSETCHAINS_EQUIHASH; uint32_t ASSETCHAINS_VERUSHASH = 1; const char *ASSETCHAINS_ALGORITHMS[] = {"equihash", "verushash"}; -uint64_t ASSETCHAINS_NONCEMASK[] = {0xffff,0xffffff}; -uint32_t ASSETCHAINS_NONCESHIFT[] = {32,40}; -uint32_t ASSETCHAINS_HASHESPERROUND[] = {1,512}; +uint64_t ASSETCHAINS_NONCEMASK[] = {0xffff,0xfffffff}; +uint32_t ASSETCHAINS_NONCESHIFT[] = {32,16}; +uint32_t ASSETCHAINS_HASHESPERROUND[] = {1,4096}; uint32_t ASSETCHAINS_ALGO = _ASSETCHAINS_EQUIHASH; // Verus proof of stake controls int32_t ASSETCHAINS_LWMAPOS = 0; // percentage of blocks should be PoS -int32_t VERUS_BLOCK_POSUNITS = 1000; // one block is 1000 units +int32_t VERUS_BLOCK_POSUNITS = 1024; // one block is 1000 units int32_t VERUS_MIN_STAKEAGE = 150; // 1/2 this should also be a cap on the POS averaging window, or startup could be too easy +int32_t VERUS_CONSECUTIVE_POS_THRESHOLD = 7; +int32_t VERUS_NOPOS_THRESHHOLD = 150; // if we have no POS blocks in this many blocks, set to default difficulty uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED,ASSETCHAINS_SUPPLY = 10; diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 2fa46819a..e927cc883 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -28,6 +28,8 @@ #define portable_mutex_lock pthread_mutex_lock #define portable_mutex_unlock pthread_mutex_unlock +extern void verus_hash(void *result, const void *data, size_t len); + struct allocitem { uint32_t allocsize,type; }; struct queueitem { struct queueitem *next,*prev; uint32_t allocsize,type; }; @@ -1022,23 +1024,45 @@ int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_ // from all other blocks. the sequence is extremely likely, but not guaranteed to be unique for each block chain uint64_t komodo_block_prg(uint32_t nHeight) { - int i; - uint8_t hashSrc[8]; - uint64_t result, hashSrc64 = (uint64_t)ASSETCHAINS_MAGIC << 32 + nHeight; - bits256 hashResult; - - for ( i = 0; i < sizeof(hashSrc); i++ ) + if (strcmp(ASSETCHAINS_SYMBOL, "VRSC") != 0 || nHeight >= 12800) { - hashSrc[i] = hashSrc64 & 0xff; - hashSrc64 >>= 8; - } - vcalc_sha256(0, hashResult.bytes, hashSrc, sizeof(hashSrc)); + uint64_t i, result = 0, hashSrc64 = ((uint64_t)ASSETCHAINS_MAGIC << 32) | (uint64_t)nHeight; + uint8_t hashSrc[8]; + bits256 hashResult; - for ( i = 0; i < 8; i++ ) - { - result = (result << 8) + hashResult.bytes[i]; + for ( i = 0; i < sizeof(hashSrc); i++ ) + { + uint64_t x = hashSrc64 >> (i * 8); + hashSrc[i] = (uint8_t)(x & 0xff); + } + verus_hash(hashResult.bytes, hashSrc, sizeof(hashSrc)); + for ( i = 0; i < 8; i++ ) + { + result = (result << 8) | hashResult.bytes[i]; + } + return result; + } + else + { + int i; + uint8_t hashSrc[8]; + uint64_t result, hashSrc64 = (uint64_t)ASSETCHAINS_MAGIC << 32 + nHeight; + bits256 hashResult; + + for ( i = 0; i < sizeof(hashSrc); i++ ) + { + hashSrc[i] = hashSrc64 & 0xff; + hashSrc64 >>= 8; + int8_t b = hashSrc[i]; + } + + vcalc_sha256(0, hashResult.bytes, hashSrc, sizeof(hashSrc)); + for ( i = 0; i < 8; i++ ) + { + result = (result << 8) + hashResult.bytes[i]; + } + return result; } - return(result); } // given a block height, this returns the unlock time for that block height, derived from @@ -1052,11 +1076,19 @@ int64_t komodo_block_unlocktime(uint32_t nHeight) unlocktime = ASSETCHAINS_TIMEUNLOCKTO; else { - unlocktime = komodo_block_prg(nHeight) / (0xffffffffffffffff / ((ASSETCHAINS_TIMEUNLOCKTO - ASSETCHAINS_TIMEUNLOCKFROM) + 1)); - // boundary and power of 2 can make it exceed to time by 1 - unlocktime = unlocktime + ASSETCHAINS_TIMEUNLOCKFROM; - if (unlocktime > ASSETCHAINS_TIMEUNLOCKTO) - unlocktime--; + if (strcmp(ASSETCHAINS_SYMBOL, "VRSC") != 0 || nHeight >= 12800) + { + unlocktime = komodo_block_prg(nHeight) % (ASSETCHAINS_TIMEUNLOCKTO - ASSETCHAINS_TIMEUNLOCKFROM); + unlocktime += ASSETCHAINS_TIMEUNLOCKFROM; + } + else + { + unlocktime = komodo_block_prg(nHeight) / (0xffffffffffffffff / ((ASSETCHAINS_TIMEUNLOCKTO - ASSETCHAINS_TIMEUNLOCKFROM) + 1)); + // boundary and power of 2 can make it exceed to time by 1 + unlocktime = unlocktime + ASSETCHAINS_TIMEUNLOCKFROM; + if (unlocktime > ASSETCHAINS_TIMEUNLOCKTO) + unlocktime--; + } } return ((int64_t)unlocktime); } diff --git a/src/main.cpp b/src/main.cpp index 44eb29f83..91fe8e62f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,7 +31,9 @@ #include "wallet/asyncrpcoperation_sendmany.h" #include "wallet/asyncrpcoperation_shieldcoinbase.h" +#include #include +#include #include #include @@ -908,7 +910,7 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in bool ContextualCheckCoinbaseTransaction(const CTransaction& tx, const int nHeight) { // if time locks are on, ensure that this coin base is time locked exactly as it should be - if ((uint64_t)(tx.GetValueOut()) >= ASSETCHAINS_TIMELOCKGTE) + if (((uint64_t)(tx.GetValueOut()) >= ASSETCHAINS_TIMELOCKGTE) || (nHeight >= 31680) && komodo_ac_block_subsidy(nHeight) >= ASSETCHAINS_TIMELOCKGTE) { CScriptID scriptHash; @@ -2045,7 +2047,7 @@ namespace Consensus { const COutPoint &prevout = tx.vin[i].prevout; const CCoins *coins = inputs.AccessCoins(prevout.hash); assert(coins); - + if (coins->IsCoinBase()) { // Ensure that coinbases are matured if (nSpendHeight - coins->nHeight < COINBASE_MATURITY) { @@ -2066,7 +2068,8 @@ namespace Consensus { // Disabled on regtest if (fCoinbaseEnforcedProtectionEnabled && consensusParams.fCoinbaseMustBeProtected && - !tx.vout.empty()) { + !tx.vout.empty() && + (strcmp(ASSETCHAINS_SYMBOL, "VRSC") != 0 || (nSpendHeight >= 12800 && coins->nHeight >= 12800))) { return state.Invalid( error("CheckInputs(): tried to spend coinbase with transparent outputs"), REJECT_INVALID, "bad-txns-coinbase-spend-has-transparent-outputs"); @@ -3138,13 +3141,18 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { return false; if (!fBare) { - // Resurrect mempool transactions from the disconnected block. - BOOST_FOREACH(const CTransaction &tx, block.vtx) { + // resurrect mempool transactions from the disconnected block. + for (int i = 0; i < block.vtx.size(); i++) + { // ignore validation errors in resurrected transactions + CTransaction &tx = block.vtx[i]; list removed; CValidationState stateDummy; - if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL)) + // don't keep staking or invalid transactions + if (tx.IsCoinBase() || ((i == (block.vtx.size() - 1)) && block.IsVerusPOSBlock()) || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL)) + { mempool.remove(tx, removed, true); + } } if (anchorBeforeDisconnect != anchorAfterDisconnect) { // The anchor may not change between block disconnects, @@ -3160,8 +3168,17 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { assert(pcoinsTip->GetAnchorAt(pcoinsTip->GetBestAnchor(), newTree)); // Let wallets know transactions went from 1-confirmed to // 0-confirmed or conflicted: - BOOST_FOREACH(const CTransaction &tx, block.vtx) { - SyncWithWallets(tx, NULL); + for (int i = 0; i < block.vtx.size(); i++) + { + CTransaction &tx = block.vtx[i]; + if ((i == (block.vtx.size() - 1) && block.IsVerusPOSBlock())) + { + EraseFromWallets(tx.GetHash()); + } + else + { + SyncWithWallets(tx, NULL); + } } // Update cached incremental witnesses //fprintf(stderr,"chaintip false\n"); @@ -3999,7 +4016,6 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn { const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1; const Consensus::Params& consensusParams = Params().GetConsensus(); - bool checkBlockOne = (nHeight == 1); // Check that all transactions are finalized BOOST_FOREACH(const CTransaction& tx, block.vtx) { @@ -4087,7 +4103,7 @@ bool AcceptBlockHeader(int32_t *futureblockp,const CBlockHeader& block, CValidat komodo_requestedhash = block.hashPrevBlock; komodo_requestedcount = 0; }*/ - LogPrintf("AcceptBlockHeader hashPrevBlock %s not found\n",block.hashPrevBlock.ToString().c_str()); + LogPrintf("AcceptBlockHeader %s\n hashPrevBlock %s not found\n", hash.ToString().c_str(), block.hashPrevBlock.ToString().c_str()); return(false); //return state.DoS(10, error("%s: prev block not found", __func__), 0, "bad-prevblk"); } @@ -4139,7 +4155,7 @@ bool AcceptBlock(int32_t *futureblockp,CBlock& block, CValidationState& state, C AssertLockHeld(cs_main); CBlockIndex *&pindex = *ppindex; - if (!AcceptBlockHeader(futureblockp,block, state, &pindex)) + if (!AcceptBlockHeader(futureblockp, block, state, &pindex)) { if ( *futureblockp == 0 ) { @@ -4343,7 +4359,7 @@ bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNo if ( 1 ) { // without the komodo_ensure call, it is quite possible to get a non-error but null pindex returned from AcceptBlockHeader. In a 2 node network, it will be a long time before that block is reprocessed. Even though restarting makes it rescan, it seems much better to keep the nodes in sync - komodo_ensure(pblock,hash); + komodo_ensure(pblock, hash); } bool ret = AcceptBlock(&futureblock,*pblock, state, &pindex, fRequested, dbp); if (pindex && pfrom) { @@ -5623,10 +5639,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, LogPrintf("dropmessagestest DROPPING RECV MESSAGE\n"); return true; } - - - - + if (strCommand == "version") { // Each connection can only send one version message @@ -6015,9 +6028,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (pindex) pindex = chainActive.Next(pindex); } - - // we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end - vector vHeaders; + + // we must use CNetworkBlockHeader, as CBlockHeader won't include the 0x00 nTx count at the end for compatibility + vector vHeaders; int nLimit = MAX_HEADERS_RESULTS; LogPrint("net", "getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString(), pfrom->id); //if ( pfrom->lasthdrsreq >= chainActive.Height()-MAX_HEADERS_RESULTS || pfrom->lasthdrsreq != (int32_t)(pindex ? pindex->nHeight : -1) )// no need to ever suppress this @@ -6025,6 +6038,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->lasthdrsreq = (int32_t)(pindex ? pindex->nHeight : -1); for (; pindex; pindex = chainActive.Next(pindex)) { + CBlockHeader h = pindex->GetBlockHeader(); + //printf("size.%i, solution size.%i\n", (int)sizeof(h), (int)h.nSolution.size()); + //printf("hash.%s prevhash.%s nonce.%s\n", h.GetHash().ToString().c_str(), h.hashPrevBlock.ToString().c_str(), h.nNonce.ToString().c_str()); vHeaders.push_back(pindex->GetBlockHeader()); if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop) break; @@ -6168,8 +6184,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, Misbehaving(pfrom->GetId(), nDoS); } } - - + else if (strCommand == "headers" && !fImporting && !fReindex) // Ignore headers received while importing { std::vector headers; @@ -6195,6 +6210,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CBlockIndex *pindexLast = NULL; BOOST_FOREACH(const CBlockHeader& header, headers) { + //printf("size.%i, solution size.%i\n", (int)sizeof(header), (int)header.nSolution.size()); + //printf("hash.%s prevhash.%s nonce.%s\n", header.GetHash().ToString().c_str(), header.hashPrevBlock.ToString().c_str(), header.nNonce.ToString().c_str()); + CValidationState state; if (pindexLast != NULL && header.hashPrevBlock != pindexLast->GetBlockHash()) { Misbehaving(pfrom->GetId(), 20); diff --git a/src/main.h b/src/main.h index 3a43b5fba..99babb874 100644 --- a/src/main.h +++ b/src/main.h @@ -751,7 +751,7 @@ private: public: CScriptCheck(): amount(0), ptxTo(0), nIn(0), nFlags(0), cacheStore(false), consensusBranchId(0), error(SCRIPT_ERR_UNKNOWN_ERROR) {} CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn, uint32_t consensusBranchIdIn, PrecomputedTransactionData* txdataIn) : - scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey), amount(txFromIn.vout[txToIn.vin[nInIn].prevout.n].nValue), + scriptPubKey(CCoinsViewCache::GetSpendFor(&txFromIn, txToIn.vin[nInIn])), amount(txFromIn.vout[txToIn.vin[nInIn].prevout.n].nValue), ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), consensusBranchId(consensusBranchIdIn), error(SCRIPT_ERR_UNKNOWN_ERROR), txdata(txdataIn) { } bool operator()(); diff --git a/src/metrics.cpp b/src/metrics.cpp index e10e5cf8d..39050f681 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -25,6 +25,7 @@ #include extern int64_t ASSETCHAINS_TIMELOCKGTE; +extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH; int64_t komodo_block_unlocktime(uint32_t nHeight); void AtomicTimer::start() @@ -74,8 +75,21 @@ double AtomicTimer::rate(const AtomicCounter& count) CCriticalSection cs_metrics; +double AtomicTimer::rate(const int64_t count) +{ + std::unique_lock lock(mtx); + LOCK(cs_metrics); + int64_t duration = total_time; + if (threads > 0) { + // Timer is running, so get the latest count + duration += GetTime() - start_time; + } + return duration > 0 ? (double)count / duration : 0; +} + boost::synchronized_value nNodeStartTime; boost::synchronized_value nNextRefresh; +int64_t nHashCount; AtomicCounter transactionsValidated; AtomicCounter ehSolverRuns; AtomicCounter solutionTargetChecks; @@ -109,7 +123,12 @@ int64_t GetUptime() double GetLocalSolPS() { - return miningTimer.rate(solutionTargetChecks); + if (ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH) + { + return miningTimer.rate(nHashCount); + } + else + return miningTimer.rate(solutionTargetChecks); } int EstimateNetHeightInner(int height, int64_t tipmediantime, diff --git a/src/metrics.h b/src/metrics.h index 65d88ce84..0fc03bf8a 100644 --- a/src/metrics.h +++ b/src/metrics.h @@ -8,6 +8,8 @@ #include #include +extern int64_t nHashCount; + struct AtomicCounter { std::atomic value; @@ -52,6 +54,8 @@ public: uint64_t threadCount(); double rate(const AtomicCounter& count); + double rate(const int64_t count); + }; extern AtomicCounter transactionsValidated; diff --git a/src/miner.cpp b/src/miner.cpp index 22d5d5a5b..53b69069e 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -107,11 +107,12 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, #include "komodo_defs.h" +extern CCriticalSection cs_metrics; extern int32_t ASSETCHAINS_SEED,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAIN_INIT,KOMODO_INITDONE,KOMODO_ON_DEMAND,KOMODO_INITDONE,KOMODO_PASSPORT_INITDONE; extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_STAKED; extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[]; extern const char *ASSETCHAINS_ALGORITHMS[]; -extern int32_t VERUS_MIN_STAKEAGE, ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH, ASSETCHAINS_LASTERA, ASSETCHAINS_LWMAPOS, ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[]; +extern int32_t VERUS_MIN_STAKEAGE, ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH, ASSETCHAINS_VERUSHASH, ASSETCHAINS_LASTERA, ASSETCHAINS_LWMAPOS, ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[]; extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; extern std::string NOTARY_PUBKEY; extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33]; @@ -127,11 +128,12 @@ int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_ int64_t komodo_block_unlocktime(uint32_t nHeight); uint64_t komodo_commission(const CBlock *block); int32_t komodo_staked(CPubKey &pubkey, CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig); -int32_t verus_staked(CPubKey &pubkey, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig); +int32_t verus_staked(CBlock *pBlock, CPubKey &pubkey, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig); int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33); -CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, bool isStake) +CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, bool isStake) { + CScript scriptPubKeyIn(_scriptPubKeyIn); uint64_t deposits; int32_t isrealtime,kmdheight; uint32_t blocktime; const CChainParams& chainparams = Params(); // Create new block std::unique_ptr pblocktemplate(new CBlockTemplate()); @@ -368,7 +370,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, bool isStake) //fprintf(stderr,"dont have inputs\n"); continue; } - CAmount nTxFees = view.GetValueIn(chainActive.Tip()->nHeight,&interest,tx,chainActive.Tip()->nTime)-tx.GetValueOut(); + CAmount nTxFees = view.GetValueIn(chainActive.LastTip()->nHeight,&interest,tx,chainActive.LastTip()->nTime)-tx.GetValueOut(); nTxSigOps += GetP2SHSigOpCount(tx, view); if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1) @@ -460,9 +462,13 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, bool isStake) { uint32_t nBitsPOS; arith_uint256 posHash; - siglen = verus_staked(key, txStaked, nBitsPOS, posHash, utxosig); + + siglen = verus_staked(pblock, key, txStaked, nBitsPOS, posHash, utxosig); blocktime = GetAdjustedTime(); - pblock->SetVerusPOSTarget(nBitsPOS); + + // change the scriptPubKeyIn to the same output script exactly as the staking transaction + if (siglen > 0) + scriptPubKeyIn = CScript(txStaked.vout[0].scriptPubKey); } else { @@ -479,7 +485,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, bool isStake) pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txStaked)); nFees += txfees; pblock->nTime = blocktime; - //printf("PoS ht.%d t%u\n",(int32_t)chainActive.Tip()->nHeight+1,blocktime); + //printf("PoS ht.%d t%u\n",(int32_t)chainActive.LastTip()->nHeight+1,blocktime); } else return(0); //fprintf(stderr,"no utxos eligible for staking\n"); } @@ -546,6 +552,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, bool isStake) // Fill in header pblock->hashPrevBlock = pindexPrev->GetBlockHash(); pblock->hashReserved = uint256(); + if ( ASSETCHAINS_SYMBOL[0] == 0 || ASSETCHAINS_STAKED == 0 || NOTARY_PUBKEY33[0] == 0 ) { UpdateTime(pblock, Params().GetConsensus(), pindexPrev); @@ -716,11 +723,11 @@ 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.Tip()->nHeight+1); // Found a solution { LOCK(cs_main); + LogPrintf("generated %s height.%d\n", FormatMoney(pblock->vtx[0].vout[0].nValue),chainActive.Tip()->nHeight+1); if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash()) { uint256 hash; int32_t i; @@ -756,7 +763,7 @@ static bool ProcessBlockFound(CBlock* pblock) // Process this block the same as if we had received it from another node CValidationState state; - if (!ProcessNewBlock(1,chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL)) + if (!ProcessNewBlock(1,chainActive.LastTip()->nHeight+1,state, NULL, pblock, true, NULL)) return error("KomodoMiner: ProcessNewBlock, block not accepted"); TrackMinedBlock(pblock->GetHash()); @@ -777,20 +784,38 @@ int32_t waitForPeers(const CChainParams &chainparams) { if (chainparams.MiningRequiresPeers()) { - do { - bool fvNodesEmpty; - { - LOCK(cs_vNodes); - fvNodesEmpty = vNodes.empty(); - } - if (!fvNodesEmpty ) - break; - MilliSleep(1000); - } while (true); + bool fvNodesEmpty; + { + LOCK(cs_vNodes); + fvNodesEmpty = vNodes.empty(); + } + if (fvNodesEmpty) + { + do { + MilliSleep(5000 + rand() % 5000); + { + LOCK(cs_vNodes); + fvNodesEmpty = vNodes.empty(); + } + } while (fvNodesEmpty); + MilliSleep(5000 + rand() % 5000); + } } } #ifdef ENABLE_WALLET +CBlockIndex *get_chainactive(int32_t height) +{ + if ( chainActive.Tip() != 0 ) + { + if ( height <= chainActive.Tip()->nHeight ) + return(chainActive[height]); + // else fprintf(stderr,"get_chainactive height %d > active.%d\n",height,chainActive.Tip()->nHeight); + } + //fprintf(stderr,"get_chainactive null chainActive.Tip() height %d\n",height); + return(0); +} + /* * A separate thread to stake, while the miner threads mine. */ @@ -817,22 +842,32 @@ void static VerusStaker(CWallet *pwallet) break; } - // try a nice clean peer connection to start - waitForPeers(chainparams); - sleep(5); - CBlockIndex *curTip = chainActive.Tip(), *lastTip; - do { - lastTip = curTip; - printf("Verifying block height %d \n", lastTip->nHeight); - MilliSleep(3000 + rand() % 1900); - curTip = chainActive.Tip(); - } while (curTip != lastTip); - SetThreadPriority(THREAD_PRIORITY_LOWEST); + // try a nice clean peer connection to start + waitForPeers(chainparams); + // try a nice clean peer connection to start + waitForPeers(chainparams); + CBlockIndex* pindexPrev, *pindexCur; + do { + { + LOCK(cs_main); + pindexPrev = chainActive.Tip(); + } + MilliSleep(5000 + rand() % 5000); + { + LOCK(cs_main); + pindexCur = chainActive.Tip(); + } + } while (pindexPrev != pindexCur); + sleep(5); - printf("Staking height %d for %s\n", chainActive.Tip()->nHeight + 1, ASSETCHAINS_SYMBOL); - //fprintf(stderr,"Staking height %d for %s\n", chainActive.Tip()->nHeight + 1, ASSETCHAINS_SYMBOL); + + { + LOCK(cs_main); + printf("Staking height %d for %s\n", chainActive.Tip()->nHeight + 1, ASSETCHAINS_SYMBOL); + //fprintf(stderr,"Staking height %d for %s\n", chainActive.Tip()->nHeight + 1, ASSETCHAINS_SYMBOL); + } miningTimer.start(); @@ -845,7 +880,7 @@ void static VerusStaker(CWallet *pwallet) // Create new block unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); - CBlockIndex* pindexPrev = chainActive.Tip(); + CBlockIndex* pindexPrev = chainActive.LastTip(); if ( Mining_height != pindexPrev->nHeight+1 ) { Mining_height = pindexPrev->nHeight+1; @@ -863,8 +898,8 @@ void static VerusStaker(CWallet *pwallet) if ( ptr == 0 ) { // wait to try another staking block until after the tip moves again - while ( chainActive.Tip() == pindexPrev ) - sleep(5); + while ( chainActive.LastTip() == pindexPrev ) + sleep(1); continue; } @@ -881,7 +916,6 @@ void static VerusStaker(CWallet *pwallet) return; } - CBlock *pblock = &pblocktemplate->block; LogPrintf("Staking with %u transactions in block (%u bytes)\n", pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION)); // @@ -889,12 +923,13 @@ void static VerusStaker(CWallet *pwallet) // int64_t nStart = GetTime(); + // take up the necessary space for alignment + pblock->nSolution = solnPlaceholder; + // we don't use this, but IncrementExtraNonce is the function that builds the merkle tree unsigned int nExtraNonce = 0; IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); - pblock->nSolution = solnPlaceholder; - if (vNodes.empty() && chainparams.MiningRequiresPeers()) { if ( Mining_height > ASSETCHAINS_MINHEIGHT ) @@ -910,9 +945,9 @@ void static VerusStaker(CWallet *pwallet) continue; } - if ( pindexPrev != chainActive.Tip() ) + if ( pindexPrev != chainActive.LastTip() ) { - printf("Block %d added to chain\n", chainActive.Tip()->nHeight); + printf("Block %d added to chain\n", chainActive.LastTip()->nHeight); MilliSleep(250); continue; } @@ -924,27 +959,32 @@ void static VerusStaker(CWallet *pwallet) uint256 hashTarget = ArithToUint256(arith_uint256().SetCompact(pblock->nBits)); - LogPrintf("Using %s algorithm:\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]); - LogPrintf("Staked block found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex()); - printf("Found block %d \n", Mining_height ); - printf("staking reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL); - printf(" hash: %s \ntarget: %s\n", pblock->GetHash().GetHex().c_str(), hashTarget.GetHex().c_str()); - if (unlockTime > Mining_height && subsidy >= ASSETCHAINS_TIMELOCKGTE) - printf("- timelocked until block %i\n", unlockTime); - else - printf("\n"); - pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus()); UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); ProcessBlockFound(pblock, *pwallet, reservekey); - sleep(3); + LogPrintf("Using %s algorithm:\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]); + LogPrintf("Staked block found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex()); + printf("Found block %d \n", Mining_height ); + printf("staking reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL); + arith_uint256 post; + post.SetCompact(pblock->GetVerusPOSTarget()); + pindexPrev = get_chainactive(Mining_height - 100); + printf(" hash: %s \ntarget: %s\n", + CTransaction::_GetVerusPOSHash(&(pblock->nNonce), pblock->vtx[pblock->vtx.size()-1].vin[0].prevout.hash, 0, Mining_height, pindexPrev->GetBlockHeader().GetVerusEntropyHash(Mining_height - 100), pblock->vtx[pblock->vtx.size()-1].vout[0].nValue).GetHex().c_str(), ArithToUint256(post).GetHex().c_str()); + if (unlockTime > Mining_height && subsidy >= ASSETCHAINS_TIMELOCKGTE) + printf("- timelocked until block %i\n", unlockTime); + else + printf("\n"); + // Check for stop or if block needs to be rebuilt boost::this_thread::interruption_point(); SetThreadPriority(THREAD_PRIORITY_LOWEST); + sleep(5); + // In regression test mode, stop mining after a block is found. if (chainparams.MineBlocksOnDemand()) { throw boost::thread_interrupted(); @@ -993,42 +1033,57 @@ void static BitcoinMiner_noeq() break; } - // try a nice clean peer connection to start - waitForPeers(chainparams); - sleep(5); - CBlockIndex *curTip = chainActive.Tip(), *lastTip; - do { - lastTip = curTip; - printf("Verifying block height %d \n", lastTip->nHeight); - MilliSleep(3000 + rand() % 1900); - curTip = chainActive.Tip(); - } while (curTip != lastTip); - SetThreadPriority(THREAD_PRIORITY_LOWEST); - sleep(5); - printf("Mining height %d\n", chainActive.Tip()->nHeight + 1); + // try a nice clean peer connection to start + waitForPeers(chainparams); + CBlockIndex *pindexPrev, *pindexCur; + do { + pindexPrev = chainActive.LastTip(); + MilliSleep(5000 + rand() % 5000); + pindexCur = chainActive.LastTip(); + } while (pindexPrev != pindexCur); + + // this will not stop printing more than once in all cases, but it will allow us to print in all cases + // and print duplicates rarely without having to synchronize + static CBlockIndex *lastChainTipPrinted; miningTimer.start(); try { - fprintf(stderr,"Mining %s with %s\n", ASSETCHAINS_SYMBOL, ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]); + printf("Mining %s with %s\n", ASSETCHAINS_SYMBOL, ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]); while (true) { miningTimer.stop(); waitForPeers(chainparams); - miningTimer.start(); + + pindexPrev = chainActive.LastTip(); + sleep(1); + + // prevent forking on startup before the diff algorithm kicks in + if (pindexPrev->nHeight < 50 || pindexPrev != chainActive.LastTip()) + { + do { + pindexPrev = chainActive.LastTip(); + MilliSleep(5000 + rand() % 5000); + } while (pindexPrev != chainActive.LastTip()); + } // Create new block unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); - CBlockIndex* pindexPrev = chainActive.Tip(); if ( Mining_height != pindexPrev->nHeight+1 ) { Mining_height = pindexPrev->nHeight+1; Mining_start = (uint32_t)time(NULL); } - //fprintf(stderr,"%s create new block ht.%d\n",ASSETCHAINS_SYMBOL,Mining_height); + if (lastChainTipPrinted != pindexPrev) + { + printf("Mining height %d\n", Mining_height); + lastChainTipPrinted = pindexPrev; + } + + miningTimer.start(); #ifdef ENABLE_WALLET CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey); @@ -1042,6 +1097,7 @@ void static BitcoinMiner_noeq() fprintf(stderr,"created illegal block, retry\n"); continue; } + unique_ptr pblocktemplate(ptr); if (!pblocktemplate.get()) { @@ -1084,9 +1140,13 @@ void static BitcoinMiner_noeq() Mining_start = 0; - if ( pindexPrev != chainActive.Tip() ) + if ( pindexPrev != chainActive.LastTip() ) { - printf("Block %d added to chain\n", chainActive.Tip()->nHeight); + if (lastChainTipPrinted != chainActive.LastTip()) + { + lastChainTipPrinted = chainActive.LastTip(); + printf("Block %d added to chain\n", lastChainTipPrinted->nHeight); + } MilliSleep(250); continue; } @@ -1102,18 +1162,36 @@ void static BitcoinMiner_noeq() while (true) { - // for speed check multiples at a time - for (int i = 0; i < ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO]; i++) + arith_uint256 arNonce = UintToArith256(pblock->nNonce); + + CVerusHashWriter ss = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION); + ss << *((CBlockHeader *)pblock); + int64_t *extraPtr = ss.xI64p(); + CVerusHash &vh = ss.GetState(); + uint256 hashResult = uint256(); + vh.ClearExtra(); + int64_t i, count = ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] + 1; + int64_t hashesToGo = ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO]; + + // for speed check NONCEMASK at a time + for (i = 0; i < count; i++) { - solutionTargetChecks.increment(); + *extraPtr = i; + vh.ExtraHash((unsigned char *)&hashResult); - // Update nNonce and nTime - pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1); - - if ( UintToArith256(pblock->GetHash()) <= hashTarget ) + if ( UintToArith256(hashResult) <= hashTarget ) { + if (pblock->nSolution.size() != 1344) + { + LogPrintf("ERROR: Block solution is not 1344 bytes as it should be"); + sleep(5); + break; + } + SetThreadPriority(THREAD_PRIORITY_NORMAL); + *((int64_t *)&(pblock->nSolution.data()[pblock->nSolution.size() - 15])) = i; + int32_t unlockTime = komodo_block_unlocktime(Mining_height); int64_t subsidy = (int64_t)(pblock->vtx[0].vout[0].nValue); @@ -1126,29 +1204,35 @@ void static BitcoinMiner_noeq() printf("- timelocked until block %i\n", unlockTime); else printf("\n"); - #ifdef ENABLE_WALLET ProcessBlockFound(pblock, *pwallet, reservekey); #else ProcessBlockFound(pblock)); #endif SetThreadPriority(THREAD_PRIORITY_LOWEST); - - // In regression test mode, stop mining after a block is found. - if (chainparams.MineBlocksOnDemand()) { - throw boost::thread_interrupted(); - } break; } - else + // check periodically if we're stale + if (!--hashesToGo) { - if ((UintToArith256(pblock->nNonce) & mask) == mask) + if ( pindexPrev != chainActive.LastTip() ) { + if (lastChainTipPrinted != chainActive.LastTip()) + { + lastChainTipPrinted = chainActive.LastTip(); + printf("Block %d added to chain\n", lastChainTipPrinted->nHeight); + } break; } + hashesToGo = ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO]; } } + { + LOCK(cs_metrics); + nHashCount += i; + } + // Check for stop or if block needs to be rebuilt boost::this_thread::interruption_point(); @@ -1161,31 +1245,28 @@ void static BitcoinMiner_noeq() } } - if ((UintToArith256(pblock->nNonce) & mask) == mask) - { - fprintf(stderr,"%lu mega hashes complete - working\n", (ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] + 1) / 1048576); - break; - } - if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60) { fprintf(stderr,"timeout, retrying\n"); break; } - if ( pindexPrev != chainActive.Tip() ) + if ( pindexPrev != chainActive.LastTip() ) { - printf("Block %d added to chain\n", chainActive.Tip()->nHeight); + if (lastChainTipPrinted != chainActive.LastTip()) + { + lastChainTipPrinted = chainActive.LastTip(); + printf("Block %d added to chain\n", lastChainTipPrinted->nHeight); + } break; } - pblock->nBits = savebits; - UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); - if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks) - { - // Changing pblock->nTime can change work required on testnet: - hashTarget.SetCompact(pblock->nBits); - } +#ifdef _WIN32 + printf("%llu mega hashes complete - working\n", (ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] + 1) / 1048576); +#else + printf("%lu mega hashes complete - working\n", (ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] + 1) / 1048576); +#endif + break; } } } diff --git a/src/pow.cpp b/src/pow.cpp index 70319ca34..26d432da8 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -22,7 +22,8 @@ uint32_t komodo_chainactive_timestamp(); extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH; -extern int32_t VERUS_BLOCK_POSUNITS; +extern char ASSETCHAINS_SYMBOL[65]; +extern int32_t VERUS_BLOCK_POSUNITS, VERUS_CONSECUTIVE_POS_THRESHOLD, VERUS_NOPOS_THRESHHOLD; unsigned int lwmaGetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params); unsigned int lwmaCalculateNextWorkRequired(const CBlockIndex* pindexLast, const Consensus::Params& params); @@ -157,55 +158,142 @@ bool DoesHashQualify(const CBlockIndex *pbindex) // the goal is to keep POS at a solve time that is a ratio of block time units. the low resolution makes a stable solution more challenging // and requires that the averaging window be quite long. -unsigned int lwmaGetNextPOSRequired(const CBlockIndex* pindexLast, const Consensus::Params& params) +uint32_t lwmaGetNextPOSRequired(const CBlockIndex* pindexLast, const Consensus::Params& params) { arith_uint256 nextTarget {0}, sumTarget {0}, bnTmp, bnLimit; bnLimit = UintToArith256(params.posLimit); - unsigned int nProofOfStakeLimit = bnLimit.GetCompact(); + uint32_t nProofOfStakeLimit = bnLimit.GetCompact(); + int64_t t = 0, solvetime = 0; + int64_t k = params.nLwmaPOSAjustedWeight; + int64_t N = params.nPOSAveragingWindow; + + struct solveSequence { + int64_t solveTime; + bool consecutive; + uint32_t nBits; + solveSequence() + { + consecutive = 0; + solveTime = 0; + nBits = 0; + } + }; // Find the first block in the averaging interval as we total the linearly weighted average // of POS solve times const CBlockIndex* pindexFirst = pindexLast; - const CBlockIndex* pindexNext; - int64_t t = 0, solvetime = 0, k = params.nLwmaPOSAjustedWeight, N = params.nPOSAveragingWindow; - - for (int i = 0, j = N - 1; pindexFirst && i < N; i++, j--) { - pindexNext = pindexFirst; - // we measure our solve time in passing of blocks, where one bock == VERUS_BLOCK_POSUNITS units - for (int x = 0; x < params.nPOSAveragingWindow; x++) - { - solvetime += VERUS_BLOCK_POSUNITS; - pindexFirst = pindexFirst->pprev; - // in this loop, unqualified blocks are assumed POS - if (!pindexFirst || !DoesHashQualify(pindexFirst)) - break; - } + // we need to make sure we have a starting nBits reference, which is either the last POS block, or the default + // if we have had no POS block in the threshold number of blocks, we must return the default, otherwise, we'll now have + // a starting point + uint32_t nBits = nProofOfStakeLimit; + for (int64_t i = 0; i < VERUS_NOPOS_THRESHHOLD; i++) + { if (!pindexFirst) - break; + return nProofOfStakeLimit; + CBlockHeader hdr = pindexFirst->GetBlockHeader(); + + if (hdr.IsVerusPOSBlock()) + { + nBits = hdr.GetVerusPOSTarget(); + break; + } + pindexFirst = pindexFirst->pprev; + } + + pindexFirst = pindexLast; + std::vector idx = std::vector(); + idx.resize(N); + + for (int64_t i = N - 1; i >= 0; i--) + { + // we measure our solve time in passing of blocks, where one bock == VERUS_BLOCK_POSUNITS units + // consecutive blocks in either direction have their solve times exponentially multiplied or divided by power of 2 + int x; + for (x = 0; x < VERUS_CONSECUTIVE_POS_THRESHOLD; x++) + { + pindexFirst = pindexFirst->pprev; + + if (!pindexFirst) + return nProofOfStakeLimit; + + CBlockHeader hdr = pindexFirst->GetBlockHeader(); + if (hdr.IsVerusPOSBlock()) + { + nBits = hdr.GetVerusPOSTarget(); + break; + } + } + + if (x) + { + idx[i].consecutive = false; + if (!memcmp(ASSETCHAINS_SYMBOL, "VRSC", 4) && pindexLast->nHeight < 67680) + { + idx[i].solveTime = VERUS_BLOCK_POSUNITS * (x + 1); + } + else + { + int64_t lastSolveTime = 0; + idx[i].solveTime = VERUS_BLOCK_POSUNITS; + for (int64_t j = 0; j < x; j++) + { + lastSolveTime = VERUS_BLOCK_POSUNITS + (lastSolveTime >> 1); + idx[i].solveTime += lastSolveTime; + } + } + idx[i].nBits = nBits; + } + else + { + idx[i].consecutive = true; + idx[i].nBits = nBits; + // go forward and halve the minimum solve time for all consecutive blocks in this run, to get here, our last block is POS, + // and if there is no POS block in front of it, it gets the normal solve time of one block + uint32_t st = VERUS_BLOCK_POSUNITS; + for (int64_t j = i; j < N; j++) + { + if (idx[j].consecutive == true) + { + idx[j].solveTime = st; + if ((j - i) >= VERUS_CONSECUTIVE_POS_THRESHOLD) + { + // if this is real time, return zero + if (j == (N - 1)) + { + // target of 0 (virtually impossible), if we hit max consecutive POS blocks + nextTarget.SetCompact(0); + return nextTarget.GetCompact(); + } + } + st >>= 1; + } + else + break; + } + } + } + + for (int64_t i = N - 1; i >= 0; i--) + { // weighted sum - t += solvetime * j; + t += idx[i].solveTime * i; // Target sum divided by a factor, (k N^2). // The factor is a part of the final equation. However we divide // here to avoid potential overflow. - bnTmp.SetCompact(pindexNext->nBits); // TODO(miketout): this must be POS nBits + bnTmp.SetCompact(idx[i].nBits); sumTarget += bnTmp / (k * N * N); } - // Check we have enough blocks - if (!pindexFirst) - return nProofOfStakeLimit; - // Keep t reasonable in case strange solvetimes occurred. if (t < N * k / 3) t = N * k / 3; - bnTmp = bnLimit; nextTarget = t * sumTarget; - if (nextTarget > bnTmp) - nextTarget = bnTmp; + if (nextTarget > bnLimit) + nextTarget = bnLimit; return nextTarget.GetCompact(); } @@ -323,7 +411,7 @@ bool CheckProofOfWork(const CBlockHeader &blkHeader, uint8_t *pubkey33, int32_t return error("CheckProofOfWork(): nBits below minimum work"); // Check proof of work matches claimed amount - if ( UintToArith256(hash = blkHeader.GetHash()) > bnTarget && !blkHeader.isVerusPOSBlock() ) + if ( UintToArith256(hash = blkHeader.GetHash()) > bnTarget && !blkHeader.IsVerusPOSBlock() ) { if ( KOMODO_LOADINGBLOCKS != 0 ) return true; @@ -357,7 +445,6 @@ bool CheckProofOfWork(const CBlockHeader &blkHeader, uint8_t *pubkey33, int32_t return true; } - arith_uint256 GetBlockProof(const CBlockIndex& block) { arith_uint256 bnTarget; @@ -365,8 +452,6 @@ arith_uint256 GetBlockProof(const CBlockIndex& block) bool fOverflow; bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow); - // TODO(miketout): proof of stake blocks must be marked as having the minimum POW in this context - if (fNegative || fOverflow || bnTarget == 0) return 0; // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256 diff --git a/src/pow/tromp/equi_miner.h b/src/pow/tromp/equi_miner.h index ae527827a..d53d0d8aa 100644 --- a/src/pow/tromp/equi_miner.h +++ b/src/pow/tromp/equi_miner.h @@ -25,7 +25,13 @@ #include typedef uint16_t u16; +#ifdef _WIN32 +typedef unsigned long long u64; +#elif __linux__ typedef uint64_t u64; +#else +typedef unsigned long u64; +#endif #ifdef EQUIHASH_TROMP_ATOMIC #include diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index 58164ad8a..a638131a0 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -10,6 +10,8 @@ #include "utilstrencodings.h" #include "crypto/common.h" +extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH; + // default hash algorithm for block uint256 (CBlockHeader::*CBlockHeader::hashFunction)() const = &CBlockHeader::GetSHA256DHash; @@ -20,13 +22,19 @@ uint256 CBlockHeader::GetSHA256DHash() const uint256 CBlockHeader::GetVerusHash() const { - if (hashPrevBlock == uint256()) + if (hashPrevBlock.IsNull()) // always use SHA256D for genesis block return SerializeHash(*this); else return SerializeVerusHash(*this); } +uint256 CBlockHeader::GetVerusV2Hash() const +{ + // no check for genesis block and use the optimized hash + return SerializeVerusHashV2(*this); +} + void CBlockHeader::SetSHA256DHash() { CBlockHeader::hashFunction = &CBlockHeader::GetSHA256DHash; @@ -37,6 +45,48 @@ void CBlockHeader::SetVerusHash() CBlockHeader::hashFunction = &CBlockHeader::GetVerusHash; } +// returns false if unable to fast calculate the VerusPOSHash from the header. it can still be calculated from the block +// in that case. the only difference between this and the POS hash for the contest is that it is not divided by the value out +// this is used as a source of entropy +bool CBlockHeader::GetRawVerusPOSHash(uint256 &value, int32_t nHeight) const +{ + // if below the required height or no storage space in the solution, we can't get + // a cached txid value to calculate the POSHash from the header + if (!(CPOSNonce::NewNonceActive(nHeight) && IsVerusPOSBlock())) + return false; + + // if we can calculate, this assumes the protocol that the POSHash calculation is: + // hashWriter << ASSETCHAINS_MAGIC; + // hashWriter << nNonce; (nNonce is: + // (high 128 bits == low 128 bits of verus hash of low 128 bits of nonce) + // (low 32 bits == compact PoS difficult) + // (mid 96 bits == low 96 bits of HASH(pastHash, txid, voutnum) + // pastHash is hash of height - 100, either PoW hash of block or PoS hash, if new PoS + // ) + // hashWriter << height; + // return hashWriter.GetHash(); + CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION); + + hashWriter << ASSETCHAINS_MAGIC; + hashWriter << nNonce; + hashWriter << nHeight; + value = hashWriter.GetHash(); + return true; +} + +// depending on the height of the block and its type, this returns the POS hash or the POW hash +uint256 CBlockHeader::GetVerusEntropyHash(int32_t height) const +{ + uint256 retVal; + // if we qualify as PoW, use PoW hash, regardless of PoS state + if (GetRawVerusPOSHash(retVal, height)) + { + // POS hash + return retVal; + } + return GetHash(); +} + uint256 CBlock::BuildMerkleTree(bool* fMutated) const { /* WARNING! If you're reading this because you're learning about crypto diff --git a/src/primitives/block.h b/src/primitives/block.h index 8dbcd7d5d..12bffbeab 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -7,6 +7,7 @@ #define BITCOIN_PRIMITIVES_BLOCK_H #include "primitives/transaction.h" +#include "primitives/nonce.h" #include "serialize.h" #include "uint256.h" #include "arith_uint256.h" @@ -25,7 +26,6 @@ public: static const size_t HEADER_SIZE=4+32+32+32+4+4+32; // excluding Equihash solution static const int32_t CURRENT_VERSION=4; static uint256 (CBlockHeader::*hashFunction)() const; - static void SetHashAlgo(); int32_t nVersion; @@ -34,7 +34,7 @@ public: uint256 hashReserved; uint32_t nTime; uint32_t nBits; - uint256 nNonce; + CPOSNonce nNonce; std::vector nSolution; CBlockHeader() @@ -85,12 +85,17 @@ public: uint256 GetVerusHash() const; static void SetVerusHash(); + bool GetRawVerusPOSHash(uint256 &value, int32_t nHeight) const; + uint256 GetVerusEntropyHash(int32_t nHeight) const; + + uint256 GetVerusV2Hash() const; + int64_t GetBlockTime() const { return (int64_t)nTime; } - int32_t GetVerusPOSTarget() const + uint32_t GetVerusPOSTarget() const { uint32_t nBits = 0; @@ -102,31 +107,66 @@ public: return nBits; } - bool isVerusPOSBlock() const + bool IsVerusPOSBlock() const { - arith_uint256 arNonce = UintToArith256(nNonce); - arith_uint256 tmpNonce = ((arNonce << 128) >> 128); - CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION); - hashWriter << ArithToUint256(tmpNonce); - return (nNonce == ArithToUint256(UintToArith256(hashWriter.GetHash()) << 128 | tmpNonce)); + return nNonce.IsPOSNonce(); } - void SetVerusPOSTarget(int32_t nBits) + void SetVerusPOSTarget(uint32_t nBits) { CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION); - uint256 hash; - arith_uint256 tmpNonce; arith_uint256 arNonce = UintToArith256(nNonce); - arNonce = ((arNonce >> 32) << 32) | nBits; - tmpNonce = ((arNonce << 128) >> 128); - hashWriter << ArithToUint256(tmpNonce); + // printf("before svpt: %s\n", ArithToUint256(arNonce).GetHex().c_str()); - nNonce = ArithToUint256(UintToArith256(hashWriter.GetHash()) << 128 | tmpNonce); + arNonce = (arNonce & CPOSNonce::entropyMask) | nBits; + + // printf("after clear: %s\n", ArithToUint256(arNonce).GetHex().c_str()); + + hashWriter << ArithToUint256(arNonce); + nNonce = CPOSNonce(ArithToUint256(UintToArith256(hashWriter.GetHash()) << 128 | arNonce)); + + // printf(" after svpt: %s\n", nNonce.GetHex().c_str()); } }; +// this class is used to address the type mismatch that existed between nodes, where block headers +// were being serialized by senders as CBlock and deserialized as CBlockHeader + an assumed extra +// compact value. although it was working, I made this because it did break, and makes the connection +// between CBlock and CBlockHeader more brittle. +// by using this intentionally specified class instead, we remove an instability in the code that could break +// due to unrelated changes, but stay compatible with the old method. +class CNetworkBlockHeader : public CBlockHeader +{ + public: + std::vector compatVec; + + CNetworkBlockHeader() : CBlockHeader() + { + SetNull(); + } + + CNetworkBlockHeader(const CBlockHeader &header) + { + SetNull(); + *((CBlockHeader*)this) = header; + } + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(*(CBlockHeader*)this); + READWRITE(compatVec); + } + + void SetNull() + { + CBlockHeader::SetNull(); + compatVec.clear(); + } +}; class CBlock : public CBlockHeader { @@ -145,6 +185,7 @@ public: CBlock(const CBlockHeader &header) { SetNull(); + *((CBlockHeader*)this) = header; } ADD_SERIALIZE_METHODS; diff --git a/src/primitives/nonce.cpp b/src/primitives/nonce.cpp new file mode 100644 index 000000000..6ff258174 --- /dev/null +++ b/src/primitives/nonce.cpp @@ -0,0 +1,75 @@ +// Copyright (c) 2018 Michael Toutonghi +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "hash.h" +#include "nonce.h" +#include + +extern char ASSETCHAINS_SYMBOL[65]; + +arith_uint256 CPOSNonce::entropyMask = UintToArith256(uint256S("00000000000000000000000000000000ffffffffffffffffffffffff00000000")); +arith_uint256 CPOSNonce::posDiffMask = UintToArith256(uint256S("00000000000000000000000000000000000000000000000000000000ffffffff")); + +bool CPOSNonce::NewPOSActive(int32_t height) +{ + if ((strcmp(ASSETCHAINS_SYMBOL, "VRSC") == 0) && (height < (96480 + 100))) + return false; + else if ((strcmp(ASSETCHAINS_SYMBOL, "VRSCTEST") == 0) && (height < (1000 + 100))) + return false; + else + return true; +} + +bool CPOSNonce::NewNonceActive(int32_t height) +{ + if ((strcmp(ASSETCHAINS_SYMBOL, "VRSC") == 0) && (height < 96480)) + return false; + else if ((strcmp(ASSETCHAINS_SYMBOL, "VRSCTEST") == 0) && (height < 1000)) + return false; + else + return true; +} + +void CPOSNonce::SetPOSEntropy(const uint256 &pastHash, uint256 txid, int32_t voutNum) +{ + // get low 96 bits of past hash and put it in top 96 bits of low 128 bits of nonce + CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION); + + // first hash the pastHash, txid, and voutNum, to create a combined 96 bits, which will be used in the nonce + hashWriter << pastHash; + hashWriter << txid; + hashWriter << voutNum; + + arith_uint256 arNonce = (UintToArith256(*this) & posDiffMask) | + (UintToArith256(hashWriter.GetHash()) & entropyMask); + + // printf("before %s\n", ArithToUint256(arNonce).GetHex().c_str()); + + hashWriter.Reset(); + hashWriter << ArithToUint256(arNonce); + + *this = CPOSNonce(ArithToUint256((UintToArith256(hashWriter.GetHash()) << 128) | arNonce)); + + // printf("after %s\n", this->GetHex().c_str()); +} + +bool CPOSNonce::CheckPOSEntropy(const uint256 &pastHash, uint256 txid, int32_t voutNum) +{ + // get low 96 bits of past hash and put it in top 96 bits of low 128 bits of nonce + CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION); + + // first hash the pastHash, txid, and voutNum, to create a combined 96 bits, which will be used in the nonce + hashWriter << pastHash; + hashWriter << txid; + hashWriter << voutNum; + + arith_uint256 arNonce = (UintToArith256(*this) & posDiffMask) | + (UintToArith256(hashWriter.GetHash()) & entropyMask); + + hashWriter.Reset(); + hashWriter << ArithToUint256(arNonce); + + return UintToArith256(*this) == (UintToArith256(hashWriter.GetHash()) << 128 | arNonce); +} + diff --git a/src/primitives/nonce.h b/src/primitives/nonce.h new file mode 100644 index 000000000..a3da4b6b5 --- /dev/null +++ b/src/primitives/nonce.h @@ -0,0 +1,64 @@ +// Copyright (c) 2018 Michael Toutonghi +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_PRIMITIVES_NONCE_H +#define BITCOIN_PRIMITIVES_NONCE_H + +#include "serialize.h" +#include "uint256.h" +#include "arith_uint256.h" + + +/** For POS blocks, the nNonce of a block header holds the entropy source for the POS contest + * in the latest VerusHash protocol + * */ +class CPOSNonce : public uint256 +{ +public: + static bool NewPOSActive(int32_t height); + static bool NewNonceActive(int32_t height); + + static arith_uint256 entropyMask; + static arith_uint256 posDiffMask; + + CPOSNonce() : uint256() { } + CPOSNonce(const base_blob<256> &b) : uint256(b) { } + CPOSNonce(const std::vector &vch) : uint256(vch) { } + + int32_t GetPOSTarget() const + { + uint32_t nBits = 0; + + for (const unsigned char *p = begin() + 3; p >= begin(); p--) + { + nBits <<= 8; + nBits += *p; + } + return nBits; + } + + bool IsPOSNonce() const + { + arith_uint256 arNonce = UintToArith256(*this); + arith_uint256 tmpNonce = ((arNonce << 128) >> 128); + CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION); + hashWriter << ArithToUint256(tmpNonce); + return (*this == ArithToUint256(UintToArith256(hashWriter.GetHash()) << 128 | tmpNonce)); + } + + void SetPOSTarget(uint32_t nBits) + { + CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION); + + arith_uint256 arNonce = (UintToArith256(*this) & entropyMask) | nBits; + hashWriter << ArithToUint256(arNonce); + + (uint256 &)(*this) = ArithToUint256(UintToArith256(hashWriter.GetHash()) << 128 | arNonce); + } + + void SetPOSEntropy(const uint256 &pastHash, uint256 txid, int32_t voutNum); + bool CheckPOSEntropy(const uint256 &pastHash, uint256 txid, int32_t voutNum); +}; + +#endif // BITCOIN_PRIMITIVES_NONCE_H diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index d6d7051cf..852aa4181 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -14,6 +14,7 @@ #include "arith_uint256.h" #include "consensus/consensus.h" #include "hash.h" +#include "nonce.h" #ifndef __APPLE__ #include @@ -474,25 +475,39 @@ public: } // verus hash will be the same for a given txid, output number, block height, and blockhash of 100 blocks past - static uint256 _GetVerusPOSHash(const uint256 &txid, int32_t voutNum, int32_t height, const uint256 &pastHash, int64_t value) + static uint256 _GetVerusPOSHash(CPOSNonce *pNonce, const uint256 &txid, int32_t voutNum, int32_t height, const uint256 &pastHash, int64_t value) { - CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION); + pNonce->SetPOSEntropy(pastHash, txid, voutNum); + CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION); hashWriter << ASSETCHAINS_MAGIC; - hashWriter << pastHash; - hashWriter << height; - hashWriter << txid; - hashWriter << voutNum; - return hashWriter.GetHash(); + + // we only use the new style of POS hash after changeover and 100 blocks of enforced proper nonce updating + if (CPOSNonce::NewPOSActive(height)) + { + hashWriter << *pNonce; + hashWriter << height; + return ArithToUint256(UintToArith256(hashWriter.GetHash()) / value); + } + else + { + hashWriter << pastHash; + hashWriter << height; + hashWriter << txid; + hashWriter << voutNum; + return ArithToUint256(UintToArith256(hashWriter.GetHash()) / value); + } } - uint256 GetVerusPOSHash(int32_t voutNum, int32_t height, const uint256 &pastHash) const + // Nonce is modified to include the transaction information + uint256 GetVerusPOSHash(CPOSNonce *pNonce, int32_t voutNum, int32_t height, const uint256 &pastHash) const { uint256 txid = GetHash(); + if (voutNum >= vout.size()) return uint256S("ff0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"); - return ArithToUint256(UintToArith256(_GetVerusPOSHash(txid, voutNum, height, pastHash, (uint64_t)vout[voutNum].nValue)) / vout[voutNum].nValue); + return _GetVerusPOSHash(pNonce, txid, voutNum, height, pastHash, (uint64_t)vout[voutNum].nValue); } std::string ToString() const; diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index d9cc072e5..717c57aef 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -268,6 +268,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx result.push_back(Pair("difficulty", GetDifficulty(blockindex))); result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); result.push_back(Pair("anchor", blockindex->hashAnchorEnd.GetHex())); + result.push_back(Pair("blocktype", block.IsVerusPOSBlock() ? "minted" : "mined")); UniValue valuePools(UniValue::VARR); valuePools.push_back(ValuePoolDesc("sprout", blockindex->nChainSproutValue, blockindex->nSproutValue)); diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index c9bbd967d..d80996b8b 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -32,7 +32,7 @@ using namespace std; -extern int32_t ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH; +extern int32_t ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH, ASSETCHAINS_LWMAPOS; /** * Return average network hashes per second based on the last 'lookup' blocks, @@ -320,7 +320,7 @@ UniValue setgenerate(const UniValue& params, bool fHelp) if (params.size() > 1) { nGenProcLimit = params[1].get_int(); - if (nGenProcLimit == 0) + if (ASSETCHAINS_LWMAPOS == 0 && nGenProcLimit == 0) fGenerate = false; } @@ -375,12 +375,12 @@ UniValue getmininginfo(const UniValue& params, bool fHelp) obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1))); if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH) { - obj.push_back(Pair("localsolps" , getlocalsolps(params, false))); - obj.push_back(Pair("networksolps", getnetworksolps(params, false))); + obj.push_back(Pair("localsolps" , getlocalsolps(params, false))); + obj.push_back(Pair("networksolps", getnetworksolps(params, false))); } else { - obj.push_back(Pair("localhashps" , getlocalsolps(params, false))); + obj.push_back(Pair("localhashps" , GetBoolArg("-gen", false) ? getlocalsolps(params, false) : (double)0.0)); } obj.push_back(Pair("networkhashps", getnetworksolps(params, false))); obj.push_back(Pair("pooledtx", (uint64_t)mempool.size())); diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index bbc87871b..419ee382a 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -204,7 +204,7 @@ UniValue getinfo(const UniValue& params, bool fHelp) if ( ASSETCHAINS_STAKED != 0 ) obj.push_back(Pair("staked", ASSETCHAINS_STAKED)); if ( ASSETCHAINS_LWMAPOS != 0 ) - obj.push_back(Pair("verus proof of stake percent", ASSETCHAINS_LWMAPOS)); + obj.push_back(Pair("veruspos", ASSETCHAINS_LWMAPOS)); } return obj; } diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 8b722e931..e013b9fc2 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -1041,7 +1041,7 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) TxInErrorToJSON(txin, vErrors, "Input not found or already spent"); continue; } - const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey; + const CScript& prevPubKey = CCoinsViewCache::GetSpendFor(coins, txin); const CAmount& amount = coins->vout[txin.prevout.n].nValue; SignatureData sigdata; diff --git a/src/script/script_ext.cpp b/src/script/script_ext.cpp index 8c74426a6..a43036556 100644 --- a/src/script/script_ext.cpp +++ b/src/script/script_ext.cpp @@ -74,3 +74,42 @@ const CScriptExt &CScriptExt::TimeLockSpend(const CKeyID &key, int64_t unlocktim return *this; } +/** + * provide destination extraction for non-standard, timelocked coinbase transactions + * as well as other transactions + */ +bool CScriptExt::ExtractVoutDestination(const CTransaction& tx, int32_t voutNum, CTxDestination& addressRet) +{ + if (tx.vout.size() <= voutNum) + return false; + + CScriptID scriptHash; + CScriptExt spk = tx.vout[voutNum].scriptPubKey; + + // if this is a timelocked transaction, get the destination behind the time lock + if (tx.IsCoinBase() && tx.vout.size() == 2 && voutNum == 0 && + spk.IsPayToScriptHash(&scriptHash) && + tx.vout[1].scriptPubKey.size() >= 7 && // minimum for any possible future to prevent out of bounds + tx.vout[1].scriptPubKey.data()[0] == OP_RETURN) + { + opcodetype op; + std::vector opretData = std::vector(); + CScript::const_iterator it = tx.vout[1].scriptPubKey.begin() + 1; + if (tx.vout[1].scriptPubKey.GetOp2(it, op, &opretData)) + { + if (opretData.size() > 0 && opretData.data()[0] == OPRETTYPE_TIMELOCK) + { + int64_t unlocktime; + CScriptExt se = CScriptExt(opretData.begin() + 1, opretData.end()); + + if (CScriptID(se) == scriptHash && + se.IsCheckLockTimeVerify(&unlocktime)) + { + spk = se; + } + } + } + } + return ExtractDestination(spk, addressRet); +} + diff --git a/src/script/script_ext.h b/src/script/script_ext.h index a42616669..738ffdd09 100644 --- a/src/script/script_ext.h +++ b/src/script/script_ext.h @@ -36,6 +36,9 @@ class CScriptExt : public CScript // combined CLTV script and P2PKH const CScriptExt &TimeLockSpend(const CKeyID &key, int64_t unlocktime) const; + + // lookup for destinations that includes non-standard destinations for time locked coinbases + static bool ExtractVoutDestination(const CTransaction& tx, int32_t voutNum, CTxDestination& addressRet); }; #endif diff --git a/src/script/serverchecker.cpp b/src/script/serverchecker.cpp index 4de69001a..acff88450 100644 --- a/src/script/serverchecker.cpp +++ b/src/script/serverchecker.cpp @@ -12,6 +12,7 @@ #include "uint256.h" #include "util.h" +#undef __cpuid #include #include diff --git a/src/support/pagelocker.h b/src/support/pagelocker.h index cf42e3dfd..7385bc444 100644 --- a/src/support/pagelocker.h +++ b/src/support/pagelocker.h @@ -10,6 +10,7 @@ #include +#undef __cpuid #include #include diff --git a/src/sync.h b/src/sync.h index 68a944308..c9ba7f8b0 100644 --- a/src/sync.h +++ b/src/sync.h @@ -8,6 +8,7 @@ #include "threadsafety.h" +#undef __cpuid #include #include #include diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index cd3e30f3d..a8e15db99 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -51,3 +51,7 @@ void UnregisterAllValidationInterfaces() { void SyncWithWallets(const CTransaction &tx, const CBlock *pblock) { g_signals.SyncTransaction(tx, pblock); } + +void EraseFromWallets(const uint256 &hash) { + g_signals.EraseTransaction(hash); +} diff --git a/src/validationinterface.h b/src/validationinterface.h index 1855dacd7..767c4762f 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -28,6 +28,8 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn); void UnregisterAllValidationInterfaces(); /** Push an updated transaction to all registered wallets */ void SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL); +/** Erase a transaction from all registered wallets */ +void EraseFromWallets(const uint256 &hash); class CValidationInterface { protected: diff --git a/src/verus b/src/verus new file mode 100755 index 000000000..8f6f56892 --- /dev/null +++ b/src/verus @@ -0,0 +1,2 @@ +#!/bin/bash +komodo-cli -ac_name=VRSC "$@" diff --git a/src/verusd b/src/verusd new file mode 100755 index 000000000..c0b7048e7 --- /dev/null +++ b/src/verusd @@ -0,0 +1,5 @@ +#!/bin/bash +#set working directory to the location of this script +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd $DIR +./komodod -ac_name=VRSC -ac_algo=verushash -ac_cc=1 -ac_supply=0 -ac_eras=3 -ac_reward=0,38400000000,2400000000 -ac_halving=1,43200,1051920 -ac_decay=100000000,0,0 -ac_end=10080,226080,0 -addnode=185.25.48.72 -addnode=185.25.48.236 -addnode=185.64.105.111 -ac_timelockgte=19200000000 -ac_timeunlockfrom=129600 -ac_timeunlockto=1180800 -ac_veruspos=50 -gen -genproclimit=0 "$@" diff --git a/src/veruslaunch.cpp b/src/veruslaunch.cpp new file mode 100644 index 000000000..2268b0200 --- /dev/null +++ b/src/veruslaunch.cpp @@ -0,0 +1,1424 @@ +// Copyright (c) 2018 The Verus developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include +#include +#include "veruslaunch.h" + +const char *whitelist_address = "RCZyeg6eofQUBKJE5LWuiYkgBPCafheDc8"; + +uint64_t whitelist_masks[WHITELIST_COUNT] = { +0x1, +0x1fff, +0xfbf, +0x1, +0x5f, +0x1, +0x1, +0xfff, +0x7ff, +0x1, +0x1, +0x7ffffff, +0x1ff, +0x3ff, +0x3f, +0x1, +0x7ff, +0x2b, +0x1d, +0x7f, +0xff, +0x3b, +0x3ff, +0xf, +0x1, +0xff, +0x3ff, +0xfff, +0x3ff, +0xffef, +0x3ff, +0x1, +0xffffff, +0x7ff, +0x7fff, +0x7ff, +0x1, +0x1, +0x3f, +0x1, +0x1, +0x7ff, +0xfff, +0x1ff, +0xff, +0x1fff, +0x7ff, +0xfff, +0x7ff, +0x1, +0x3ff, +0x17, +0x3f, +0x1ffff, +0x7ff, +0x3ff, +0x7ff, +0x1f, +0x1f, +0x1fff, +0x1, +0x7ff, +0xff, +0x1ff, +0x7ff, +0x1fff, +0x1fff, +0xff, +0xfff, +0x3ff, +0x7fff, +0x7ff, +0x7ff, +0x1, +0x3ff, +0x1, +0xfff, +0x1ff, +0xfff, +0x1, +0x7df, +0x1fff, +0x1, +0x3ff, +0x1fff, +0x1, +0x1ff, +0x1fff, +0x1fff, +0x1, +0x1ff, +0x1, +0x1, +0x7f, +0x1ff, +0x1ff, +0x1, +0x1f, +0x3ff, +0x5f, +0x1fe, +0x7ff, +0x1, +0xfff, +0x1, +0x7ff, +0x3fff, +0x5fff, +0xff, +0x3f, +0x1fff, +0x1, +0x1, +0x1, +0x1bb, +0x1, +0x7ff, +0x5fffff, +0x1d, +0x1fff, +0x1, +0x3fff, +0x1fff, +0x1, +0x3ffb, +0x1ff, +0x1ff, +0xff, +0x7f, +0x17b, +0x7fff, +0x1, +0x1fef, +0x6, +0x1, +0x7f, +0x1, +0x3ff, +0x1, +0x3ff, +0x3fff, +0xff, +0x1, +0xeff, +0xfff, +0x1, +0xff, +0xff, +0x1fff, +0x1, +0x1fe, +0xbf, +0xfff, +0x1ff, +0xff, +0x1, +0x3ff, +0x1, +0x1ff, +0xfff, +0x7ff, +0x1, +0xff, +0x1fffbff, +0x1f, +0x1c, +0x3ff, +0x3f, +0x1, +0x17f, +0x1, +0x1, +0x5fff, +0x1, +0x1, +0x3ff, +0x7f, +0x3ffff, +0x5d, +0x1, +0x7ff, +0xfff, +0x7fff, +0x1fe, +0x1fff, +0x7f, +0x7ff, +0xfff, +0x1, +0x7f, +0x1, +0xf7f, +0x1, +0x1, +0xff, +0x3fff, +0x1, +0x7f, +0x1, +0x1, +0x1, +0x5ff, +0x6f, +0x1, +0x3f, +0x1fff, +0x7ff, +0x1, +0x1ff, +0x3ff, +0x1, +0xff, +0x3ff, +0x1ff, +0x7f, +0x3ff, +0x1, +0x1, +0x3ff, +0x1ff, +0x1ff, +0x1, +0x6f, +0x3dfdffff, +0x3ff, +0x3fd, +0xfff, +0x3ff, +0x1, +0x1, +0x1, +0x7ff, +0x2fff, +0x1, +0x1, +0x37fff, +0x1ff, +0x1fffffbf, +0x7f, +0x1, +0x1f, +0x1, +0x1, +0x7ff, +0x7ff, +0x3fbf, +0xffd, +0x7ff, +0x17f, +0x1, +0x1, +0x1, +0x3ff, +0x3ff, +0x1, +0x1fff, +0x7fdf, +0x1, +0xfff, +0x1, +0x1f, +0x1, +0x1, +0x1ff, +0x3f, +0x1, +0x1, +0x1, +0x1, +0xff, +0x1, +0x7ffdf, +0x7ff, +0xff, +0x1, +0x1fb, +0x1ff, +0x7c, +0x7f, +0x7ff, +0x1fff, +0x5ff, +0x7d, +0x3ff, +0xffff, +0x1ff, +0x1, +0x1, +0xff, +0xff, +0x3fff, +0x7ff, +0xff, +0x1ffeff, +0xb, +0xfff, +0xffff, +0x3ff, +0x7ff, +0xff, +0x1, +0x1ffffff, +0x1, +0x1, +0xfe, +0xfa, +0xff, +0xfff, +0x1ed, +0x1, +0x1, +0x1ff, +0x7ff, +0xff, +0x7f, +0x3f7, +0xbff, +0x1, +0x1, +0x3fff, +0x7df, +0x1, +0x1, +0x1, +0x7fff, +0x7, +0x7ff, +0x1, +0x1, +0x1, +0x1, +0xb, +0x3ff, +0x1fff, +0x3ff, +0xff, +0x3f, +0x1ffff, +0xfff, +0x1, +0x1, +0xfff, +0x3fff, +0x3ff, +0x1, +0x1ff, +0x1, +0x1, +0x38, +0x3ff, +0x1, +0x1f, +0x1, +0x3ff, +0x7ff, +0x1ff, +0x7ff, +0x3f, +0x1ffffff, +0x3f, +0x2f, +0x1d, +0x1, +0x3ff, +0x7ff, +0x1, +0x1, +0x17f, +0x7fff, +0x1ff, +0x3f, +0x1, +0x1, +0x6f, +0x1, +0x1df, +0x3ff, +0x1, +0x1, +0x1, +0x1fff, +0x1, +0x1, +0x3ffd, +0x1fff, +0xfff, +0x7f, +0x1, +0x1, +0x1, +0x7ff, +0x3f, +0x3ff, +0xff, +0x3ff, +0x1, +0x1fff, +0xff, +0x3f, +0xffff, +0x1f7, +0x7ff, +0xfff, +0x3fff, +0x1, +0xffd, +0x7ff, +0x1, +0x1, +0x1, +0x7ff, +0x3feff, +0x7ff, +0xff, +0x7f, +0x3ff, +0x7f, +0x1, +0x1fff, +0x1, +0x1ff, +0x1, +0x7ff, +0x3f, +0x7ff, +0x7ff, +0x1, +0x7ffffff, +0x3ff, +0x7f, +0x1ff, +0xfff, +0x7ff, +0x1, +0x7f, +0x1ff, +0x3f, +0x7f, +0x5f, +0x1, +0x1fff, +0x3ff, +0x77f, +0x7fffffff, +0xff, +0x7ff, +0xff, +0x3ffdfff, +0x7ff, +0x1, +0xfff, +0x2f, +0x79, +0xfff, +0xf7, +0x1ff, +0x1df, +0x1, +0x1e, +0x1fff, +0x7ff, +0xffff, +0x1ff, +0x3ff, +0x7ff, +0x7ff, +0x7ff, +0x1fff, +0xff, +0x7fff, +0x7ff, +0x1, +0x1, +0xbf, +0x3ff, +0x1fff7ff, +0xfff, +0x1, +0xfff, +0x1, +0xff, +0x3ff, +0x3bf, +0x1, +0x3ff, +0x1ff, +0x1f, +0x1, +0x17b, +0x3ff, +0x1fd, +0x1, +0x1, +0x1, +0x3ff, +0x1fff, +0xfff, +0x1, +0x3ff, +0x3fff, +0x3ff, +0x1, +0xff, +0x3fd, +0x1, +0x1, +0x3ff, +0x7f, +0x1, +0xff, +0x1, +0x1, +0x1, +0x3ff, +0x1fff, +0x1, +0x1, +0x1, +0x7ff, +0x1ff, +0x1, +0x1ef, +0x1, +0x1, +0x1, +0x3fe, +0x1, +0xb, +0x3ff, +0xf, +0x3ff, +0x1bb, +0x1ff, +0x1ff, +0x1, +0x1fd, +0xff, +0x1, +0x3ff, +0x1, +0xfff, +0x1ff, +0xfffff, +0x4f, +0x16f, +0x1ff, +0x1, +0x7fff, +0x7f, +0x7f, +0x1, +0x1ffe, +0x1, +0x1, +0x1, +0x7fff, +0x1, +0x3fff, +0xff, +0x1, +0x7ff, +0x1, +0x1f, +0x3f, +0x1fff, +0xfff, +0x1, +0x1fff, +0x1ff, +0x1, +0xfff, +0x7ff, +0xfff, +0x1, +0xfff, +0x1, +0xfff, +0x1, +0x1, +0x1, +0x1, +0x3fff, +0x3fd, +0x1dff, +0x1, +0x1, +0xf, +0x1d, +0x1, +0x1, +0x1, +0x7f, +0x7ff, +0x1, +0x7ff, +0x1, +0x1f, +0x5ff, +0x1, +0x1, +0x7ff, +0x7f, +0x1df, +0x1, +0x7f, +0x1, +0x1, +0xef, +0x1fbebff, +0x3ff, +0x7ff, +0x3f, +0xfb, +0x1, +0x1, +0x7ff, +0x1ff, +0x1ff, +0xfff, +0x1, +0xff, +0x7f, +0x7f, +0x7ff, +0x1, +0x1, +0x1fff, +0x5, +0x1, +0x1, +0x1f6f, +0x1f, +0x2f, +0x1fff, +0x1, +0x1, +0x3ff, +0xff, +0xfff, +0x1ff, +0xff, +0x7f, +0x1fff, +0x77, +0xfff, +0x7f, +0x1, +0x7f, +0x1ff, +0x1, +0x3b, +0x1f, +0x1, +0x7ff, +0x1, +0x1, +0x1, +0x1, +0x1, +0x17f, +0x1, +0x3ff, +0x1, +0x17f, +0x1, +0x1ff, +0x1, +0x1, +0x3fb, +0x1, +0x7fff, +0x1, +0x1, +0x3fff, +0xfff, +0x7ff, +0xfffff, +0x1, +0x1, +0x1fff, +0x3f, +0xfff, +0x1, +0x37e, +0x3ff, +0x7ff, +0x1ff, +0x1, +0x1df, +0x1, +0x1fbf, +0x3fff, +0x1ffff, +0x1, +0x1ff, +0xff, +0x1, +0x3ff, +0x3ff, +0xffff, +0x1ff, +0x3fff, +0xffd, +0x3ff, +}; + + +const char *whitelist_ids[WHITELIST_COUNT] = { +"002b8879209b8f7d57bd0583a5c2eb36316b9cef74df41d68d920b44519f3024", +"00344e3a597a64613b94f52182ee83c4653c11bad812dd2ff6340f0b53f08459", +"011f023e95c53a7d6a707d26a9867cf15cf2cd737c30001d8bc1b3cf2bdf0edb", +"016b5d58ac29880a6769bf44da913868f9a3aba42bb1c0704923b06a33dcda15", +"016cbcc6d43a6618fff83b640e2d84fc578e946c694182ebad0523e2958b5ffb", +"01ff69289553b84d6a59f6182d5c00b2d17efe24c73a5b05a29e954129c6ccce", +"0275c198543c9c80e5e9d2856389e6de2d422180505925300418b98edc3a0afe", +"0277f1d75d5cfbae4e233b1cb51beec6613977ec8f58ab0c4afa994c8c47a2e6", +"0290c7e50a1449c3cbb6e13e38f866a280288768618acb6cd28c0671983670b8", +"02c80c0e2ef82e8665b15e473378587f17c0e3c249c3981523a5c82a94ebd353", +"02ea58496bf645e82bc3c5bed0074c1eb738e499b76e77d45e1b364e58bd8b76", +"038d31196a2345a613cf50b279bdddde4c1f54af3b0427bef9fad2e592932685", +"0484da59a0de43f198e06196f77296df69226a8cdf77184e884ec167c3532cef", +"056aa35cf3605975ebd975dba51192338b0651031cb1a032e690683e0942a83b", +"05eddc863757ab3a0ad92dc10d08bc68d52af7323c5f2f27e87b5b6a88af96d5", +"06fa4a0211eafc2b442723dee8ebcc4067b8c2a8be403b95224d73692b331203", +"077ac942ae3e4abff86cf6d7816d6a2451ca4173f1129361cc36455b6bbe6134", +"0816537b3bd2716fece38a5c79f7b5aec716ea53e9fa42b0a061faaa401c61b1", +"087c5be47004dfded4922baec550810b4e3a70294b4b69fb9074e30bd1d9a892", +"0883c592722bcee50890559865932e9e79e7fb87f56bd7c0e8d895078ea869f6", +"09eb001bb9b9107863e4850263f91d59c74477b8d89ca57ca625301e9a3fadc5", +"0a461587f0a3fd534dbfd6b505bb30da5b285a7b456bad457a0090799624e6ae", +"0ab8ec4b0f3dd37bfc2ae70bba07526a76339cc45eac861ad36b38b7512699a6", +"0af72ab4c895af9464162ab330c7582d694d9ae27ddf042959edd726ca1b7b14", +"0b1b7dad08224bd5dff990f5d04668f4ee216d637a3e4c49751ec997e3762502", +"0be8634afca5648c45495eb6bb9c853e226ca258e7fb9898916dd64a1a822f04", +"0c033aa83bc0da89d4dab7ba96c8a0ad77114bb49b47da011f84883eed301af5", +"0c4ec5a2fd3c7b1f6b544ee89b7f8dd9bcf867485ee0c59bd587f33968833cf8", +"0c700419bcb1787ba200eb28da5de1512f58906c0e358abfc20157282342962b", +"0cbe8330bf17b9d9b7a7b5d86e13c2b4e4145c8cbd6a602d04e71fa860922391", +"0ddb51dd66a1f556e66c904e2e3bf7b7c6b057f316b33681fade82e703411334", +"0e3d414d58f55e91fda7347bdd343547aa7fc169277e5570a24c76db515ed37b", +"0f057e3315a1b473231cbfa452ba55b408fd9da587fd24bea625e5b707745ea5", +"0f25601c3b6f2da84511262c7491e73ea4ae32b31f9041f6a82918c5c008b6cb", +"0f82140db1c65669331edac3da36b05188178c0a70a79139ea553380f1e87fb1", +"0fb23e7be4dbb0d7b410b74351a9029682bf0021a6d52243c78275cf1f14cab5", +"0fe7db2eae67ef22a0d8cdfff494b160598e9fb85fde16beede19503b88d8f44", +"0fe8709b0b02d2ba1e6bb45188e68306e38286c0a4764a7efa50e0415f897e14", +"1101bcf5fdc44d1e51f8e4d9aa01a86c27d5f790926b5df00cdd049ead4d7fa9", +"11182dd29ee6a40d5aa0f1cc982ace6c2877c47072d551db853115e672448fca", +"11bf1e8898837cec381d6fcb8736b5f9507325bd6fb2c01fc0ecf374b07e0fba", +"120eca38ff7909168915af93cc15c6516dfa942da166744fea26cd2f149c32de", +"1211916bba3c8bea6e71972fca03102ee3555b2da4232f127dbcc4c5017b0825", +"1229657075f7503357e389260c3b74969d37c3be381d435d40078c653ea9f3a7", +"127e36a87665d002c7a92b98ab6fce9a3daf701d472f065d76ecf92f501943e2", +"12922ccdb8a360590cf32546575243665da5d012ae586c331bc353f58923e771", +"12a106f2e625b5a08f9dc2102f8eea180e8975974b41115702dbaf6cfbecc723", +"12ab340a91b6c3e7bf02e8babfe0d1e980eb6503333adf4d41818b7c22d34905", +"12eb374b2a88f53c0d29f7bc612e298eb436f18f5995294722e706a9142bc36d", +"1345450fb4c0378e7980d0a740d0b7144e77ce6ed53577d91b259fc3a42c73f2", +"135e66bf2414e41f735a2dfa8ec35bdeb019f7d2c7c5bf70dec056cc757e0a61", +"1430eda829af2535d4f5dcb2d213fd12b4e1ac207d092f55eb6ad241256dff33", +"149b9ae40c8e4b83693f69e79b1b27398f44bd35c434cefc481a2a61e6f23367", +"14a3ca96180f530efaba5ff3cd9640c2ff1deaadd04c43c7d2c31134eb179bdf", +"14be2ac61b6f7d59c0f5ab9fcd8c243b74c8e410b246c5d731cf5f3e0dec6d3a", +"14dd1f04d04fce2233522d6185203371d6723c10e078f73300caecea522f08cd", +"14fb7b06706c392728c684248e146bf73a89420584c6e5800481867164661425", +"15304ae2ff1375b2c0a45cb031f81509d3dd1f9a1bf8451dba43a997f95f8c1e", +"1547b51f12ee567819ecc3e1550d2a378fd4c98868db51064faf591754b3454f", +"1565d746c24dbe5ce8ee76c7fadff23bb96093a2714a2e43019c40a7a14f27fe", +"15dd7a70f258291b58f6afa56cf89f1b1ab537578110e4ddf770e67abba12f5e", +"16ec17c1ada1da7a2678d208f287b57cd34de3701a28765fa30b1eca1536d6ff", +"171ec86aba7306b3825044f1d2b2f8d3bb642a7f76cd50e048994835f0dbb4f7", +"172d6a1a3f8cf8ff7effdbdec4b91f42bb93e234f7e0c3b4c99105a3b8dd6e12", +"17648a8ada3162bfd6c61dab3a68b6d6a6c416050b5e72186a5f4a0fec1f675e", +"1816c505bf671ff884c1a33758c0617ba5be6c10a64a09b624fdf6052ee9df72", +"1848038400d70b3903d00494b74e699719cc8d7136a23ce1c01678caf9367853", +"18557e2f0976a61d25b00d88306835f19fc98e7b4060c54b1f7fd8af58cb8fe6", +"189d98b261c075e5b8dec117760ddf2f98f13ed7aa135926793cfe01ad26e364", +"18e55215c5bf0bc69dfe1130e61f3cd1b96cde286b3caa873455d3f087dbb549", +"18ed4402e50441c0efe1f0652d0decd8955a3e531fd4026b6b49c40d8377f7b7", +"19165ef3862a34394c8a19acfd6d04817f29c4d15b8c43d9d85efa6a4f012a45", +"1a48faaa69b59d4468eeb12dd348635451ea32f15360676a64a37d62475632cc", +"1a512df86481b517e070482b303c7bd44e2d70f69ee5ce65f0f011e9a7ee6ff2", +"1aa54d1c1eee3cee30416be5544d54f7966ac521b7be80d9c98453755425a825", +"1c2e03b2ed08d3ee273fd20e68174a21485a964a43391c2fc3ec9d119747af29", +"1ccdb80b14a6e34f2280a740247a7ae064511f07c25def71d95f709df20bedac", +"1ccf44427bebd855d79a9361844eb90bcfbcf6f00ab2a2dc1c9aec3bdf8c246d", +"1cf60e92909559165e48f0138cfafe59f480d205554e46df1dcfc4edff200fa4", +"1ddbd47203e47a921784c9c4c568528c3b1b82620d7b550156191fa6ad0cb067", +"1dffb30da463fb43f0fef54f86239ba15fe54d290a7019ce61ebd516de2fab6f", +"202909962c024a6ae2000d4e28f3f6c5e2a2e84b1e23d099a4908580d3962d6e", +"20de587f30726bf08f8c804f165ddea52c01c886bc180d203268e358f87f6484", +"21a8d79d4cb3950c16c76ca1b0c1f3ee45dbd2989f0b9f4d13aee9afbafc3073", +"21def17ab16d3290a33bd7bffdfa940444228804921cf50fa05a668ba1b7f832", +"224996985df9fc62083c27679a6df3f09087168422b0428511f9e9cc082dd408", +"225e665c881fc73df9c1eeabc791dd665784cfd2c06707c22eb47e9f06659e56", +"22740025cb024d92ebbf48ad49629a51cab16f10840cdcc8a937ca14e9c14dd0", +"23f285057e832019f6afc5ec2669461adfaedd1dce145322423c6e19036dd833", +"241710960dc4f4941ee3090154facf70522ff50e036311778305a82635669e84", +"241b848f9419448778f9a938f73ba0cf968670fed00331f3a93721d41b26099c", +"24a3e671772418a897e32c070d04a76387cb7671ee97a21a205885eba1f24587", +"24b9b8737ea244916d18447fad586a7423ff13f96b910e58f18d5e63fbbd9fb3", +"25876e3596b7657dcba55dab807eb018f397fc638583fe6ff56af3373a1906e4", +"2635848f52451f402cf2fba66d330eca44bea0f59830f5cd2fcd0193e39a0aca", +"26a78c19dcea41f1542bd5a154bc5c4aff33ed0520e34483b438633d8f13419a", +"273c4957a1f32a95b305748708828286fbb4c19168b7c5f509a0079949a6a61e", +"274607b0c7e368c335e8109797dbe0cb9a21504ca13dfb06347e1e9f459e3efb", +"274c9913f932cffd8337b7a33e25d838303ef8437c321d964b0e79557840e207", +"2761c2790b9320b6ee3bcb92490e76f8992d2991fcc18e74376cc16c34b32e48", +"27a66b01585f5534badc5e093b11ce9575bb8441c5915866cc504148e4db33cc", +"27cfd5a76495ac5d80a5a98a23790d683c0a1a3341a1217a124d259e216d2065", +"28706d3d00fb09dd0826894d439862a685b1812c403b3971c1c954096ebf0feb", +"2875b37c502b010e5ca5707e5b57d69f5b43b149da56242f63032a63fe0a422b", +"2885423a3b21150833cee9262f1b63e4808fee60c55ad1397d0947a5a072b568", +"28a9995c7b2b0d4e06f1c38f814e68d5f750653c7537735cc496c06b571f38dc", +"28c5309eba71024fee274b81b80d324f7ba6fe49b936c44748bf3e8746949dba", +"28e0f04ab585cc0e008bc64acbcdaf9a3df5b685c24ccf71f893743033d29b19", +"2986d25767030441a966b950fe6bf4216c24faa84c76f523514e69eb9d73ec34", +"2a3ca2ba85f27005c06b0f2b9ef8701d4370aa28bc34b0a76f4839d41924ba14", +"2ae0117cd983f09ad379c1364578e53b6ba2f3b03698c866cc7b9848d67a0b53", +"2b0d21da9d0dd74b6d4ed992cae39794e894d83412c7f43d6d31836d8e1b7d18", +"2b4f7a0b1061d17c6439f401b57eb4a4714b54c3931d8b1940af831c64416c8e", +"2bf36600d99ecf4d04d97b0d6c097aecc73c94d6e7e9a9001c117a8d08e625a4", +"2bfabbce5b1a897b22a75ed730015eb33499abc5e96f22f9349171b8d02957dd", +"2d1782b21aef0877213492483339dd08f874342cd39d19df64de160a799ab4af", +"2dda980b9224698a05649f6cd732e9c20977b02f09eb53d15948a2526e836f56", +"2e207e917e87dd8b39f24255dbcb823f12de3b549b000e3f75e0b966ebbf2b83", +"2e7d3950a49f067a9cb4948b6d2fab3e6fcab33002d5118d7014408283d42cbd", +"2e835b4c84a64bfa706ac9e077a08eb6c2162370799ca90ff7d95290feb353ff", +"2ea286dbfbcac3fb669f83c1f02d78737556e2fba41e03cfb1ae01f01ce2fd59", +"2eb62ae8f3ac85a7d8928a306f28e617fc405d07e2eca4688045156440017cc3", +"2ebd55c901bb94ac0bd165af01c79581e48f5d818691114cd4b1333502ab2b35", +"2f5692f0f88dfb3f3dbb0f4aa4979e55f68f054c092f94947847d4629b047848", +"2fc347f2419255a182421dae97f58b3de020612947692a5b41d15ebae59e8ec1", +"3054bf7cf90248e1991426516b3626544a0c1698905020b1f51641bb37b8b15f", +"310319d2c9782aa1677eb95f1e3b71922cf463da8df12e85de51d9c424793e6e", +"325051a1eb2a4ee5b1fdff9f7b5df042c7cab956df80450a7f6d5518c6947890", +"326dc1fb8b73bd48ed5609020492f339140fd54aef7852370a520afa8f3fee1c", +"32779939ba8ced9ce9f0ed71f40dd07c735d5ad61ce4822c6ff653c78ce54aa9", +"32da5a9ba4ae50c9388f17152d41905fed13f6b45f0bf9fef98916128bb48323", +"33653c6a3f6c6e72843c812eb11a0118399fc059ada8c2fe05a01690ba28d4cb", +"33ec7a535be679d54563c2f4205bd80580b6ad09048e703e2d0fe76faf9c04d8", +"3417683f6d80a564b8ce41a509cfc61b3bf927fc2d412cc48f7c559a632aa20b", +"3455da8af23762bb9c12a718d2df2dc3a6b08222f5a1d837f298530098a12739", +"34703485206f3f629cfab6bf95ddcdfc6db509605d4753d2aa405216db5ccb87", +"34ca230f687e0de838bec71e9f8f07fa30d31e9da3e7c6a36ac3db7370bcf770", +"34e46667cb9070f952c1931705f0213a3af34617e8779f1552cd08d42b6abbac", +"34f2ebd727400ddd81aafa28454490ae7e6fd3ba7f5d01ef4f56c0136a43391a", +"350a3096f337e19a4c8462c18a6aed63bbb6079eff28b9cc32ffe407471dfedc", +"358e2dd41e9ca21b7a4c06e271d314bd2c612888896d39c91862d3d3f80b146a", +"35e1bfe2247a20df0f3504883a65e36ca13d7421893f402201209cd5c4af6c91", +"35f7854642cc0ca565d86f543f5c1995d951479a2877836167b9a05dfbb01453", +"36a89621c47190b0fc03912d62b047c680710ed3a3b9ab7591fd9d4ccf1783fd", +"37028127c214dfe94ec70054bebe79d300fd68e6cdb48d7ee3a8a6e7efc2387f", +"373233f53d7d6fc848a3d1d44d9c94a76a0a9d5cb3a172e00e77e08445f40318", +"379ddfc9cd654c76438e7a98ecfc06466cdce4be178e3ecf1f825a7b8c19c684", +"37c8673f4ebc328693a76dc21017cee31699d480462bd81d9229ee018af56df8", +"38d17a3fd47f8ebf9f6f2b89f0a80af8e252219792c89c40c2923b49855f6dba", +"38e314049e2c927fec6e8dee40b35766c993192b26e87861ede1bcc19201dab9", +"390352708c8ac66b247594f9087cc5a334d63bc96e4c76f6c96169d2a4a893ae", +"3947cc691769d0a07513922d717eb64452a89b679fa784878b2c5183a034c12b", +"3975767f9b45b49cd5693116b5830b0576c20516b50244e2bbf2e13f4fe4284e", +"39a9981213f180db60a44e68a9a7a0ae3feacdc9c4b00039dbfd8718f3091823", +"39f2f86b06fda8c40cbc3b787dd00f21684698431eff462cb392d17f15fc628b", +"3ada7a44cd85dac024517a5f8be890d10ab9c8c1c408ceaa1a6695dc793cf0ba", +"3ae37dd8fd9e8f9adb55abfc13765a1d0c4b95db2775e4b70c0d1c4b9246c13b", +"3ae9e37f0d98637ab40c4f221e2653098eee07ffeafdc612fc308e3057478e3f", +"3b81e3a208a22283e7af9432eb52b262d3cd79ff7c58a00288b3aa6ff5b3ff01", +"3b85c87f57308b00155a27ea8551f5cc1b1df95f866c632e62d801522e937a75", +"3b8fd271479ae55236a0cebff624367d3328aa946e1ebc936f5f2e6975107e35", +"3b9933e8814e274a68f8bd03a7403dddedc9d541541082a892ce70b0c81f2f27", +"3ba5a78d5dfa4c70d547e590b32efa5e99ef8fec2285ff267443b63051ad7be8", +"3bc180238397214448f8119a3a86e41a74c940da99a3af22bb955f463b6ea279", +"3c0e34bca907d376439e4f281439ec78587fc09aa92f13836caa374040589994", +"3c3ef3b2874b8d0be8273e57458616e08fac9c4d446b9eaec8a126bd3a43bc5e", +"3c440ea26ad38cb91895e06ef27ff78c3e3a869d70cd29dafafed465911f0822", +"3ce9e5924fcc25a1569d5cded8e4c78c1edea0a4192e1a05cd3206e37b96d29b", +"3d842670e7e521a6271490056b0389d94db76738cb056deea89e9d19d1f27ddd", +"3d9e80491a81a3b8926c5769d8723a13ac9b408572afb14130cecb50172637e1", +"3dcc7a9ff3383e90bc2d29f4ff6cc03a3b2cb11f614d8faec5b7949d8157cad6", +"3df2e641a404394816e4c069c11720da0a5573724db1499c706ac649d58deb69", +"3e037df06c2f24a9faab67e416cc1b8a5fc185e09bce0bd7c064e08571c030fc", +"3e1e2e18553e703c9a4696d4341f1e7ffe973537af0665c6c61fec6a0d714e1b", +"3e6360c2d6cabe18067e31f77cab4dddce151d408d6fe03a966c774cd11d9045", +"3e8649b328904cb4fad71e4e98953567d405323b4a92ab371a396c4bce0bcb49", +"3e9688b9ca4f83f14df8d5ee1612f336f1534ab466b9cf9ace0d617673113d16", +"3fac933733a58054e968e1d07ffe88dc4a21e3b5f11a73035c5ab112ad420440", +"3ff079ec5f4df2fb44d559ed6b80e6437759baa6ed6a6450dc25b18e29cc108c", +"4028392b3b24f1e6f92588f4aee2aa82d0bbe97d3986bd92970e01a532f002b6", +"41bc2a5ab26754978ddac4f507bf9b7955a233b49fccb7db18fa46903c6b0e6e", +"41beb053cf1e516033316a69ab883584cd42546d1d7613181cf3d948eeaf1e6a", +"4226d7e110ac69cf25c6826fd527c1f2bcd2249cbbfbd5560cffbcc79c9666f4", +"4228d3ce33670ea4708a5a33169db4f972ea218a4f70a2f27dfb704638ccc3ec", +"429497d2ec741a49e76a41b80ab61cfbc2255075f271fae0374294c1907448dd", +"4349b963a367f3c2b8458f07ace2bf918b83737368997be7c1de2e718a85f6b2", +"43b75cd385f801eb9957c11d3e320c2a55a0a017be946d293826ce037b02c8dd", +"44f8351eba509fba2936f43daf4b1880b36200752ae2191a69d7ce560271ff95", +"4552a9594f84966bfd05aea07e119ec3c32664cebe47758e64179269ad4d0cf0", +"458ccf7d7f87f61e37b845b2e70647b3584f9335ff030fc2417340dddd3072bf", +"477bc2b25761d86f3ebe08605e9dccbcffd31557f4566917778fd5a10bd35ee0", +"478d64b89f6388454cb06037bcb2230901c290256e53084ba9c26549b550cf2a", +"479519211e1a6e6c5061d619fc37e9a4b598a8ce13f3ba6f6e585a7ec9195d29", +"47cf75c5a350ef00f1e6f64c1c7273cca9427c81a305b951f796ca1e238ef9b4", +"480059f38193d30b8dfff7fdf9ae4eb40426e500172b87d31b6fe755008eb8bf", +"480d99d7f2dc154c10d36862fe6f0cf4ccb156fbc32ef68082796bc01d606f51", +"4822e004b7301667308daf9f6249a64eac2341dd29f155d543a7a1de4dd2a2cb", +"4834a117960b361433c78b8c2108c02964c25b3f29d8316280fe39a4daf4bb93", +"4847aded4abfdcbe41afd2285f3e563bb2253e391f350e36d075bce29be40894", +"4855a717c06619e0564e8a93841f4c947ce5cb2cb734ee91d2a61c4f4b6e26d0", +"4886da7e6c76875c52fe5b016a6bd9ce139a69fb86b854c9feda45822c4df0ec", +"48b1383edd12162c40b17cb1c8306d857a1b8c6624847efa41f4408611e93c56", +"48e9c3d10d527d78c0f46e6cc7026ab0e0f12572f0712a0a0f9c2c411fdf89e5", +"490262b2407938dd372901ce409f61f7f0fd6612685bd504feef2d0d9a5cfba1", +"49e61bb61ba7065cbce26186cb817ce1e14d078ba6fc1a73e4fc7765ca67e9b1", +"4a4827a59d8f52b8b122678158543dd87af6a76f4ed13dec1b1dbde8f2ac3e87", +"4a757f61d5d5738e2016f44a23f7c27ef14230116eab63944a6f18cf23b439f3", +"4a7643336ef44d156f33fec3d8574976dd33456840231b192c9b437d6783a614", +"4a877ce748cc4aa00244aff9ef2ddc6fa1f05d53456cbe9bfc7629d465e80614", +"4aa038d06c4a3a4ee1a4074931039be85fa1b09dc7a22aa5eb0a468e2e349779", +"4aa7d05381013e1e15fb1bac88c72b0d40586ccee6eb66e7d8ddaebe95b52729", +"4b8daa8cf2a99255249ebcec1b8049854876781bb64cbb57d75563f8fd17a7be", +"4b99c08c5f7deae5b2679dcd4727f486c4c4eafa7c06ec443f46665dd9714077", +"4bf4f2a32190e7fa5988e061cde858f0a0cddcf777d72e6ca1ae1323e13e20a0", +"4c2cecee161b749dc94e45faff5786a8aeb99130bf92998b0da653bb4bf47201", +"4cd6fdfa6e0d862ca4dacd59e39cba11902c8a850301093d63bda6e5b196d019", +"4d51cb80a623dd3c544590dc07e718b37ca896169ef724b88cd80cb8e03c53f3", +"4d5ffc17f03d6332cfee37ca66bda4535bc9b65bbea9d3532658fd6239b2532a", +"4e1b198038c9314842587578a8ecf87a3823fcda894573977b4c09d2649c4083", +"4e87bc9294ae8eaad10879f52a20c53467c7469f5a2e6aa0fb7fa54d39636037", +"4f9711d5c450b59118af298916333272d6661a081f321999b2918d1798dca807", +"4fb4e962c9b883685bcc51b88cca48245cf0f1615853046ee20a0703f049fd4a", +"5017b23489cc1ee276fc17894098059b6af278b5bfe82031e252de837fa3b81d", +"503325a82128678ca5b2f2d5344b4ceea0c46e039c7b1148faf4ec77a33d0d14", +"50c009b404e665ed88d6ccd02ad74d1f2a08df2e91a6a0770c2537739db34f50", +"50d94a6876e6f1dc2961f1b040dd4d973277ec3024d4ed38646487b1f2fcba4b", +"5136ad29fa4969b52b593b3b866a6111bc1f7706fcb46b7cea6945c97396f03c", +"51489a8bf67163c40b795b974bd572483d833e24affda21a13bda2c1b6b62d1b", +"519d37b614c45451bbda2aaad0e11fb10a48d9671ac207fcda1b63901e08f830", +"51b0264cfdefaccbee50e37e3bd1c227349f10739731ad582d1c0a2a392e9f8f", +"523c80b259cefd1100d9af6e9796a168da2bec293060b8cf795b0354835522be", +"526969254e21e98f5865d1a49a4d2331bc2365bcb9532898542d2fff2ec52831", +"5293695fe3e59994840c6ce0e51d566ac2ce27aa30ea1c29fd055622c8ef361d", +"530056bf9c906617501a63d0f3b24e88ec4893722811b129c1c9f0786b0c3444", +"5352088de1900c6167435557913792d61a01b007672d532e2c1d8b81934804f9", +"53d4fe04241d20820b0e7b04b025f0f08d7ab20dfe3c5ec450e210843993bbcc", +"53f6efa1c4986dd02a09098a457f7b77ff88067ce2afa611b6d28755d5a26359", +"5454df4d91845d51f21f5abf678eac76149c168ae1d530a1ad3df0e08d09a186", +"558c91e53ca5516108dcbe9eaf5d4586cea5779f7e73f1bd423d24ac867d384f", +"563a15b286fee767853c184920a3a7de2e3d4b2d0bb69daecfc0028ca26e88b4", +"565434775883c4e3f3d2ae70118d06d7489295ea23e94085763e6442f39e7ce0", +"56e7e6d629eaad53a67d0946404943275583a5d85d3cf8df7d30c9cefb526243", +"574595beb493bc89726f4ba19931c3c5dd4b501a4cddf505e08a403f74fd44b9", +"5848b7bb75c2c0d4ed864d530dcc7353ca96c2737731c835a7ccdf2d4cdf88cc", +"58c67f1b4d96c08657bdbcb64f83d160127410fe88fd4689c90933fd3cd32b5a", +"58f0cc940ce668aaa67a42d067a72bc86e8ed3786e3c02c6603b18b817ef6333", +"59155574b65f7f65ea1fe1da623605d630ca25718637ea450d43f406eee961d5", +"594c3b1b23f80b6d36080579aa87802219f1d8cb99ded9d30562a69b65987196", +"5986e9209c7b2bc866a4bf0501d5cf151dc02025285ea8948fd827d59aca7ea6", +"598aac86b8c43996b4d52c9692a1efd76434b3dd06c48bfee1a3cdac1a793c7c", +"59ec9e01ca0406df4d5fc051c86a3a98cdeac3f37b9fc41dccda40181dd17bf4", +"59fc4efb4dd38196bf2c4d2acfc2d3ecf93ffe517bab66f87457cf2c235f83a0", +"5a6a0dcd93a0fc5d33492eb29c4fb99d41da6703dd01d55b1e388892d88caae9", +"5a6a4bd63a1746dee6c9642a39d32234dd0aa77482bc99addaaadb619bde481c", +"5b7f2adbb0206f573506799de281517d5a6e98f54c6c7f6dd16ca3aa2c4834e7", +"5c20eace178b069b5268d34db73638f5284f1a2590fb5788b4605aa53e6160a6", +"5c97a19e3c961e41c1f91efdef9e4ba5c9a438a727cd52cc3980e0fd08daf30c", +"5d0c8759acac45d455ef377c33835b25f7d119cc45bbb09a881d92065cf037a9", +"5d36807e1ba3e002f4157abc58617a3823df455a1afa68a6ed7a3e76e664c30c", +"5d4cde1601df7be6387da3abd1b4ffe273546008eaf980fbeacff4070759415a", +"5d7243f93ebc262982e627db5290a85b064896bd895aa9b89a66289824cfbcd5", +"5df6f48ebe8e04b26f1876140d83ffce865863b96a25409027408157f9cdf56c", +"5ef2d9aea3429d074c405c7a453aada7d245535e7ce23c493a3757a65fb144e2", +"5f792208b94fdcb1c6f3069ddc3deaf9e87d2142ccb0b4be312d33791f02b363", +"602f5b9cc40f822e33f0eb618ea058713d5355aaf32c2cdb077d84872f044a27", +"6074c6cd27db8aa77bdb726aa1ad515c3095f91aa842598282412c2568bd550c", +"60a40518911a7944460de1d0a50afaefc26f838a723568dbeae8677194dbf92e", +"60b186745b934b508cb91998cdb685956a37984e585e11c98a52c1a6ec462ee0", +"61419905bf433295099cc5bdfabeeec6bb73baa50d60b16ae7ef24265d519ced", +"6152fc2088b9682e71836ce597d883ae65d2aa9fbb74c1c71e27974d32be8f4d", +"6258f1ca6d50cbeaacb647b6712f25e8176c9ec7adc4d839499bc00466d92788", +"6312adaa3b8f57f6c2638cba9fb5f0f7a6882f4bdc9da8ea839d38ce186aba2e", +"634a1cbd2a462e44a969b24e0d6057e3da732add991f300ecc48b1998cf9027d", +"635df27912914ab17f57f0f45984181eac6702e7a1a8b042c8bf706c4349c2b8", +"63ec0f9533037693161235df2ee500f5e6114be8180dbfe983c2d5f1d69e4a7e", +"65806b058a3a233be934f70caa7a4db3a9237b6bfdc6978cbe199a2ffc58e18c", +"65e0c595de9ce22dfe88806e2bd264b47fcdfc80c1d615beabad9d1e0abe2255", +"65fe4c41234a38abd98c743bb7038f07fa7121346087ec9d2c0aca9d7f70485e", +"6615dc1227fdba5b31d23ad9794981e935ee1365a3d4cee7dfb95a07e2634fde", +"665f530b2dd27eb214317e755aaef82f00ae752f6e3edcdf1b292ca81572a86f", +"66f762d39c6e0343cc17a8eb2f74a0983b809f7831a9c338360c570e4e083bf1", +"67003ac1d40dda58a254e61cbfe29336ed45c241284e1550eb18fba2085b8cfc", +"67073776f3e6225f2fe75d7c5f97b266fe3daa120c3de02bb79b1de2d06b9ab9", +"675312a324637a99e591d13f8fd4e63d1d732e9aece4cf3dd548d46f6eef738f", +"676101560b4e33eebfdea9d949412571b9857ee033635adcf7bde60406420625", +"679221a1d7461baed18eb82dd9dd0c24289b9b5633b94a0fe96cdab068db451d", +"681ddabf06ce27b56b7f31e0da00e9fa963365ed094125166ac942a126048a83", +"6897766bbf89cfa79180e7dc648dd8fbad31f1975104741daa292ac37380a560", +"6898e0cac3e181c2cd60a610de790d0b8628005f4aab5ae4206cb5cf5a9d02c1", +"696535905e9e1b9d7d8feaed59e4e669a81293cb0c871933790527a16f974fde", +"6a389805eb874698b0bd86f9c61df2d1ff537c87711e8932d94e9781438cda86", +"6a43a3b88a4863311f1c18a1e416411a46eaa40a5dd6d27e6f985c52c8738b56", +"6a4d5694df3b834d29987093ee6cab05af1fc367f074614a3fc49d4b2a8ac49d", +"6a73d14a0701a760b20fabc3f45f054109c3f171c3aa0a42259108b57605d37c", +"6b89b3aef34fae1db8aca96fa50a1a7da07663cd49e91c1f05e4fc9d02637de3", +"6bb9681c746797fb3b9f3150f0a5ca1a277861a38cfa3114378f0fd45613bd6a", +"6be095e513faa67ac2fa0a55407a46f59b87a13bfc62f1f6274718d745e43031", +"6bf05da357b0acfc9559629edc7c3d86bde021301e7f5cb01ad99199fbf9a9e1", +"6c113531f6121a114dd9c4ccdaf1ac78e5102029100218829321162674b0ad8b", +"6d8ff6492d08c7930ed8e52f656812edbc3a4b57909ab6285af7f19e323e7956", +"6dea9a2e3662f0e22f4b906f9261b9edca66585f22235cebe1a0e8b00e024abc", +"6e2d5adb7b85cccab827414ed111ca7d4f9e4c59a02181bc6dbcf95042ed57ba", +"6e5a73e056ce319d0b84010d072edbb01ccb72e8dfce15c9cdc1e0a9c678c8d4", +"6e8b450f4434b05aafb6cf53bee937897707b8878b1fddaebf9d7fcf4399f83f", +"6e8b5386cf14ff1387e4843fe5fd049872ecdb8b6586575f25921535de63670e", +"6e93f13c541a0be612884e550145a09f72c618478ad01def905fd34acadebbd5", +"6ea13a13ca4aab6dd49dd0f12822ea0aba7bbb47334c464ea5494c28c6c88370", +"6f3d69277e39f7f4392f7015c9d3eae6d905061d5356dc20a473c77a72abcd8b", +"6f6bccf50229982a2bccc8903927b5d2bc960dbe8044b224cb9b1cd03e922b38", +"6fa3a32e70242da9f18fb4cb874c35fbc7c5eb527c245651a3f7074454e4815c", +"703ddfbbb6c464b7f5718e8aadb800430a720d67f18bd7c7262ec9e692025ec5", +"7058c92f50ca3d4ff03f81014450b77b7bca11c00b65a09a84c940b2c4da363c", +"708715ba463cf2e0824f5e5c204fe29143dd5c6ce8e246d765178190aa3e9c5e", +"70aac25fbb04170b0c853e2010a683e255a89713c6450e4bd5ea3f6715aa6131", +"7219fa6e5d01fb8a8193341d0f5274e0d9835263f69180125138e12ee945d58e", +"7225fa07f1acf861b2928060f63f757b04f7d525474e9e49ce7e3ab70a715e70", +"728957480847a0f2226ae210957a833174819005a6def020c6b284bf708988d3", +"729b061e0749c52102cc4654539d865b7de77c0600b67c9b26a1bc67a157e4d0", +"72a4436566a08b41fb272f486409961496a3967ccea554759691032dda0cb639", +"72ab445beb477f16a3e364ebf318e072a05119f1171875fa1c6ca0c72dad8792", +"7340f2e48c9566b5bbe21d019f8c89d45f3e868efe8aad9a34b3c8aba2495c15", +"7405399346d6d301704a03ec37fef4e3fd70b5011f7ec767046e504e67b981a6", +"740a8638fb4f54a0898041bb3aa1b4e479428db8c524f4cb8b6513137d52efdf", +"741e7c539b542bd4bdc5489b150d238a683aa55726c5ef8770805121763f1e0b", +"742e5486aaee55c085d58786a7766f811e5638eab8d09bd936156ffdd02d5d46", +"743d899743c6eff5afcf30145694b3ce8f5f30e9e4dfcc29e49da407e93a2537", +"7454fb35f15239ff0076217cd4eda49bdc05f71978d284883d9e47b35bfb1261", +"74589fcec630662347c382f43a81c7b547eb542703f8c50d60aadd6cee8e4816", +"747f2d88f1dccd6e5bcb136004ec327a811986946ea58f0b188ad2a80af7a0b5", +"7506d8d9d20775dbdcb8dc26e4faf9f2997f8e73c1f20c4cb6a0b9346827b336", +"75cb420f6d0f16a357c23798ba4cbab5b40bf72eb6c5e40d29d263a2c4c8c466", +"761b7761473df6d07ba455267dc9a6efea8321527fcfb459529c7c5e33bc8a4a", +"76327346e3741359a0df51c2df10103416faa53fef8f02858c9fec01cd52c214", +"771b9f4e19b05683a5d7508776178094d1165c632a93d03860a44c00a51b5eb7", +"7766a8179fccb69bd0caf975c5f7ec2f72ba0040e89186bbf0f3ba69852cdd29", +"77881656a0a89d985b19e00f345cd924b4df021693ae1b56265a9b541299cf12", +"7790d8c118a812da34707d98926bc65b8372708ec4141a467c46eb33ada37701", +"7793ee3ccd1f18463be869a1b367bf28eedfabf670b4e9a9fe05c280d64844db", +"779e3193eb795967fc70bb19a88dbe76c026d350887176eef48f48f0162924d7", +"7914f19448af9e56c2ef16257b1bc424342086f8a08eba39040aba9575d906fd", +"79b33fbedb764375cc8f05a6c34ac1e7f013fdec417a54aae828112f919a20ec", +"79bedfd9d39125c45904e1ad0b43110886c6b7cce6296d9335e6bb92fe58dc4d", +"79f46d6465397d7d496c194d93d16b52bb777bc50743f367e5fc729ee922dbd1", +"7a6350960aa4d6936edf2d4ddb45f01a5bc1a23bcca72670ec2205471789c810", +"7ab8f8182d43c43b6813600cee1838d4c9ce65d8a4da841397781362ef0cb728", +"7bea041b46a72b405ac3ef5f5eac137e169cb813d9aeb9b277483640ee872294", +"7bf3bb12c1828809f237d0de8b97b6719f8137f10079758f8d9a1b32de90f1b3", +"7ce7d496dba75a34f72fbd1372adb8e33e207b2e1daf17ce1e41b9ef2d0786b5", +"7d1f1e63a9792b26ba62ad7ad27177e54441c5980ca194f988f7e93d76942b21", +"7d494fb086b1da8bfc47b76fbe13c53f0bf89a90eaa0b4190125dfe8c7737ad3", +"7d7a19d707c59ec2fb43860a60adffc9c711bd89b685677fd4c4509877b76024", +"7d91bf06bb71d4d4c9059af32b979bac68c58830f4291d0f1fedd5bee8d868be", +"7d963c75f3b7c13eb999f1e3dc25ac6e65c683b3bfb9b4e4fc5a8dab8da232c2", +"7da4d7f478c29db68fe28d9f9be7c21a34b96240804911c668e4307b3a4f5e7f", +"7db45ec092d1e5fee7b95f7659f9bd9aceb7ba3287ece8950c1a650abe3a4526", +"7dc63b0e876295e920e9bfd12504b9f7c4b85f1724285d8ac441e3ac642ed7c3", +"7dfd0b3aa6533d91674dd7f44cdabfddf0a5ff7c232495443eea7a2586f4e87c", +"7dff6d716e664b88a7996a7858e246542722f748a6ebe98fc8193af0c876d817", +"7e02137ce984537710aeb12680203628ff0c0bca644d8ab876183c91c3590dd5", +"7e29da8c0c9b569d52090a8a4e05578e841da444f1de80958537b8b0c57ef0f6", +"7e35b9676f6e143929d1d0a7401492ca6b735759298e86842ec937d6a4f9ed00", +"7e9fca684c167611fa73c96ecd90f3d034c289223ffe436a8bb1712b8487739b", +"7f5090a09888f69ebf4f349e52a81c9db5bf3d3480aeea5e3638f27b50c428f9", +"7faa66c9a74e6ecba1d217316348dd26f77a3955ad2b470e90d1f1ad5d252763", +"801477fbb380aae6f1fd021fd63fb5d22d021d745997cea163497a6dbd82712f", +"806dc47f0ee4c87e1494c13c98a9c00d7f781f3f7d8046ebaff8ae1507236270", +"812db712d834f2a859870437215330401ba050b796996bf25b708ac712f4d9e4", +"813e56e269ce416236e351ab98ae5a8da2c2bc24df632529960eb56f4a5f5d8a", +"815c385909692679bf70524f2cfa7b2a29bb600f8641ce450bef34c2850368d1", +"817f28d5c20042dc761f8079bdb0315a3d77805548de1d619117149dbe887890", +"82357c1f55d2b2622848c30661bda420a1ec4b01c20f96b935c3e4c70442ea03", +"82429b61e99c73fd518b4f6e84cb722a1e5b730acbf92449b5e42420b8795670", +"82779c5415b3ae646e588d990d7976c09b8aff1bf2f7468e93c787dceddf508a", +"82b76958ee4cd9de1227e710dd823da40674d081400f79cc827e82b0095f8ae3", +"82d9e277089773ba75b31db62b10233e3f418c383625a1be835a9e6f2ca0c5d3", +"8305ce6302ee2266292eb1165afacc7b79514f222e1b7898853a0ebccda5d70e", +"833eb9d97bfd71f730b6d699e348dfce9cce39051d67006f016b0ea9010b1b19", +"8351cb9acaea335a365bbc13d975a410c9ab77ae5d6a6605ac46ad74a048e71d", +"845707a7e12d0b72a7be59a1bc65ec0a359ab65cb30bdf1b12724b41be36d30a", +"847fa24a6c46c117b89180d579157b4707806c0f7236b4546843df3b86ab531b", +"85025f89bb4adc7b1af3500780d4a96fecbdf7ec92748beb7081c1524e611d23", +"854cccce38d91927b5ecdf7a698032048873a202f83e2e2d07183b7357918cb5", +"8550a81b4a24e1ade6c00311ac2346e71ae1a9dcf61265f21864e1faf03c1df1", +"85583915baf4fd22bd6b29385d754d6a9850969c5fff6cd788ca61ce719a495b", +"8576310a71ea0e72b0033d198a692a778a3c0ed7b6abfffd54e6c76a7785d3f5", +"85bf013948212ffae055cf280c54c511798f13b62bf94db0a3c5aaf83bb0da93", +"85d5d7d63b97c0e27b473c28287600ad07f7c8107369c7a3e32430f5c011bcf9", +"8642ccdd7b07b8e3adab6b49aed4562c6d04bdad63ec47714eefa1d1d65456d0", +"8666a378b1164d068a8d325d9c11692f9a6a79ae7e2ef2f72521e6965f5fd14c", +"86aedcb0dafc2f7fe88c498b49d1ad48eb0366c43d2edb2603ea8ba6d2896cd8", +"86b019b257f8cccef914b22857ef373b175a4e75852ab7336d112cb234b07409", +"8740932f7c611b1a6a64894370c8df37604c8755781a269542b16b1ac4794f2b", +"882a62089c81afbf5ce58a0112744b8814a5aa8be328c158a6d9bf5d0e676b38", +"895d89b8a94921fb1475ff7986a3d0c4def81a01adc505d5cede7990ad497180", +"8a67c36720d61d9acf46798b1a50658cc1807deb1adf5f9c035582c2250986a4", +"8ab2e117de4268dd6351b6f30b25eee184211018e85c362de95ac6d99261eec4", +"8ba968865d5fe5c745b70a739084c95ed44412f19c305f0476060cf1d2e5d3f5", +"8c18ad65dd3f05e26e26d5bfe816c2ff3941f5af269771401947d1d07144953f", +"8c2678c037fc9435cd3b46b47423c814360dcd3f3ba5d4e8383311132911fc13", +"8c2f7105e141e012d2d776d14d01429db6ec0465494527397a65cafbc7e90647", +"8c4160ba8a7be774eabf6001fe9fd225259e37699978666b963e392e64b335e9", +"8c7b33dcd60c9cdf01a942b78bd019d84262d8f4f7168e6348c2d8f82e57e82a", +"8c938d3a1d658bae7131f2da052c83e82ac0e4ad68f33eea14d79e382cdc0b7b", +"8cf837a1f020b9d1d82035726b7cbbc1924065f969771d7f15d0330d5628ea5f", +"8d12ff2d891621e8ec8b40b30133535d33f2f7c772367b6cf6f3a7ca99585c2f", +"8d1ffba86bfd3e2a0edb6b4e9a04c6fb23bc2912588c1f8f501992e5e94d4256", +"8d3adbe56f63ef4d0abc87235f5f07da9c84cc7b6c07dca1134de3ea0eeb464e", +"8d80d27d779a08bad79445995b40cdfc967f6f4cd1a81ce57b8355dd1273493f", +"8d8dc1d563c585f623f9fec12475a6f7aa060bc473e2cd32185c655850d80abf", +"8da0a770826004c4a37a0d74dc8d294e189bceb4dbcdca52d0011331240986d4", +"8da8c66d56a861c6bb52d6e12d2488e4118b93bfca4b60671fd92c12ed3a34c4", +"8dd466842944c2e88ab2eda955695cc6fb7afba3c0c45539aec63255465ef0f7", +"8eb75a8b97ebe66be4c2bb5f5fb526beae9aad85fd4fca6515681763f09d8645", +"8ec82cb5286c7d4536909e1f79afbefc203b4b64a77dc1fb2b9549c43c5af7a9", +"90d611eee19c011390205e9130276fc88164f369aaa57e2dbd1a1c540fc655b5", +"912c97d13bea7423aed6137729e399d3da81889c4ebfa8af6a3689f10517288e", +"9172db355c6a0bfff9d64be62c508e7b7a7a29d1b97e9c223f29e78e50f214bc", +"91ac43125d842ff86c848f1f4e4e3814ec8d1d5a66af5469a6fcc54e80302afe", +"91e9f3514429ea59f417cc0c18de1fb7e8a6c0b42d8a20b19b67d0cd922f2fc9", +"9213a8663230599d67b698c815b805c4ed2afded7e32f3298389112496fe22b6", +"9333f7d5e5f20c8a5e190f5c2d47b8c068b57403471614ea6abdb4cad987736e", +"937a72e54843d3420544a0a1e685c105a72b363fbe50bd441b01bfd2a0596c22", +"93b483d7f8e15f43117ed1148c8c07a05c73a7d5a1d7962dae66458dda8052fb", +"93b7a10ad87b0e0fbaf074318f6bf26bf1a0dcbe851b042ec8c310f13bb2bb27", +"94de72f54c1f35683f9a5953ef50d35241bda08eaf4226374dea7861fe394377", +"950bb380139f2970fef060a4b7cb8cab47ac6e894c17db4847214176d71a8309", +"952e76b8bfbf1bd710fcc776958b35458ebbabcb79d7325709f7ad2c4a8c0474", +"9558f303fda9abbc350eb7bb2e21b080881da5e7f45827a9b4277ca1b3d40ac3", +"956c347527141bdb666781019c595e8550f83a8066c1405aa77bbae43ebfa0a9", +"959e3b906efd636d95871bc29f6a24e9ff529a1afdf061910b719c7c3238a63f", +"95bfc307a4cadd5b53237c38ab89732ecba367fc4047f0b28f3142ee7346d893", +"9628ff7531f4b3a6e438aee7f8150cf2df4ca28d0b9021ba701b8d5f2810c0c1", +"974a90358b73e571aeb70bb116e0312c01c2f25e9d4d8ef44ee5aeafc7f8752e", +"97a7b33f98ee755c106c3d74d7bb43d2e0efabd4c8e43e308675649fd160af1d", +"9812897cb1b3a2f9e5456515cfe1da92d65132b09b77a23d32572fee46666e1f", +"981ceabdf18a036f1b31476db256c35e777c530438dac4eb599857e01bad96f3", +"98a5579e0aafb542718d6f10bd045621cbd3e36e86b4c49db0f16358085a6554", +"9953a1bb578cd7cd0080f5ed72baea76501e3e5bf28d01a5f21fc4ea0e59383e", +"998f1941190afcece028c77541b1d1dadf68a9ecaf1b433e8b038356e09d545f", +"99fb87970b354fac1b3faeeadea2d486727b3eaaaed5085f285d6388b74b550b", +"9aaaf49fb60b08bf0b11adb8fba64d46f300a9552e773d09902d65b2346b4d8b", +"9c15b3d83e171d359141375d1c706ee88ca6e649ba5c52e7f5a32a44ce4e7c59", +"9d5731654cf81fbf4de388c078a706891c672a5f42875d416cff6fbc3fb2c0af", +"9db13d4aae4424db994f9e4571d40af396314ac057b4533f7e28f2697f90f60d", +"9e9421d6bb3e5779cc0e2bfeeb7d277026bda087fef458478226865a466e9f5b", +"9ebf590272e80ddac92c929b0c68639863a5c870f02a21ca4e146c5dd825e4b2", +"9f46111ebf5349117903dcc055773dc8d2a3ca746dd1b6f737ce3d18853b00a1", +"a0207f0aab71c10809cc3334e7fad09fb1b184e94e41b71ac2fdd58bc1f33e2f", +"a0ee59d3cdfcf9df11ae2ab11222827ba54d8bdfca4556e2ddef86b6ebf9bc5b", +"a12ee161a767e55b1e7e1a0c341ccacc6807a336b56c752e68c53e476427bef5", +"a1d341eb7ef5ce3ba356ff0894a981fbb54297aca5b6041adc239e9d584d32f2", +"a1e0149a2896d6c374351853f75765f1497d1cfa589f22399d189d30b85873f7", +"a2369b8d3cc1bac5e71845b21d86cf263faa92a76b1578f61d19dc9961cca224", +"a2aa0f2fe085630ec0ef538641d87f54aafe4e15c806af233ddba19a28c82a60", +"a2cd435677b0a4f04805b2bcc74b17f23c339f04a4087425c1ef08fa16638a1e", +"a2f2baa665e9e93af3b0aff4b9e5875cbfe628044d6013445569bef4666f7150", +"a39bc41a07e47ca93e4c7744841af7c978ac3c00c7a8dbfdc4d0a635b29118ce", +"a3b0aacbd06446c64d71572d8913ad8882a6e7949226f71ed331abb4536309cb", +"a3c7f5ff3b31ed2f071f2c76dac1518d59b893a34154a38bdd798ac836646251", +"a40ea43b055a0c07b3e524f3491afb24f408cfd7c2b1ddbb913c6a76574ff0d1", +"a47e62e4910f3842c004d2aaa5d842fe77dcee04c225e7e7e03a4a6a99326efb", +"a4d662d25f921f0cad3c5c8fe6bd07af3493dad59e94db8e1d2b5a6e6a72242d", +"a57cb6d059beb17e15f13e0d318a9d3b06b60ae8651ba389311fbe2ce8327f58", +"a6268893016711ef88f25f4540f3f529cf7a3b56f1c0b862dc569147d54a6885", +"a6a073ab01defd1a1263add0e8e74a726560828a3efc55ae63ebc2b2bfa96cbe", +"a6b136a0d4ddcca72c0c36e2c33463320be85d45bd029345390462079ce8d06a", +"a7d4d13dfc879383b471f4594907fbc37cc7ca2fd84a7cc7c192627fb60d6ce8", +"a8440171ab018bc8cbbe33fbae4bbce86641137ee747c64c48b8df22928f33d3", +"a8c1a26ddb3caeef57146e17cee325f8113aea94e0f71df48a8d84e07f59c9ad", +"a8f40ef2d66582a95bf1ebea2c3ae0f94f4fb7c4dc6a327905df5a50dc1a048a", +"a9c4acc6d55182353d0a5183a646f63d997d747257cd1d84a7cad903f5c0ad24", +"aa11f48e1202e7bd58d0b966f8d9ac210f6c392cb88c3384409eae5bbeec335c", +"aa6503c37b548c8d1c267923e15ad8ae8a9355fafc75ec0df64d0017661b95e4", +"aace9b30c5c3a109a5cd2f3175225d36b1c669326c1b7b45f50565e84bc12a10", +"ab02e6676f649e898716c33a25d4ff41a2e5a1a40f179cc4aacb33577467c1da", +"abb429a5e938e08f1baf136b951072ea1ceed8009e900c74fc68281eb1035df1", +"abe7af27fdf442f39b5bacbbafe746444f915bc0fed63383b56645ca0b09a3fb", +"ac9e883806ff9b8d81b099162488120a5eb1ecd0e67842a621ec80c2559562cd", +"acc3eb4dc225169a38b2adfda95fe88493a8a6c703899a342ba8477e303a82f5", +"acf61bc2bd263e51909eeefb6aab2436d77fcc538bb67f91152886dcf1b30efa", +"ae3e67bf2ffd63bd789cf63b56770c54de1e4dedc067a22b9cc27928b8368eb6", +"aeb2a4c400d2e8632ceca2a14ddc5f88dfc9ce87eff25d72d7ec586c6ab11fd7", +"af3032f6b7c3d57bd743d9fe8475c839fc7d303b9f5e00475dbbffda8f96f2b5", +"b002598b4517ee50d867b9a363267a10c714860e4d1ff91737241af339cc0932", +"b02aa6cbf26e971c7498a779741b3694854195ae5d7efd7e939e937128074690", +"b06ecbc32518a1c58875c0f27b73873f35990f71ea26e391da1451109cceca75", +"b07e9b5685b0df3fc14e4b5aff3e8de3baa6a8e8301a9ee634feb0d2b71eb900", +"b0c6cda501492e5e27959788980d86232bb30cfdc4d66a32cbc737f2fdefc325", +"b1497c0ed6ce5ac86762092d1c297e5c21bc9f7998fdb9f557cc38214902a7eb", +"b17537bd53af132db28aa6cfd90c580d05f855ae703304cf6fdd5f880a982145", +"b19f31eb7afa92cba51aad46d83ac65b9a85863b859527b7903465bd1372dacd", +"b20ef4b33318ec30c99f9e9c04fb4cdeaa2d5d214040332be89cc008432b5cf7", +"b2612b94807d115b5dde40a5e141f3dd2a37668e70a85fe0d7e337a512f53436", +"b2714917337f13edc80694791c23cc2859ed0cb648300506f1916790c5f5c18e", +"b335f8cb071f918e6e69db7ef2a380869ea64ee18e4aea75b61e09d60bdca471", +"b36bc447d30f483cbc401f883793008898f8d21cd0026caa9ef5011ca092e980", +"b387e1b6aebcbe1013dc635b3bb5538b211f05965897ce6a44f4cd452956de54", +"b3885304d53b923dd5dfd8160fb2d96705d346b1fa259527c9a89cd164d69bc5", +"b398d393b60d32498ed4b47e7f5dc9352d6728d3aa2b6f8dddf16efbe9dbf5ca", +"b3bda99fa07b541ef1a6028431a119280204c92aaf748ef44c9eb33494d40e0b", +"b40826ff1790dcb31ca602854d3e74479d033e6ceabbb26f01c18acbf5d14238", +"b422c62611be24b88203d0fedb1d9aaeb048b8310d6dd7418ed44c79a9c9a2d3", +"b4a32f14a5ef694667ecdb96c38ab9b53b05d72c37c8639bad4308ad3c84a485", +"b5075bd276b3c4284ebddb9b35cde17d3392f5bd2cdb3d94c10a39b7daae29a6", +"b5524d0b748f0ce1456e68ee2b2432d3f75941077a491327712a02187eb1ce97", +"b572bd175b76310e97b125bf15347cdc492279005bbec758fd82dd634c47adb3", +"b5b2c6e15e6dbce0d92e6e1c8421f9e2f1b7435201536a1115046f1a5c24ab0d", +"b6139a32ce0ce918faffaccb81eb0af6b7876eb16c45717b2138068d535b94a9", +"b61c5814d897e82027ee54d72916e62cdc9b68e4d8d86e6eca33341a1c07134f", +"b66682319f8ad024cd3b3c95ac8dcd8c867ac42e34183ec62c050bf551f8caf0", +"b688ce77a6a1a05effc123d310d564965380f8e0b2ae83a498f2f1ef925aafea", +"b6c52f67bbe89a9a034def0179791d6aff9302100c6b906c1ca87854c45f7844", +"b769aaae3513a203755fd86a22d08b86f231bd9d6a7ef747c12d080ecf048ec5", +"b76cff990e2d9f9944fd7ffc8a0a14563f9a09b7336e3d6bc5031c4a2e863e0a", +"b7e79a5bbaeca159428eb488309eecf00d31adaa1018302fff2670d8674537c3", +"b85a58e7dbc835b3d730d17ae598cb50c7cc89b63f592d4c006d7f0915e0d4cd", +"b881a44495a3fb0b7b74a1dbeba7a864aaea3be95caaeb9cbbff7e97c95df5a3", +"b8fc45a4def8389cb37729a365e7587691074f379c1c2a27ff3f0c0dd6119461", +"b91b108fd6328800a8c019ae609e4c721f152d3df027b6728ab9ae31126f046d", +"b941eacda36399b92deef7c2e5bf2ecb7a767a10dc75a864c9c790d262884efa", +"b9b775123a94e3d72b2d6e7b03cb630aaeeb557e68502615cb1c4cc2868915c9", +"ba0f2ecfbdc10784a2e7908191a65e5ce71265656c49db0b6688f416783028aa", +"ba2da2413e58d2a4d516c43fb6e4757045f00454e488d64a77dc3de9ab841a13", +"ba3fb6950678dbd56deceb1d223babdc840ab9029e6ae82fbe1b8d8f17661f49", +"bb2e893fc178553b1bc69cb28641d3cb9c8dca4c62f61ca5674899ce7eae434a", +"bdb1eb23f48773ddfc8539f9274e503cf6d254a38eade9f61c3e31e3f29db140", +"be1802fc8945a1a5b8b9ee733950e1363c43b8bf09a221f8d7b0870d5a72e002", +"be3f40bb9d6956124eb960b86b473f97b6d86b40179cc832865e2bafbd2b16d7", +"be8495504f504a16d1f9aacfce97c88188b196fbe0200c9467f21530b715013d", +"bf789f7903f27e97c0d50fd250ad145ef66a4e49bfdf026cb3ae1037937f0b1e", +"bfec5e5f08608628d76b8507d4826838397c3025ac9d83df252e2562611de4f9", +"c04da726f102e44cca0335a4d8545505a858ddb88024ba02c59b65ce9373aff3", +"c0ac1d3c6046d21b0d19f0b938743c6d0611cd198318216ba4127447e8ca4995", +"c0b7b81da30bf715ec43b70fee354b4767ee49fbdc6bb00035f72fb407c53072", +"c0ea3b2416e056d89dc8d4860ad03ee684629e9b951c98b8030b56be0351242a", +"c0f69054fdd368a45dc9df80833ab41b3821ff10261dd3ffc296c5aaa15df7a8", +"c13ef7b0678ed3b4bd541f133d359111a69cd47adb73a3f213eab02171a480a4", +"c144f305a44d0f6149429927ae40992604d5aa6f1cd9a5291b25d2e5caa00e88", +"c2f46d2ab19a37aaa7ff39f9aac18e6d619aff7621b11f2921b44b8b737e2036", +"c40a8cdd03f316cc6360825f4b99c1f744c58f978bcc7c35e12279d3b2062ba2", +"c40d70d00cc546b7fa3b545ca0573899b6e7b3e260354b18276c0f816a1339aa", +"c458699b9b9b5372c3033398343184d3dfeb4c67902a7dfa8e8f399053a7e920", +"c49ec7dd7563e86e51c750ecb1c25e21aaff726724da25d7d1287d7288798e4d", +"c4b83410c0a7a779aa50f80fbe4f85fa9f735b2f41e2d5874f1c994354650e58", +"c538efa7d740b28165ca6d085628dfb6f14cf3b064721be04ba29c3b7be97135", +"c5ef4d5c58fa2fe03a022f20fd910153aaa5e6b22c60eb2f32da274f6007fa56", +"c61d41eaa53d2eb8432616d618835e2a9103fcabed13be28b65d0991b9e91d2f", +"c6a4029e37012eb65a4834094caeb6cd8059e1769234094a512751fe61ff5bd2", +"c6d6f3b087fc21c04443c2718de3a849740d34da6226276fcac7e79e117616c1", +"c6e9fbda0064ffa2d91cea1c0d414b61b79646f9706724959feb6d9b6885db55", +"c79444b73c2be39d31938dc476dd4ead5474600dc50330d2e00cf1aef0f44d47", +"c8956ee9b4b2f22bffb2e1313b978851a2ba40dfdb7d6a900bee53c0063c8093", +"c89d71a6f659a0690de6c7ae81a2fb7d25aef0b10864e7a1c0401cd79172da23", +"c8f06411299302030dc94df149e12f8db5267efa86572067dca592ef0ae72f97", +"c90e1f2f62b4df1ee054e6fa468d904f144f15d923f1a167ac591bf5215376e3", +"ca1effebd6ceec9fd29af3da34c7b519020fa366f5bb209506659d201649b526", +"ca2a75809bbcc7b11b3106d767c0b5c4e61fad3033abfd80b8c7024f1b50760c", +"cb169159b89b98dcbb1c0be75539be137ca39ed69d7f0c0df03f5b27e062da20", +"cb95970cbb382ab5af8b45c194ee0a386e313566cac0d32ac76d11b2fc5a67e6", +"cbffa46d6d8eff49613e586ed9cefd6d50dca7c632e489fe9a5db5e19c6f8646", +"cd17e0713701812f08ac92c3b43f6cb3ebdb81f07ba1524e81ea668f255f84f5", +"ce2153385a3abd393e48ef7aa9a487ea097af13b6b6f778c198b723bc0f51fae", +"cf17e3c4c9f4985f29abf2bf19222d0531ddafa0ebe18b74d05a89d9028d2eaf", +"cfa473fec3999e51337fed325c6da1df7f027a9f97b1de049fd2c196e97ae755", +"d0f17caa9b401929f9333073e5ab4421e9cd0e39b5946d3894a533fe66256eed", +"d10fcb346876bd804d44f22a3cfd5ebc7ded0ba4f5f0c3d0d50de92c1429b516", +"d1a357079b7ff24706600fdd45eb12f1d6704bcd4281f09de4a9ab41adf3d419", +"d2c006d6ca537749c985e04b830ce17d47fd42e7a2ab1a6123c03d3db2838ea0", +"d2ff7fdbc1cab96ae8a4ade63179a29faef0825ab296615fc353704263281146", +"d332bc97043c94f72604b31cf4509f306cb2f3a6822c68db7985d63e9ae1587a", +"d367a15459b7c4280a9392beb3b3670ebcee1a296e5ef1e14d4acb83af98fff9", +"d37c4b5f657fe98c2e40d22d049163a379ba3697fb6c1e9b27fcd8c2944a5d22", +"d413fe20342df3c8621929fabe4f50fe885b13e719dcb1f12eba54b56fd6ecfb", +"d438996281c527e53bd2ff73faa25462f0191a2bc9fdf3c0e7d4bb5a458da050", +"d4f530b0ad515731c628ecf70aa12919b861de2244607811f9e74902e5891b4b", +"d52cfa54686e2fae7db1c391b754f52e12c2e7eff3b90cf9aed210e188d98a86", +"d5405d840b7d738be0e401d42b9c2d6c6e5a36a7a05357178036c0a3500d7c47", +"d6138be7bd511588f2f3cdeaf37c1fb26f1aa051930170834c37adc8c72204fe", +"d614cecff549b32d73f5fa72139c575f852629cb7c53835d6da831736145b170", +"d6d52bb3c8965a95b8520b5921dfac30a312d8db4c35e7deac679de073549970", +"d6dadd094d818d1aa19078dc418f3c11ac97b36bd857f761d39ffca55c59a98e", +"d73d18497cc888713655ee65b3525a502b9758196b0d6d3f81509f1c78f3d347", +"d78c0329d621cb71cc6a30d3e56bc98a4205c1741fcacc450c264acce9fefee9", +"d8f865a34c5d20d0441ca56df7744bc2f3f86412787f4210c5fe24f36cb22a97", +"d9441a7825585aa7ce4a1db1f52eb0b2e8e06afc53d76c07c5d34c19ff7b3eef", +"d9970b9029331ec5b646bb2c00ab8bf025218b14df46742f1db7184d9a7f639c", +"d9c6622cb19d520d7ed30682c65b82afe1afb02af408159255aa9b28aa003f2b", +"da702f1071941958f446f887e753298b9d5600631abfaa2914ef789fdc0c6b6d", +"da90c6cbf2137cdeb222504b5aab13f5745764e56a2a9dca5bf6335d0ba27653", +"dab55adca8d2e7979a221886216a060389a8c28eb17a4699e924f5175c5a2e8c", +"dafed9f1c7c62859810717b8c39e45c6d38d06f82d526e56eb5686fb461a7420", +"dbe966f0bf291d2f852ebce75b722282f2e78b45be2d4a7ef2475626cd1d5e29", +"dbf0ac3bf82be34f2ab3261eff345c8160f5ba263e5df596f4165ff3f05a476b", +"dbf4defb38fb50f3673df83415855b125656f98ce0b4cbd9ff945eab84544617", +"dc549ae979919af281eaa66e0b77589a54c868640665ca1a7f8e7d6d8b2777d6", +"dc5ae132157f07517d9bbf436f85c7d06d383e67974a0e931126ea6ae6b0604b", +"ddf8fe65ff1bb1471dcf50d9c9582f4d2e45172ac403f795f94c93603d076dfc", +"de17982b2b795a5a76635598fef165bad28b6eddefa953c5eab7c2c58099fb79", +"dec3fd28760fb4371259c11bd6a3c8da74209ed879fcfea85f3c5bbfd90db0c0", +"deeb6289c34666860513c7f766cfd16160e4aee511f7fcfbee44c2e56478517b", +"df3f12c0246146c55fc971b81b34d033ec768f1d1e7e82750cdf8bba7431f246", +"df9059d9f7f24219805a11ea50b73433d8a6ce7cf4af31fdc2d9ad7ab10db80f", +"e09e77de453a208767d35955ef273072743c332d4eadc7a444a31d95d334af29", +"e0cb2e68da5c2a22d1f611050460d27bdf120fcfcfe0b6d0a501ee7d5a599782", +"e0fd6a49a89689b5b7a9ffbb0c024e2e549e827caed6df896b1743cba7931bd1", +"e1571f2032c913fe8d466a05f81141c8a78e63b2c4955f607ff84bb8f3276c8a", +"e1d0595e5c8f2aa948daac642306023db0c34233fb4693f59d87f91f83765ed8", +"e32b41c1f421339238bd8518972651f4b860eaf9d613bde723041ab877c4fbf2", +"e33321c913f6af442dedc4c8f6ccb44286bb4fc1bf3a9ed3e36c3c6fc71ea5bb", +"e342c5f98ddc557fb938d46ac99579e5c927ed2929db4ecc0b7aecf9cc8f1931", +"e350819b29bdbb2a4218fe99b12bcac5ae9afe2504c3586e21627eb497621e1d", +"e37c436163b831cac6284eb3e6cb9848946e756bb639705279f72dc84e4c4ff3", +"e39edf70ec8f6d81b566a6907df63bf8b7ca85e453d71273d3a34f75e717f9e3", +"e3d61a55c9dfc335ca2be1ecc0bac39ffcf17c621b5805505128bcfb44407623", +"e3fb67b8d5d0844433f2306901a26196669e047160cc96d4641e87fadea0c408", +"e47dc8fbf8286a8d1b85769c05d3434950ff59e12c05cf5fe89144513fec2e98", +"e48ed7b1f444c282edce46e373d2c670415d18d798cee113739b094863c9dc56", +"e4c91ad52da7d4b7f582e8772aadbd311499f70098af0ab194fa6053829e7f03", +"e57dbec2d57d240f74308e8b5f59a6301efd74ae081a6a8eaefd0d3bd29a4190", +"e5bf7ba6b543615982d70d8fc785c9c1639220c1de284ab1de43a34f1de3fdc2", +"e5c80a3cf4e56ce81db7c5fa776925d26e8d5a841416d7ed919cfb24c407b158", +"e60d8df101933e7802a456df4eeb45b98f8d7db511dd9975cf6704bb2f30339c", +"e64ba5e7b479b3ad54b7b9333e5053cdd43930ec5adcc8ea37dfc4f42612dc72", +"e6955a326839da77307fe806b976975c9e2c4c93d237f9667abe9b69ce74cabe", +"e695bc41eb0ffa1c2dadb390e5294522bb5d0e42802fb7b47957b0f5aa9789f2", +"e6a132751e0e55e969a5ceab62483fcb85d06380a37e912e4c5953a476ddec40", +"e6abf1b643cb676f6bb587cab4dc04e607c3fb0d4c142758b90946fff137ee7a", +"e6bcbc7f692c3f9c847af822735461d83007f9a09956dc2f71b2af98e1d1d380", +"e7088919ca800eb174780758a6e656712af61bd7b9e4aa39fc276d9696dfcf85", +"e7137a074ac85291ac4ec39bb06103521225fa05d3c2269b4967afd6b81680c1", +"e7f192929ead8728d678cdf4692106b3427812b23a54e0fa8159d4942f08516f", +"e81b838b47cccd2a490884e7d79d2cc2a10cb6be50b90f11dad729a408af107c", +"e8f1bb9ae9d51ee27c1a437ec70e07d1e5d4b85e1b0702f0f1defc2a03b9a815", +"e908a268e0134959707d8d15582b97f9faa86f80c3448972db640665c5f58831", +"e98e80fa5977235c6895b411b6518ab1d084d09a097efa97a72c070bc242d85d", +"e9a9f260d31636451f7c188851bb54c9e7208b413b927a623296791e13dcf8ee", +"ea2882ddc2f7824741671b9b8e703f0011a64137652cdacca940ffe538585755", +"eb16d0c1567c34dc4217e2916bec37c934bf9c7c71f1768960990a563fc273e1", +"eb5a783ff603ae878af092e4b66e0bc22ee10f2768daafa5e4c0a1cfaa0eb547", +"eb96d352e986039713b0ab96c050193006909b1fc96ed10d0828ec84124df621", +"ebb656612ebd8f15df6682db342d57f02409ec9395edc5a39fe01f3c330552e6", +"ec692aab6dff6825a05baf7c90737dc2b66d1b1ce13c25d61258f3702fcc9403", +"ed77a1a1da00c4dfe100a8c656ff1d8336d5982b11a8a0c8236ebc0272fa631d", +"edcff1388f91fd80a2b62ec31cb0492960ffb62206dd9e01d8690dd24ca7cf7b", +"ee194bbbdf6b9ae5405d1e2565427a50c93b2fe7b9ac5c525fa6f2cde67c7e51", +"ee1e01ec7a5e9893fcf8470aea62c03943c795d3b271a7d1f764a255648b4b7b", +"ee717e1a1ce1162ca1bf48a49874ac3a07825c0a131a928d5f647fa80ea19177", +"eea120c9a37cae64352df0b7a0223d8ed1a96561c8c1c6558e5dfe1242969c3b", +"eeb8a491df8df8d1369af7f56e84301abd465a30284b4c9d9b3742faaa21f2a7", +"eed3f14a42ad30a4895ac71dfb66f4152bfea5f6eee2a50097aa28320400915b", +"eef086f911b7483149da38088c50a19208409156074d37f787b86d3f2e1b00da", +"eefd25a321c6c29532a0971af7e28c949c0afdbc2bd005311db2bcb8b7c2c7bf", +"ef1affc22033b8c329eea7de39ae99a4c206ce7cb13a0ae18287d027daf8443d", +"efa335271b61f6468fdeba3e8f84a9909b5d10eed195172368045e05548979c0", +"efd61d23aaa7ccc95a8413373e2c93465a77dd934207fd093e876f9cbbf6527b", +"f02249c03a3d62665d33c54336f647b643fd4e86869dcfd957ea498b5a3bab1f", +"f10193b34fa878cb3828e7df1d56537afc19d20f7c3749b8ef2a3da02335da0d", +"f15cd0e24e9956c7e19f4327b1e162aa41c83442df251382adb7b14403bdbac6", +"f17b282c97be3d57cc033235cb2c36ed993b3a2983561c8790478a146a8d79d2", +"f1cba5c8848c8024f4bcb86f09a6d698349a01a9eb7ccc146ee395e3c34140dd", +"f20d92b13b27733d411c2676486ef7281a72da05f8b29c8c06ff2877eb14c35e", +"f2bd54d61f8b12a7f2305f0df2125c659c71f6b0eecb65911db05a6f4f91a50f", +"f2ca83b3ca7f974607cb5285699b42002bbda937a03bc7d8b76227f5fc0dfb75", +"f2d3624cc81db6dd6a6529f801739066e24ba332e3a85d5af0769f3598338eb6", +"f2f519e3c719d330ddbfba05fdc5368cda0ac65536fc34555cd9615e0c4624db", +"f31fddc0966b0561b2aa5d6436732457252eff51dda4022d83713c4a597b67a6", +"f35daff8db8ff3e286a5b4704c7c24c954dc11ec177aec756c613c3461f51ac2", +"f39428f690c49d3c4dd5f428f710b3608d7e75be2ab316c091c80ed31aad2a5a", +"f3d84962adcbd6a03ac169a004a0aee70e6e49d967ce10c934c693c1babd5e37", +"f45b82f84bb1b477447cc9128cc7a51797f28441a89dfdcbb17df6dd6a0da492", +"f45ef3feae28bb0ff5600cca630ab000acad15e8296d97e4cbfd425b4bce1387", +"f503813b48f51d5712d6bb64828a3e14877b9d5f40b7722df4c2ceac1ef5f9c5", +"f632dd3b7a4e36306ae504ab2dbf2dc4f171c0ec33fa702cc30642ddf6aab789", +"f79256f68b2011712d0d074248876caccf98614ec1d15d84ecd4a5a7f02576ae", +"f79373cbf026b4737dc9a5e69bb71112a91d2fcd602b93b7b9cae3baee4c5804", +"f7e3344ae2b06b8bd3596b54930b6af055c515b4f9dbb839bc63b1bb13e5efd8", +"f8450815db8e2e8695db5da777fa053a80ff80f747175c6653df031211bc6607", +"f87c92566596fff9083a67d6a810575da0b01a63a8c6c6026b1d120f548d6951", +"f890ed99e394d322712db3d9aaeef36710167dbf6c71a31a13e1158efaeee755", +"f8d924bb9bf40a313c2c160894aaa3b75294be55c349198ec380706cd6997b90", +"f91848f4e7fce0036d2bf207f9488ada0c3d0d8a24ff22bbea60e9d331e25f41", +"f987b68f789b31eb610e2552bbfeb1cf6c7b0c962109b3be28bb079c26eea9a9", +"f9adc5269a86f7f5df0bdcd20267bd2723c6f66bf0704879019af4cc85db193f", +"f9b21276c4fc9b6f3de673b2b2c3176dfe0594155f4046e28bbcd83236fce667", +"f9b3968c19691e8db10bde4bd06fde35f0d081e7ee9e10cb0cd320bc20558f96", +"f9dd719319a9bc015d0a80a32589873603808a386df04e5a5372cdb9894704b1", +"fa278d51fc6711b3d14ec7d230cc7f1b2fb57a894d5b1284d1f73b9643b31f87", +"fb284598c4c59f69abd77e0222a5d723e44bb217f34176151b377df92c0bcfe3", +"fb6bbad84d35d47a49eaf3fba088228d299f9efc792e96c8ff6910d4a8fbbb6c", +"fb86bd928ef2b1ecd9918cf427a3a91e24074723922bf8e53e616f698c70c38f", +"fc1d38a9ce46a7fb8b0b0f0cc0ac3a5f802d663ab5f4c2aa5a76ba885f78f6a3", +"fc68a61bbca0c9625be8a30080353cd71fbf6f53b5e02852063c2ecd7c591cd5", +"fcca7e635caa12b17c68ad65b9c666b339232c0a963eb882d4a17ce7a6b7c509", +"fd00432172be122a36bd1fd86a1a200b14cadba9b3f38ffa361b933df9293c10", +"fdad07cf96335392e4b7c8004cfc1f34835c59b66827bb05a735f676218c72b3", +"fdd5a1169ab44e2cfce3a8609d63e88386481f149a198f9e956276e7598ba3f7", +"fe0e2a3d68aec63785b880811ccf19a70893cf9901e48036dcb300f49b2fdb7b", +"fe26826593168d80cc58e86dd22161129f538d65751fbbff81adba425fba4e05", +"feb3400d62fe9a150da8ca8c930f3eae195b3a8f99467d88c5b5a9bf525e8d3a", +"ff82ff74e5cbd2b06468133d88bcc5d260cc7a3de73fb35192dcc87e78cee9f2", +"ff90e9d931b23add9b25c3c4e5b1f4d4623622aca888ccf18e59c96fd43b5a28", +"ffdeaffdaa820f860be1e0d7722c12b8213f93f7b0292f15e835408ac4e45d45", +"fff0ad60c32b99edadf3d327393fec3e5ef0ed476666528d8b86ce587fab4f23", +"fff6592657f29d91d6f9e3fe76de2eec9d461173cd7248a9ff2f065393234bb5", +}; diff --git a/src/veruslaunch.h b/src/veruslaunch.h new file mode 100644 index 000000000..de081e11d --- /dev/null +++ b/src/veruslaunch.h @@ -0,0 +1,17 @@ + +// Copyright (c) 2018 The Verus developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef VERUS_LAUNCH_H +#define VERUS_LAUNCH_H + +#include + +#define WHITELIST_COUNT 704 + +extern const char *whitelist_ids[WHITELIST_COUNT]; +extern const char *whitelist_address; +extern uint64_t whitelist_masks[WHITELIST_COUNT]; + +#endif diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 49ea9270d..66fa30efa 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1606,7 +1606,13 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY)) entry.push_back(Pair("involvesWatchonly", true)); entry.push_back(Pair("account", account)); - MaybePushAddress(entry, r.destination); + + CTxDestination dest; + if (CScriptExt::ExtractVoutDestination(wtx, r.vout, dest)) + MaybePushAddress(entry, dest); + else + MaybePushAddress(entry, r.destination); + if (wtx.IsCoinBase()) { int btm; @@ -4661,7 +4667,7 @@ int32_t komodo_staked(CPubKey &pubkey, CMutableTransaction &txNew,uint32_t nBits return(siglen); } -int32_t verus_staked(CPubKey &pubkey, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig) +int32_t verus_staked(CBlock *pBlock, CPubKey &pubkey, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig) { - return pwalletMain->VerusStakeTransaction(txNew, nBits, hashResult, utxosig); + return pwalletMain->VerusStakeTransaction(pBlock, txNew, nBits, hashResult, utxosig); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index c3451afc0..e12a352a6 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -998,8 +998,9 @@ CWallet::TxItems CWallet::OrderedTxItems(std::list& acentries, // UTXO with the smallest coin age if there is more than one, as larger coin age will win more often and is worth saving // each attempt consists of taking a VerusHash of the following values: // ASSETCHAINS_MAGIC, nHeight, txid, voutNum -bool CWallet::VerusSelectStakeOutput(arith_uint256 &hashResult, CTransaction &stakeSource, int32_t &voutNum, int32_t nHeight, const arith_uint256 &target) const +bool CWallet::VerusSelectStakeOutput(CBlock *pBlock, arith_uint256 &hashResult, CTransaction &stakeSource, int32_t &voutNum, int32_t nHeight, uint32_t &bnTarget) const { + arith_uint256 target; arith_uint256 curHash; vector vecOutputs; COutput *pwinner = NULL; @@ -1007,52 +1008,61 @@ bool CWallet::VerusSelectStakeOutput(arith_uint256 &hashResult, CTransaction &st txnouttype whichType; std:vector> vSolutions; + pBlock->nNonce.SetPOSTarget(bnTarget); + target.SetCompact(bnTarget); + pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, false); - if (pastBlockIndex = komodo_chainactive(nHeight - COINBASE_MATURITY)) + if (pastBlockIndex = komodo_chainactive(nHeight - 100)) { - uint256 pastHash = pastBlockIndex->GetBlockHash(); + CBlockHeader bh = pastBlockIndex->GetBlockHeader(); + uint256 pastHash = bh.GetVerusEntropyHash(nHeight - 100); + CPOSNonce curNonce; BOOST_FOREACH(COutput &txout, vecOutputs) { - if (txout.fSpendable && (UintToArith256(txout.tx->GetVerusPOSHash(txout.i, nHeight, pastHash)) <= target) && (txout.nDepth >= VERUS_MIN_STAKEAGE)) + if (txout.fSpendable && (UintToArith256(txout.tx->GetVerusPOSHash(&(pBlock->nNonce), txout.i, nHeight, pastHash)) <= target) && (txout.nDepth >= VERUS_MIN_STAKEAGE)) { // get the smallest winner if (Solver(txout.tx->vout[txout.i].scriptPubKey, whichType, vSolutions) && (whichType == TX_PUBKEY || whichType == TX_PUBKEYHASH) && (!pwinner || pwinner->tx->vout[pwinner->i].nValue > txout.tx->vout[txout.i].nValue)) pwinner = &txout; + curNonce = pBlock->nNonce; } } if (pwinner) { stakeSource = *(pwinner->tx); voutNum = pwinner->i; + pBlock->nNonce = curNonce; return true; } } return false; } -int32_t CWallet::VerusStakeTransaction(CMutableTransaction &txNew, uint32_t &bnTarget, arith_uint256 &hashResult, uint8_t *utxosig) const +int32_t CWallet::VerusStakeTransaction(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &bnTarget, arith_uint256 &hashResult, uint8_t *utxosig) const { - arith_uint256 target; CTransaction stakeSource; int32_t voutNum, siglen = 0; int64_t nValue; txnouttype whichType; std::vector> vSolutions; - CBlockIndex *tipindex = chainActive.Tip(); + CBlockIndex *tipindex; + { + LOCK(cs_main); + tipindex = chainActive.Tip(); + } bnTarget = lwmaGetNextPOSRequired(tipindex, Params().GetConsensus()); - target.SetCompact(bnTarget); - if (!VerusSelectStakeOutput(hashResult, stakeSource, voutNum, tipindex->nHeight + 1, target) || + if (!VerusSelectStakeOutput(pBlock, hashResult, stakeSource, voutNum, tipindex->nHeight + 1, bnTarget) || !Solver(stakeSource.vout[voutNum].scriptPubKey, whichType, vSolutions)) { + LogPrintf("Searched for eligible staking transactions, no winners found\n"); return 0; } - // komodo create transaction code below this line bool signSuccess; SignatureData sigdata; uint64_t txfee; @@ -1076,7 +1086,7 @@ int32_t CWallet::VerusStakeTransaction(CMutableTransaction &txNew, uint32_t &bnT else return 0; - nValue = txNew.vout[0].nValue = voutNum - txfee; + nValue = txNew.vout[0].nValue = stakeSource.vout[voutNum].nValue - txfee; txNew.nLockTime = 0; CTransaction txNewConst(txNew); signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, nValue, SIGHASH_ALL), stakeSource.vout[voutNum].scriptPubKey, sigdata, consensusBranchId); @@ -1568,7 +1578,7 @@ bool CWallet::IsMine(const CTransaction& tx) { for (int i = 0; i < tx.vout.size(); i++) { - if (IsMine(tx, i) == ISMINE_SPENDABLE) + if (IsMine(tx, i)) return true; } return false; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 0df2cd4dc..d42d3343c 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1149,8 +1149,8 @@ public: bool ignoreUnspendable=true); // staking functions - bool VerusSelectStakeOutput(arith_uint256 &hashResult, CTransaction &stakeSource, int32_t &voutNum, int32_t nHeight, const arith_uint256 &target) const; - int32_t VerusStakeTransaction(CMutableTransaction &txNew, uint32_t &bnTarget, arith_uint256 &hashResult, uint8_t *utxosig) const; + bool VerusSelectStakeOutput(CBlock *pBlock, arith_uint256 &hashResult, CTransaction &stakeSource, int32_t &voutNum, int32_t nHeight, uint32_t &bnTarget) const; + int32_t VerusStakeTransaction(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &bnTarget, arith_uint256 &hashResult, uint8_t *utxosig) const; }; /** A key allocated from the key pool. */ diff --git a/zcutil/build-debian-package.sh b/zcutil/build-debian-package.sh index 870530083..9c621d15b 100755 --- a/zcutil/build-debian-package.sh +++ b/zcutil/build-debian-package.sh @@ -5,8 +5,8 @@ set -e set -x -BUILD_PATH="/tmp/zcbuild" -PACKAGE_NAME="zcash" +BUILD_PATH="/tmp/verus-cli" +PACKAGE_NAME="verus-cli" SRC_PATH=`pwd` SRC_DEB=$SRC_PATH/contrib/debian SRC_DOC=$SRC_PATH/doc @@ -17,7 +17,13 @@ if [ ! -d $BUILD_PATH ]; then mkdir $BUILD_PATH fi -PACKAGE_VERSION=$($SRC_PATH/src/zcashd --version | grep version | cut -d' ' -f4 | tr -d v) +## PACKAGE_VERSION=$($SRC_PATH/src/zcashd --version | grep version | cut -d' ' -f4 | tr -d v) +## Need version setting from environment + +PACKAGE_VERSION=0.3.10-beta + +## +## Also, what does the sed end up doing? DEBVERSION=$(echo $PACKAGE_VERSION | sed 's/-beta/~beta/' | sed 's/-rc/~rc/' | sed 's/-/+/') BUILD_DIR="$BUILD_PATH/$PACKAGE_NAME-$PACKAGE_VERSION-amd64" @@ -38,8 +44,12 @@ chmod 0755 -R $BUILD_DIR/* #cp $SRC_DEB/preinst $BUILD_DIR/DEBIAN #cp $SRC_DEB/prerm $BUILD_DIR/DEBIAN # Copy binaries -cp $SRC_PATH/src/zcashd $DEB_BIN -cp $SRC_PATH/src/zcash-cli $DEB_BIN +cp $SRC_PATH/src/komodod $DEB_BIN +strip $DEB_BIN/komodod +cp $SRC_PATH/src/verusd $DEB_BIN +cp $SRC_PATH/src/komodo-cli $DEB_BIN +strip $DEB_BIN/komodo-cli +cp $SRC_PATH/src/verus $DEB_BIN cp $SRC_PATH/zcutil/fetch-params.sh $DEB_BIN/zcash-fetch-params # Copy docs cp $SRC_PATH/doc/release-notes/release-notes-1.0.0.md $DEB_DOC/changelog @@ -47,8 +57,8 @@ cp $SRC_DEB/changelog $DEB_DOC/changelog.Debian cp $SRC_DEB/copyright $DEB_DOC cp -r $SRC_DEB/examples $DEB_DOC # Copy manpages -cp $SRC_DOC/man/zcashd.1 $DEB_MAN -cp $SRC_DOC/man/zcash-cli.1 $DEB_MAN +cp $SRC_DOC/man/komodod.1 $DEB_MAN +cp $SRC_DOC/man/komodo-cli.1 $DEB_MAN cp $SRC_DOC/man/zcash-fetch-params.1 $DEB_MAN # Copy bash completion files cp $SRC_PATH/contrib/zcashd.bash-completion $DEB_CMP/zcashd @@ -56,14 +66,14 @@ cp $SRC_PATH/contrib/zcash-cli.bash-completion $DEB_CMP/zcash-cli # Gzip files gzip --best -n $DEB_DOC/changelog gzip --best -n $DEB_DOC/changelog.Debian -gzip --best -n $DEB_MAN/zcashd.1 -gzip --best -n $DEB_MAN/zcash-cli.1 +gzip --best -n $DEB_MAN/komodod.1 +gzip --best -n $DEB_MAN/komodo-cli.1 gzip --best -n $DEB_MAN/zcash-fetch-params.1 cd $SRC_PATH/contrib # Create the control file -dpkg-shlibdeps $DEB_BIN/zcashd $DEB_BIN/zcash-cli +dpkg-shlibdeps $DEB_BIN/komodod $DEB_BIN/komodo-cli dpkg-gencontrol -P$BUILD_DIR -v$DEBVERSION # Create the Debian package diff --git a/zcutil/build-win.sh b/zcutil/build-win.sh index 65e0c8923..5c12893fa 100755 --- a/zcutil/build-win.sh +++ b/zcutil/build-win.sh @@ -9,9 +9,10 @@ set -eu -o pipefail set -x cd "$(dirname "$(readlink -f "$0")")/.." -cd depends/ && make HOST=$HOST V=1 NO_QT=1 && cd ../ +cd depends/ && make HOST=$HOST V=1 NO_QT=1 +cd ../ ./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 sed -i 's/-lboost_system-mt /-lboost_system-mt-s /' configure cd src/ -CC="${CC}" CXX="${CXX}" make V=1 komodod.exe komodo-cli.exe komodo-tx.exe +CC="${CC} -g " CXX="${CXX} -g " make V=1 komodod.exe komodo-cli.exe komodo-tx.exe