diff --git a/.github/actions/build-project-docker/Dockerfile.focal.ci b/.github/actions/build-project-docker/Dockerfile.focal.ci new file mode 100644 index 00000000..e26e588e --- /dev/null +++ b/.github/actions/build-project-docker/Dockerfile.focal.ci @@ -0,0 +1,17 @@ +FROM ubuntu:20.04 + +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=Europe/Amsterdam + +RUN \ + apt-get update && apt-get install --no-install-recommends -y ca-certificates curl &&\ + apt-get install --no-install-recommends -y build-essential pkg-config libc6-dev m4 g++-multilib autoconf libtool ncurses-dev unzip git python bison zlib1g-dev wget libcurl4-gnutls-dev bsdmainutils automake &&\ + apt-get install --no-install-recommends -y mingw-w64 &&\ + echo 1 | update-alternatives --config x86_64-w64-mingw32-gcc &&\ + echo 1 | update-alternatives --config x86_64-w64-mingw32-g++ &&\ + apt-get install --no-install-recommends -y librsvg2-bin libtiff-tools cmake imagemagick libcap-dev libz-dev libbz2-dev python3-setuptools libtinfo5 xorriso sudo +RUN \ + apt-get clean && rm -rf /var/lib/apt/lists/* + +COPY entrypoint.sh /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] diff --git a/.github/actions/build-project-docker/action.yml b/.github/actions/build-project-docker/action.yml new file mode 100644 index 00000000..aadfbfc0 --- /dev/null +++ b/.github/actions/build-project-docker/action.yml @@ -0,0 +1,20 @@ +# https://docs.github.com/en/actions/creating-actions/creating-a-docker-container-action +name: 'Build project in docker' +description: 'Create docker image with build environment and build the project' +inputs: + builder-name: + required: true + default: 'builder' + builder-uid: + required: true + default: 1000 + builder-gid: + required: true + default: 1000 +runs: + using: 'docker' + image: 'Dockerfile.focal.ci' + env: + BUILDER_NAME: ${{ inputs.builder-name }} + BUILDER_UID: ${{ inputs.builder-uid }} + BUILDER_GID: ${{ inputs.builder-gid }} diff --git a/.github/actions/build-project-docker/entrypoint.sh b/.github/actions/build-project-docker/entrypoint.sh new file mode 100755 index 00000000..fcae9f23 --- /dev/null +++ b/.github/actions/build-project-docker/entrypoint.sh @@ -0,0 +1,210 @@ +#!/usr/bin/env bash + +groupadd --gid ${BUILDER_GID} --force ${BUILDER_NAME} +adduser --disabled-password --gecos '' --no-create-home $BUILDER_NAME --uid ${BUILDER_UID} --gid ${BUILDER_GID} +adduser $BUILDER_NAME sudo +echo "$BUILDER_NAME ALL=(ALL:ALL) NOPASSWD: ALL" | tee /etc/sudoers.d/$BUILDER_NAME + +# there may be a better way to continue building as a user builder with the same UID and GID as the host runner +su -m $BUILDER_NAME << 'EOF' +echo "User: $(whoami)" +WORKSPACE=$(pwd) +echo "Workspace directory: ${WORKSPACE}" + +delete_linux_depends=false + +build_focal=true +build_windows=true +build_macos=true + +download_and_check_macos_sdk() { + url="https://bitcoincore.org/depends-sources/sdks/Xcode-12.1-12A7403-extracted-SDK-with-libcxx-headers.tar.gz" + output_file="Xcode-12.1-12A7403-extracted-SDK-with-libcxx-headers.tar.gz" + expected_checksum="be17f48fd0b08fb4dcd229f55a6ae48d9f781d210839b4ea313ef17dd12d6ea5" + + # Check if file exists + if [[ -f "$output_file" ]]; then + # Calculate checksum of the file + actual_checksum=$(sha256sum "$output_file" 2>/dev/null | awk '{print $1}') + if [[ -n $actual_checksum ]]; then + # Compare checksums + if [[ "$actual_checksum" == "$expected_checksum" ]]; then + echo "MacOS SDK already exists and has the correct checksum. Skipping download." + return + fi + fi + fi + + echo "Downloading MacOS SDK ..." + # Download the file + curl -L -o "$output_file" "$url" + + # Calculate checksum of the downloaded file + actual_checksum=$(sha256sum "$output_file" | awk '{print $1}') + + # Compare checksums + if [[ "$actual_checksum" != "$expected_checksum" ]]; then + echo "ERROR: Downloaded MacOS SDK has an invalid checksum." + exit 1 + fi + + echo "MacOS SDK downloaded successfully and has a valid checksum." +} + +delete_artefacts() { + local release_name=$1 + + if [[ "$release_name" = "windows" ]]; then + ext=".exe" + else + ext="" + fi + + mkdir -p ${WORKSPACE}/releases/${release_name} + + binaries=( + "src/komodod" + "src/wallet-utility" + "src/komodo-tx" + "src/komodo-cli" + "src/komodo-test" + "src/qt/komodo-qt" + ) + + for binary in "${binaries[@]}" + do + rm -f "${WORKSPACE}/${binary}${ext}" || false + done + + echo "Deleting artefacts from ${WORKSPACE} ..." + # delete possible artefacts from previous build(s) + find ${WORKSPACE}/src \( -name "*.a" -o -name "*.la" -o -name "*.o" -o -name "*.lo" -o -name "*.Plo" -o -name "*.Po" -o -name "*.lai" -o -name "*.dirstamp" \) -delete + find ${WORKSPACE}/src \( -name "*.a" -o -name "*.la" -o -name "*.o" -o -name "*.lo" -o -name "*.Plo" -o -name "*.Po" -o -name "*.lai" -o -name "*.dirstamp" \) -path "*/.*" -delete + rm -f ${WORKSPACE}/src/qt/moc_*.cpp # delete meta object code files, otherwise we will have MacOS after Linux/Windows build error +} + +copy_release() { + local release_name=$1 + + if [[ "$release_name" = "windows" ]]; then + ext=".exe" + else + ext="" + fi + + mkdir -p ${WORKSPACE}/releases/${release_name} + + binaries=( + "src/komodod" + "src/wallet-utility" + "src/komodo-tx" + "src/komodo-cli" + "src/qt/komodo-qt" + ) + + for binary in "${binaries[@]}" + do + case $release_name in + windows) + bash -c "/usr/bin/x86_64-w64-mingw32-strip ${WORKSPACE}/${binary}${ext}" || false + ;; + macos) + bash -c "${WORKSPACE}/depends/x86_64-apple-darwin/native/bin/x86_64-apple-darwin-strip ${WORKSPACE}/${binary}${ext}" || false + ;; + *) + strip "${WORKSPACE}/${binary}${ext}" || false + ;; + esac + cp -f "${WORKSPACE}/${binary}${ext}" "${WORKSPACE}/releases/${release_name}/" + done + + case $release_name in + xenial) + echo "Performing actions for Xenial..." + mv "${WORKSPACE}/releases/${release_name}/komodo-qt" "${WORKSPACE}/releases/${release_name}/komodo-qt-linux" + ;; + focal) + echo "Performing actions for Focal..." + mv "${WORKSPACE}/releases/${release_name}/komodo-qt" "${WORKSPACE}/releases/${release_name}/komodo-qt-linux" + ;; + windows) + echo "Performing actions for Windows..." + mv "${WORKSPACE}/releases/${release_name}/komodo-qt${ext}" "${WORKSPACE}/releases/${release_name}/komodo-qt-windows${ext}" + ;; + macos) + echo "Performing actions for MacOS..." + bash -c "make deploy" || false + cp -f ${WORKSPACE}/*.dmg "${WORKSPACE}/releases/${release_name}/" + mv "${WORKSPACE}/releases/${release_name}/komodo-qt${ext}" "${WORKSPACE}/releases/${release_name}/komodo-qt-mac${ext}" + ;; + *) + echo "Unknown release name: $release_name" + ;; + esac +} + +emulate_build() { + for folder in macos windows focal; do + mkdir -p ${WORKSPACE}/releases/${folder} + for file in komodo-qt komodo-cli komodo-tx wallet-utility komodod; do + extension="" + case ${folder} in + focal) + [[ "$file" == "komodo-qt" ]] && file=${file}-linux + ;; + macos) + [[ "$file" == "komodo-qt" ]] && file=${file}-mac + ;; + windows) + extension=".exe" + [[ "$file" == "komodo-qt" ]] && file=${file}-windows + ;; + esac + echo test > ${WORKSPACE}/releases/${folder}/${file}${extension} + done + done + echo test > ${WORKSPACE}/releases/macos/KomodoOcean-0.8.1-beta1.dmg +} + +if true; then + # Check if awk command exists + command -v awk >/dev/null 2>&1 || { echo >&2 "ERROR: awk command not found."; exit 1; } + # Check if sha256sum command exists + command -v sha256sum >/dev/null 2>&1 || { echo >&2 "ERROR: sha256sum command not found."; exit 1; } + + ### focal + if [[ "${build_focal}" = "true" ]]; then + + # delete old depends binaries (from previous linux version, bcz it's x86_64-unknown-linux-gnu also) + if [[ "${delete_linux_depends}" = true ]]; then + rm -rf ${WORKSPACE}/depends/built/x86_64-unknown-linux-gnu + rm -rf ${WORKSPACE}/depends/x86_64-unknown-linux-gnu + fi + # delete possible artefacts from previous build(s) + delete_artefacts focal + bash -c 'zcutil/build.sh -j'$(expr $(nproc) - 1) + copy_release focal + fi + + ### windows + if [[ "${build_windows}" = "true" ]]; then + delete_artefacts windows + bash -c 'zcutil/build-win.sh -j'$(expr $(nproc) - 1) + copy_release windows + fi + + ### macos + if [[ "${build_macos}" = "true" ]]; then + download_and_check_macos_sdk + delete_artefacts macos + bash -c 'zcutil/build-mac-cross.sh -j'$(expr $(nproc) - 1) + copy_release macos + fi +else + emulate_build + # all environment variables of docker container are accessible here, + # you can use BUILDER_NAME or GITHUB_SHA, or GITHUB_ACTOR, etc. +fi +EOF + + diff --git a/.github/workflows/build-project.yml b/.github/workflows/build-project.yml new file mode 100644 index 00000000..473b395b --- /dev/null +++ b/.github/workflows/build-project.yml @@ -0,0 +1,79 @@ +on: + pull_request: + types: + - opened + - synchronize + - reopened + branches: + - static-experimental + - static + workflow_dispatch: + +jobs: + build-project-job: + # Execute on pull requests within the same repository (and not forks) or on manual dispatch + if: ${{ github.actor == 'DeckerSU' && (github.event_name == 'workflow_dispatch' || (github.event.pull_request.head.repo.full_name == github.repository)) }} + runs-on: [self-hosted, Linux, X64] + name: Build project job + + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set variables + run: | + echo "branch=$(echo ${{ github.ref }} | sed 's/refs\/heads\///g')" >> $GITHUB_OUTPUT + echo "sha_short=$(git rev-parse --short ${{ github.sha }})" >> $GITHUB_OUTPUT + echo "builder_name=$(echo $USER)" >> $GITHUB_OUTPUT + echo "builder_uid=$(id -u)" >> $GITHUB_OUTPUT + echo "builder_gid=$(id -g)" >> $GITHUB_OUTPUT + echo "is_fork=${{ github.event.pull_request.head.repo.fork }}" >> $GITHUB_OUTPUT + id: set_variables_step + + - name: Print variables + run: | + echo "Event Type: ${{ github.event_name }}" + echo "Repository name: ${{ github.event.repository.name }}" + echo "Branch: ${{ steps.set_variables_step.outputs.branch }}" + echo "Commit: ${{ steps.set_variables_step.outputs.sha_short }}" + echo "builder_name: ${{ steps.set_variables_step.outputs.builder_name }}" + echo "builder_uid: ${{ steps.set_variables_step.outputs.builder_uid }}" + echo "builder_gid: ${{ steps.set_variables_step.outputs.builder_gid }}" + echo "is_fork: ${{ steps.set_variables_step.outputs.is_fork }}" + + - name: Build app in docker container + uses: ./.github/actions/build-project-docker + id: build-in-docker + with: + builder-name: '${{ steps.set_variables_step.outputs.builder_name }}' + builder-uid: '${{ steps.set_variables_step.outputs.builder_uid }}' + builder-gid: '${{ steps.set_variables_step.outputs.builder_gid }}' + + # we don't want use strategy / matrix here, bcz in this case matrix will be used + # for entire job and docker containet will be rebuild several times + - name: Archive artifacts (Linux) + uses: actions/upload-artifact@v3 + with: + name: komodoocean-linux-${{ steps.set_variables_step.outputs.sha_short }} + path: | + ./releases/focal + + - name: Archive artifacts (Windows) + uses: actions/upload-artifact@v3 + with: + name: komodoocean-windows-${{ steps.set_variables_step.outputs.sha_short }} + path: | + ./releases/windows + + - name: Archive artifacts (MacOS) + uses: actions/upload-artifact@v3 + with: + name: komodoocean-macos-${{ steps.set_variables_step.outputs.sha_short }} + path: | + ./releases/macos + + - name: Cleanup workspace after build + if: always() + shell: bash + run: | + rm -rf ${{ github.workspace }}/* + diff --git a/Dockerfile.focal.ci b/Dockerfile.focal.ci index bffdaf9f..7ef8fc47 100644 --- a/Dockerfile.focal.ci +++ b/Dockerfile.focal.ci @@ -20,6 +20,7 @@ ENV TZ=Europe/Amsterdam RUN \ apt-get update && apt-get install --no-install-recommends -y apt-transport-https ca-certificates curl &&\ sed -i 's/archive\.ubuntu\.com/mirror\.nl\.leaseweb\.net/g' /etc/apt/sources.list &&\ + sed -i 's/security\.ubuntu\.com/mirror\.nl\.leaseweb\.net/g' /etc/apt/sources.list &&\ sed -i 's/http:/https:/g' /etc/apt/sources.list &&\ apt-get update && apt-get install -y sudo &&\ groupadd --gid ${BUILDER_GID} --force ${BUILDER_NAME} &&\ diff --git a/Dockerfile.xenial.ci b/Dockerfile.xenial.ci index 3c9cdc77..4f114240 100644 --- a/Dockerfile.xenial.ci +++ b/Dockerfile.xenial.ci @@ -20,6 +20,7 @@ ENV TZ=Europe/Amsterdam RUN \ apt-get update && apt-get install --no-install-recommends -y apt-transport-https ca-certificates curl &&\ sed -i 's/archive\.ubuntu\.com/mirror\.nl\.leaseweb\.net/g' /etc/apt/sources.list &&\ + sed -i 's/security\.ubuntu\.com/mirror\.nl\.leaseweb\.net/g' /etc/apt/sources.list &&\ sed -i 's/http:/https:/g' /etc/apt/sources.list &&\ apt-get update && apt-get install -y sudo &&\ groupadd --gid ${BUILDER_GID} --force ${BUILDER_NAME} &&\ diff --git a/build_releases.sh b/build_releases.sh index 450502e2..a9de145a 100755 --- a/build_releases.sh +++ b/build_releases.sh @@ -142,14 +142,14 @@ copy_release() { check_image_focal() { if [[ "${force_rebuild_containers}" == "true" || "$(docker images --format '{{.Repository}}' | grep -c ocean_focal_builder)" -eq 0 ]]; then echo "Container 'ocean_focal_builder' rebuilding ..." - docker build -f Dockerfile.focal.ci --build-arg BUILDER_NAME=$USER --build-arg BUILDER_UID=$(id -u) --build-arg BUILDER_GID=$(id -g) -t ocean_focal_builder . + docker build --no-cache -f Dockerfile.focal.ci --build-arg BUILDER_NAME=$USER --build-arg BUILDER_UID=$(id -u) --build-arg BUILDER_GID=$(id -g) -t ocean_focal_builder . fi } check_image_xenial() { if [[ "${force_rebuild_containers}" == "true" || "$(docker images --format '{{.Repository}}' | grep -c ocean_xenial_builder)" -eq 0 ]]; then echo "Container 'ocean_xenial_builder' rebuilding ..." - docker build -f Dockerfile.xenial.ci --build-arg BUILDER_NAME=$USER --build-arg BUILDER_UID=$(id -u) --build-arg BUILDER_GID=$(id -g) -t ocean_xenial_builder . + docker build --no-cache -f Dockerfile.xenial.ci --build-arg BUILDER_NAME=$USER --build-arg BUILDER_UID=$(id -u) --build-arg BUILDER_GID=$(id -g) -t ocean_xenial_builder . fi } diff --git a/configure.ac b/configure.ac index f280cb87..f5b17438 100644 --- a/configure.ac +++ b/configure.ac @@ -2,12 +2,12 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 8) -define(_CLIENT_VERSION_REVISION, 1) -define(_CLIENT_VERSION_BUILD, 1) +define(_CLIENT_VERSION_REVISION, 2) +define(_CLIENT_VERSION_BUILD, 0) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) -define(_COPYRIGHT_YEAR, 2023) +define(_COPYRIGHT_YEAR, 2024) define(_COPYRIGHT_HOLDERS, "The %s developers") define(_COPYRIGHT_HOLDERS_SUBSTITUTION, "Ocean and Decker") diff --git a/depends/Makefile b/depends/Makefile index c5b00f32..56f1a3e1 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -6,7 +6,7 @@ SDK_PATH ?= $(BASEDIR)/SDKs NO_QT ?= NO_WALLET ?= NO_UPNP ?= -FALLBACK_DOWNLOAD_PATH ?= https://supernet/depends-sources +FALLBACK_DOWNLOAD_PATH ?= https://download.kmd.sh/depends-sources BUILD ?= $(shell ./config.guess) HOST ?= $(BUILD) diff --git a/depends/funcs.mk b/depends/funcs.mk index d00de578..d32ab475 100644 --- a/depends/funcs.mk +++ b/depends/funcs.mk @@ -22,8 +22,8 @@ endef define fetch_file (test -f $$($(1)_source_dir)/$(4) || \ ( mkdir -p $$($(1)_download_dir) && echo Fetching $(1)... && \ - ( $(build_DOWNLOAD) "$$($(1)_download_dir)/$(4).temp" "$(PRIORITY_DOWNLOAD_PATH)/$(4)" || \ - $(build_DOWNLOAD) "$$($(1)_download_dir)/$(4).temp" "$(2)/$(3)" ) && \ + ( $(build_DOWNLOAD) "$$($(1)_download_dir)/$(4).temp" "$(2)/$(3)" || \ + $(build_DOWNLOAD) "$$($(1)_download_dir)/$(4).temp" "$(FALLBACK_DOWNLOAD_PATH)/$(4)" ) && \ echo "$(5) $$($(1)_download_dir)/$(4).temp" > $$($(1)_download_dir)/.$(4).hash && \ $(build_SHA256SUM) -c $$($(1)_download_dir)/.$(4).hash && \ mv $$($(1)_download_dir)/$(4).temp $$($(1)_source_dir)/$(4) && \ diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index 93a657ca..56ebeb04 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -4,7 +4,7 @@ $(package)_version=1_72_0 $(package)_download_path=https://github.com/KomodoPlatform/boost/releases/download/boost-1.72.0-kmd $(package)_sha256_hash=59c9b274bc451cf91a9ba1dd2c7fdcaf5d60b1b3aa83f2c9fa143417cc660722 $(package)_file_name=$(package)_$($(package)_version).tar.bz2 -$(package)_patches=commit-74fb0a2.patch commit-f9d0e59.patch +$(package)_patches=commit-74fb0a2.patch commit-f9d0e59.patch ignore_wnonnull_gcc_11.patch define $(package)_set_vars $(package)_config_opts_release=variant=release @@ -30,6 +30,7 @@ endef define $(package)_preprocess_cmds patch -p2 -i $($(package)_patch_dir)/commit-74fb0a2.patch && \ patch -p2 -i $($(package)_patch_dir)/commit-f9d0e59.patch && \ + patch -p2 -i $($(package)_patch_dir)/ignore_wnonnull_gcc_11.patch && \ echo "using $(boost_toolset_$(host_os)) : : $($(package)_cxx) : \"$($(package)_cxxflags) $($(package)_cppflags)\" \"$($(package)_ldflags)\" \"$(boost_archiver_$(host_os))\" \"$(host_STRIP)\" \"$(host_RANLIB)\" \"$(host_WINDRES)\" : ;" > user-config.jam endef diff --git a/depends/patches/boost/ignore_wnonnull_gcc_11.patch b/depends/patches/boost/ignore_wnonnull_gcc_11.patch new file mode 100644 index 00000000..f914c1e6 --- /dev/null +++ b/depends/patches/boost/ignore_wnonnull_gcc_11.patch @@ -0,0 +1,68 @@ +diff --git a/include/boost/concept/detail/general.hpp b/include/boost/concept/detail/general.hpp +index eeb08750..8d7d6f69 100644 +--- a/include/boost/concept/detail/general.hpp ++++ b/include/boost/concept/detail/general.hpp +@@ -28,7 +28,14 @@ namespace detail + template + struct requirement + { ++# if defined(BOOST_GCC) && (BOOST_GCC >= 110000) ++# pragma GCC diagnostic push ++# pragma GCC diagnostic ignored "-Wnonnull" ++# endif + static void failed() { ((Model*)0)->~Model(); } ++# if defined(BOOST_GCC) && (BOOST_GCC >= 110000) ++# pragma GCC diagnostic pop ++# endif + }; + + struct failed {}; +@@ -36,7 +43,14 @@ struct failed {}; + template + struct requirement + { ++# if defined(BOOST_GCC) && (BOOST_GCC >= 110000) ++# pragma GCC diagnostic push ++# pragma GCC diagnostic ignored "-Wnonnull" ++# endif + static void failed() { ((Model*)0)->~Model(); } ++# if defined(BOOST_GCC) && (BOOST_GCC >= 110000) ++# pragma GCC diagnostic pop ++# endif + }; + + # ifdef BOOST_OLD_CONCEPT_SUPPORT +@@ -44,7 +58,14 @@ struct requirement + template + struct constraint + { ++# if defined(BOOST_GCC) && (BOOST_GCC >= 110000) ++# pragma GCC diagnostic push ++# pragma GCC diagnostic ignored "-Wnonnull" ++# endif + static void failed() { ((Model*)0)->constraints(); } ++# if defined(BOOST_GCC) && (BOOST_GCC >= 110000) ++# pragma GCC diagnostic pop ++# endif + }; + + template +diff --git a/include/boost/concept/usage.hpp b/include/boost/concept/usage.hpp +index 373de63a..fe88b5f5 100644 +--- a/include/boost/concept/usage.hpp ++++ b/include/boost/concept/usage.hpp +@@ -13,7 +13,14 @@ namespace boost { namespace concepts { + template + struct usage_requirements + { ++# if defined(BOOST_GCC) && (BOOST_GCC >= 110000) ++# pragma GCC diagnostic push ++# pragma GCC diagnostic ignored "-Wnonnull" ++# endif + ~usage_requirements() { ((Model*)0)->~Model(); } ++# if defined(BOOST_GCC) && (BOOST_GCC >= 110000) ++# pragma GCC diagnostic pop ++# endif + }; + + # if BOOST_WORKAROUND(__GNUC__, <= 3) diff --git a/src/assetchains.json b/src/assetchains.json index 68486cfb..d6d685f4 100644 --- a/src/assetchains.json +++ b/src/assetchains.json @@ -1,21 +1,4 @@ [ - { - "ac_name": "AXO", - "ac_supply": "200000000", - "ac_ccactivate": "130000" - }, - { - "ac_name": "BET", - "ac_supply": "999999" - }, - { - "ac_name": "BOTS", - "ac_supply": "999999" - }, - { - "ac_name": "BTCH", - "ac_supply": "20998641" - }, { "ac_name": "CCL", "ac_supply": "200000000", @@ -23,86 +6,59 @@ "ac_cc": "2", "addressindex": "1", "spentindex": "1", - "addnode": ["142.93.136.89", "195.201.22.89"] - }, - { - "ac_name": "COQUICASH", - "ac_supply": "72000000", - "ac_reward": "7200000000", - "ac_staked": "50", - "ac_halving": "420000", - "ac_cc": "2", - "ac_ccenable": "227,235,236,241", - "addnode": ["78.47.108.168"] + "addnode": ["209.222.101.247", "103.195.100.32", "142.93.136.89", "195.201.22.89", "15.235.204.174", "148.113.1.52", "65.21.77.109", "89.19.26.211", "89.19.26.212"] }, { - "ac_name": "CRYPTO", - "ac_supply": "999999" + "ac_name": "CLC", + "ac_supply": "99000000", + "ac_reward": "50000000", + "ac_perc":"100000000", + "ac_founders":"1", + "ac_cc": "45", + "ac_public":"1", + "ac_snapshot":"1440", + "ac_pubkey":"02df9bda7bfe2bcaa938b29a399fb0ba58cfb6cc3ddc0001062a600f60a8237ad9", + "ac_adaptivepow":"6", + "addnode": ["209.222.101.247", "103.195.100.32", "node.cryptocollider.com", "15.235.204.174", "148.113.1.52", "65.21.77.109", "89.19.26.211", "89.19.26.212"] }, { - "ac_name": "DEX", - "ac_supply": "999999" + "ac_name": "DOC", + "ac_supply": "90000000000", + "ac_reward": "100000000", + "ac_cc": "3", + "ac_staked": "10", + "addnode": ["209.222.101.247", "103.195.100.32", "65.21.77.109", "65.21.51.47", "15.235.204.174", "148.113.1.52", "65.21.77.109", "89.19.26.211", "89.19.26.212"] }, { "ac_name": "GLEEC", "ac_supply": "210000000", "ac_public": "1", "ac_staked": "100", - "addnode":["95.217.161.126"] - }, - { - "ac_name": "HODL", - "ac_supply": "9999999" + "addnode": ["209.222.101.247", "103.195.100.32", "95.217.161.126", "15.235.204.174", "148.113.1.52", "65.21.77.109", "89.19.26.211", "89.19.26.212"] }, { "ac_name": "ILN", "ac_supply": "10000000000", "ac_cc": "2", - "addnode": ["51.75.122.83"] - }, - { - "ac_name": "JUMBLR", - "ac_supply": "999999" + "addnode": ["209.222.101.247", "103.195.100.32", "51.75.122.83", "15.235.204.174", "148.113.1.52", "65.21.77.109", "89.19.26.211", "89.19.26.212"] }, { "ac_name": "KOIN", "ac_supply": "125000000", - "addnode": ["3.0.32.10"] - }, - { - "ac_name": "MESH", - "ac_supply": "1000007", - "ac_ccactivate": "320000" + "addnode": ["209.222.101.247", "103.195.100.32", "3.0.32.10", "15.235.204.174", "148.113.1.52", "65.21.77.109", "89.19.26.211", "89.19.26.212"] }, { - "ac_name": "MGW", - "ac_supply": "999999" - }, - { - "ac_name": "MORTY", + "ac_name": "MARTY", "ac_supply": "90000000000", "ac_reward": "100000000", "ac_cc": "3", "ac_staked": "10", - "addnode": ["138.201.136.145", "95.217.44.58"] - }, - { - "ac_name": "MSHARK", - "ac_supply": "1400000" + "addnode": ["209.222.101.247", "103.195.100.32", "65.21.77.109", "65.21.51.47", "15.235.204.174", "148.113.1.52", "65.21.77.109", "89.19.26.211", "89.19.26.212"] }, { "ac_name": "NINJA", - "ac_supply": "100000000" - }, - { - "ac_name": "OOT", - "ac_supply": "216000000", - "ac_sapling": "5000000", - "addnode": ["88.99.212.81"] - }, - { - "ac_name": "PANGEA", - "ac_supply": "999999" + "ac_supply": "100000000", + "addnode": ["209.222.101.247", "103.195.100.32", "209.222.101.247", "103.195.100.32", "15.235.204.174", "148.113.1.52", "65.21.77.109", "89.19.26.211", "89.19.26.212"] }, { "ac_name": "PIRATE", @@ -110,45 +66,11 @@ "ac_reward": "25600000000", "ac_halving": "77777", "ac_private": "1", - "addnode": ["88.99.212.81"] - }, - { - "ac_name": "REVS", - "ac_supply": "1300000" - }, - { - "ac_name": "RICK", - "ac_supply": "90000000000", - "ac_reward": "100000000", - "ac_cc": "3", - "ac_staked": "10", - "addnode": ["138.201.136.145", "95.217.44.58"] + "addnode": ["209.222.101.247", "103.195.100.32", "88.99.212.81", "15.235.204.174", "148.113.1.52", "65.21.77.109", "89.19.26.211", "89.19.26.212"] }, { "ac_name": "SUPERNET", - "ac_supply": "816061" - }, - { - "ac_name": "THC", - "ac_supply": "251253103", - "ac_reward": "360000000,300000000,240000000,180000000,150000000,90000000,0", - "ac_staked": "100", - "ac_eras": "7", - "ac_end": "500001,1000001,1500001,2000001,2500001,4500001,0", - "ac_perc": "233333333", - "ac_cc": "2", - "ac_ccenable": "229,236,240", - "ac_script": "2ea22c8020987fad30df055db6fd922c3a57e55d76601229ed3da3b31340112e773df3d0d28103120c008203000401ccb8", - "ac_founders": "150", - "ac_cbmaturity": "1", - "ac_sapling": "1", - "earlytxid": "7e4a76259e99c9379551389e9f757fc5f46c33ae922a8644dc2b187af2a6adc1", - "addnode": ["157.230.45.184", "165.22.52.123"] - }, - { - "ac_name": "ZILLA", - "ac_supply": "11000000", - "ac_sapling": "5000000", - "addnode": ["51.68.215.104"] + "ac_supply": "816061", + "addnode": ["209.222.101.247", "103.195.100.32", "209.222.101.247", "103.195.100.32", "15.235.204.174", "148.113.1.52", "65.21.77.109", "89.19.26.211", "89.19.26.212"] } -] +] \ No newline at end of file diff --git a/src/assetchains.old b/src/assetchains.old index 44d358ae..8801a6ab 100755 --- a/src/assetchains.old +++ b/src/assetchains.old @@ -3,14 +3,13 @@ set -x delay=60 source pubkey.txt echo $pubkey -./komodod -pubkey=$pubkey -ac_name=CCL -ac_supply=200000000 -ac_end=1 -ac_cc=2 -addressindex=1 -spentindex=1 -addnode=142.93.136.89 -addnode=195.201.22.89 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & -./komodod -pubkey=$pubkey -ac_name=CLC -ac_supply=99000000 -ac_reward=50000000 -ac_perc=100000000 -ac_founders=1 -ac_cc=45 -ac_public=1 -ac_snapshot=1440 -ac_pubkey=02df9bda7bfe2bcaa938b29a399fb0ba58cfb6cc3ddc0001062a600f60a8237ad9 -addnode=node.cryptocollider.com -ac_adaptivepow=6 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & -./komodod -pubkey=$pubkey -ac_name=DOC -ac_supply=90000000000 -ac_reward=100000000 -ac_cc=3 -ac_staked=10 -addnode=65.21.77.109 -addnode=65.21.51.47 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & -./komodod -pubkey=$pubkey -ac_name=GLEEC -ac_supply=210000000 -ac_public=1 -ac_staked=100 -addnode=95.217.161.126 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & -./komodod -pubkey=$pubkey -ac_name=ILN -ac_supply=10000000000 -ac_cc=2 -addressindex=1 -spentindex=1 -addnode=51.75.122.83 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & -./komodod -pubkey=$pubkey -ac_name=KOIN -ac_supply=125000000 -addnode=3.0.32.10 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & -./komodod -pubkey=$pubkey -ac_name=MARTY -ac_supply=90000000000 -ac_reward=100000000 -ac_cc=3 -ac_staked=10 -addnode=65.21.77.109 -addnode=65.21.51.47 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & -./komodod -pubkey=$pubkey -ac_name=NINJA -ac_supply=100000000 -addnode=95.213.238.98 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & -./komodod -pubkey=$pubkey -ac_name=PIRATE -ac_supply=0 -ac_reward=25600000000 -ac_halving=77777 -ac_private=1 -addnode=88.99.212.81 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & -./komodod -pubkey=$pubkey -ac_name=SUPERNET -ac_supply=816061 -addnode=95.213.238.98 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & -./komodod -pubkey=$pubkey -ac_name=THC -ac_supply=251253103 -ac_reward=360000000,300000000,240000000,180000000,150000000,90000000,0 -ac_staked=100 -ac_eras=7 -ac_end=500001,1000001,1500001,2000001,2500001,4500001,0 -ac_perc=233333333 -ac_cc=2 -ac_ccenable=229,236,240 -ac_script=2ea22c8020987fad30df055db6fd922c3a57e55d76601229ed3da3b31340112e773df3d0d28103120c008203000401ccb8 -ac_founders=150 -ac_cbmaturity=1 -ac_sapling=1 -addnode=157.230.45.184 -addnode=165.22.52.123 -earlytxid=7e4a76259e99c9379551389e9f757fc5f46c33ae922a8644dc2b187af2a6adc1 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & +komodod -pubkey=$pubkey -ac_name=CCL -ac_supply=200000000 -ac_end=1 -ac_cc=2 -addressindex=1 -spentindex=1 -addnode=142.93.136.89 -addnode=195.201.22.89 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & +komodod -pubkey=$pubkey -ac_name=CLC -ac_supply=99000000 -ac_reward=50000000 -ac_perc=100000000 -ac_founders=1 -ac_cc=45 -ac_public=1 -ac_snapshot=1440 -ac_pubkey=02df9bda7bfe2bcaa938b29a399fb0ba58cfb6cc3ddc0001062a600f60a8237ad9 -addnode=node.cryptocollider.com -ac_adaptivepow=6 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & +komodod -pubkey=$pubkey -ac_name=DOC -ac_supply=90000000000 -ac_reward=100000000 -ac_cc=3 -ac_staked=10 -addnode=65.21.77.109 -addnode=65.21.51.47 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & +komodod -pubkey=$pubkey -ac_name=GLEEC -ac_supply=210000000 -ac_public=1 -ac_staked=100 -addnode=95.217.161.126 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & +komodod -pubkey=$pubkey -ac_name=ILN -ac_supply=10000000000 -ac_cc=2 -addressindex=1 -spentindex=1 -addnode=51.75.122.83 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & +komodod -pubkey=$pubkey -ac_name=KOIN -ac_supply=125000000 -addnode=3.0.32.10 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & +komodod -pubkey=$pubkey -ac_name=MARTY -ac_supply=90000000000 -ac_reward=100000000 -ac_cc=3 -ac_staked=10 -addnode=65.21.77.109 -addnode=65.21.51.47 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & +komodod -pubkey=$pubkey -ac_name=NINJA -ac_supply=100000000 -addnode=95.213.238.98 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & +komodod -pubkey=$pubkey -ac_name=PIRATE -ac_supply=0 -ac_reward=25600000000 -ac_halving=77777 -ac_private=1 -addnode=88.99.212.81 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & +komodod -pubkey=$pubkey -ac_name=SUPERNET -ac_supply=816061 -addnode=95.213.238.98 -addnode=209.222.101.247 -addnode=103.195.100.32 $1 & diff --git a/src/chain.h b/src/chain.h index 2a7cd7df..c5e76681 100644 --- a/src/chain.h +++ b/src/chain.h @@ -35,8 +35,10 @@ extern CCriticalSection cs_main; -static const int SPROUT_VALUE_VERSION = 1001400; -static const int SAPLING_VALUE_VERSION = 1010100; +static const int SPROUT_VALUE_VERSION = 80102; +static const int SAPLING_VALUE_VERSION = 80102; +static const int TRANSPARENT_VALUE_VERSION = 80103; +static const int BURNED_VALUE_VERSION = 80104; // These 5 are declared here to avoid circular dependencies // code used this moved into .cpp @@ -191,6 +193,44 @@ class CBlockIndex //! (memory only) The anchor for the tree state up to the end of this block uint256 hashFinalSproutRoot; + //! The change to the chain supply caused by this block. This is defined as + //! the value of the coinbase outputs in this block, minus fees not claimed + //! by the miner. + //! + //! Will be boost::none under the following conditions: + //! - if the block has never been connected to a chain tip + //! - for older blocks until a reindex has taken place + boost::optional nChainSupplyDelta; + + //! (memory only) Total chain supply up to and including this block. + //! + //! Will be boost::none until a reindex has taken place, if nChainTx is + //! zero, or if the block has never been connected to a chain tip. + boost::optional nChainTotalSupply; + + //! Change in value in the transparent pool produced by the action of the + //! transparent inputs to and outputs from transactions in this block. + //! + //! Will be boost::none for older blocks until a reindex has taken place. + boost::optional nTransparentValue; + + //! (memory only) Total value of the transparent value pool up to and + //! including this block. + //! + //! Will be boost::none until a reindex has taken place. + //! Will be boost::none if nChainTx is zero. + boost::optional nChainTransparentValue; + + // This refers to the number of coins burned in this block, + // essentially making them unspendable (due to the OP_RETURN scripts value). + //! + //! For older blocks, this will be boost::none until a reindexing has occurred. + boost::optional nBurnedAmountDelta; + + //! (memory only) Total value of the burned coins up to and + //! including this block. + boost::optional nChainTotalBurned; + //! Change in value held by the Sprout circuit over this block. //! Will be boost::none for older blocks on old nodes until a reindex has taken place. boost::optional nSproutValue; @@ -246,6 +286,13 @@ class CBlockIndex hashSproutAnchor = uint256(); hashFinalSproutRoot = uint256(); nSequenceId = 0; + + nChainSupplyDelta = boost::none; + nChainTotalSupply = boost::none; + nTransparentValue = boost::none; + nChainTransparentValue = boost::none; + nBurnedAmountDelta = boost::none; + nChainTotalBurned = boost::none; nSproutValue = boost::none; nChainSproutValue = boost::none; nSaplingValue = 0; @@ -440,6 +487,19 @@ class CDiskBlockIndex : public CBlockIndex READWRITE(nNonce); READWRITE(nSolution); + // Only read/write nTransparentValue if the client version used to create + // this index was storing them. + if ((s.GetType() & SER_DISK) && (nVersion >= TRANSPARENT_VALUE_VERSION)) { + READWRITE(nChainSupplyDelta); + READWRITE(nTransparentValue); + } + + // Only read/write nBurnedAmountDelta if the client version used to create + // this index was storing them. + if ((s.GetType() & SER_DISK) && (nVersion >= BURNED_VALUE_VERSION)) { + READWRITE(nBurnedAmountDelta); + } + // Only read/write nSproutValue if the client version used to create // this index was storing them. if ((s.GetType() & SER_DISK) && (nVersion >= SPROUT_VALUE_VERSION)) { diff --git a/src/coins.cpp b/src/coins.cpp index 22764f10..bbe5b380 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -590,6 +590,12 @@ const CScript &CCoinsViewCache::GetSpendFor(const CTxIn& input) const * @returns Sum of value of all inputs (scriptSigs), (positive valueBalance or zero) and JoinSplit vpub_new */ CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t &interestp,const CTransaction& tx) const +{ + return GetTransparentValueIn(nHeight, interestp, tx) + tx.GetShieldedValueIn(); +} + +// TODO: remove this if it ends up unused +CAmount CCoinsViewCache::GetTransparentValueIn(int32_t nHeight,int64_t &interestp,const CTransaction& tx) const { CAmount value,nResult = 0; interestp = 0; @@ -617,7 +623,6 @@ CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t &interestp,const CTr } #endif } - nResult += tx.GetShieldedValueIn(); return nResult; } diff --git a/src/coins.h b/src/coins.h index d26dd792..5f6beae4 100644 --- a/src/coins.h +++ b/src/coins.h @@ -562,11 +562,22 @@ class CCoinsViewCache : public CCoinsViewBacked * so may not be able to calculate this. * @param[in] nHeight the chain height * @param[out] interestp the interest found - * @param[in] tx transaction for which we are checking input total - * @returns Sum of value of all inputs (scriptSigs), (positive valueBalance or zero) and JoinSplit vpub_new + * @param[in] tx transaction for which we are checking input total + * @return Sum of value of all inputs (scriptSigs), JoinSplit vpub_new, and + * positive values of valueBalanceSapling, and valueBalanceOrchard. */ CAmount GetValueIn(int32_t nHeight,int64_t &interestp,const CTransaction& tx) const; + /** + * Amount of coins coming in to a transaction in the transparent inputs. + * + * @param[in] nHeight the chain height + * @param[out] interestp the interest found + * @param[in] tx transaction for which we are checking input total + * @return Sum of value of all inputs (scriptSigs) + */ + CAmount GetTransparentValueIn(int32_t nHeight,int64_t &interestp,const CTransaction& tx) const; + //! Check whether all prevouts of the transaction are present in the UTXO set represented by this view bool HaveInputs(const CTransaction& tx) const; diff --git a/src/main.cpp b/src/main.cpp index 6a22a96c..c1e51550 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1410,6 +1410,10 @@ bool CheckTransaction(uint32_t tiptime,const CTransaction& tx, CValidationState REJECT_INVALID, "bad-txns-joinsplit-verification-failed"); } } + + // Sapling zk-SNARK proofs are checked in librustzcash_sapling_check_{spend,output}, + // called from ContextualCheckTransaction. + return true; } } @@ -1564,6 +1568,13 @@ bool CheckTransactionWithoutProofVerification(uint32_t tiptime,const CTransactio return state.DoS(100, error("CheckTransaction(): this is a public chain, no privacy allowed"), REJECT_INVALID, "bad-txns-acpublic-chain"); } + // In ZCash (ZEC), they have implemented [ZIP 211] which disables the addition of new values + // to the Sprout Value Pool after Canopy activations. The implementation can be found here: + // https://github.com/zcash/zcash/pull/4489. In KMD, we throw the "bad-txns-sprout-expired" + // error if a transaction contains even a single joinsplit after the KOMODO_SAPLING_DEADLINE. + // In other words, any sprout transactions are forbidden after February 15, 2019. + // It would be more logical to handle this in the ContextualCheckTransaction function, + // but historically it has been done here. if ( tiptime >= KOMODO_SAPLING_DEADLINE ) { return state.DoS(100, error("CheckTransaction(): no more sprout after deadline"), @@ -2159,20 +2170,6 @@ bool GetAddressUnspent(uint160 addressHash, int type, return true; } -struct CompareBlocksByHeightMain -{ - bool operator()(const CBlockIndex* a, const CBlockIndex* b) const - { - /* Make sure that unequal blocks with the same height do not compare - equal. Use the pointers themselves to make a distinction. */ - - if (a->nHeight != b->nHeight) - return (a->nHeight > b->nHeight); - - return a < b; - } -}; - /**** * @brief add a transaction to the mempool * @param[in] tx the transaction @@ -3534,6 +3531,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // Grab the consensus branch ID for the block's height auto consensusBranchId = CurrentEpochBranchId(pindex->nHeight, Params().GetConsensus()); + CAmount chainSupplyDelta = 0; + CAmount transparentValueDelta = 0; + CAmount burnedAmountDelta = 0; std::vector txdata; txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated for (unsigned int i = 0; i < block.vtx.size(); i++) @@ -3554,6 +3554,12 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, error("ConnectBlock(): inputs missing/spent"), REJECT_INVALID, "bad-txns-inputs-missingorspent"); } + + for (const auto& input : tx.vin) { + const auto prevout = view.GetOutputFor(input); + transparentValueDelta -= prevout.nValue; + } + // are the JoinSplit's requirements met? if (!view.HaveJoinSplitRequirements(tx)) return state.DoS(100, error("ConnectBlock(): JoinSplit requirements not met"), @@ -3607,9 +3613,21 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin LogPrintf("valueout %.8f too big\n",(double)valueout/COIN); return state.DoS(100, error("ConnectBlock(): GetValueOut too big"),REJECT_INVALID,"tx valueout is too big"); } - if (!tx.IsCoinBase()) + if (tx.IsCoinBase()) { - nFees += (stakeTxValue= view.GetValueIn(chainActive.Tip()->nHeight,interest,tx) - valueout); + // Add the output value of the coinbase transaction to the chain supply + // delta. This includes fees, which are then canceled out by the fee + // subtractions in the other branch of this conditional. + chainSupplyDelta += tx.GetValueOut(); + } else { + const auto txFee = (stakeTxValue= view.GetValueIn(chainActive.Tip()->nHeight,interest,tx) - valueout); + nFees += txFee; + + // Fees from a transaction do not go into an output of the transaction, + // and therefore decrease the chain supply. If the miner claims them, + // they will be re-added in the other branch of this conditional. + chainSupplyDelta -= txFee; + sum += interest; std::vector vChecks; @@ -3661,6 +3679,16 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin sapling_tree.append(outputDescription.cm); } + for (const auto& out : tx.vout) { + if (!out.scriptPubKey.IsUnspendable()) { + transparentValueDelta += out.nValue; + } else { + // If the outputs are unspendable, we should not include them in the transparent pool, + // but include in the burned amount calculations + burnedAmountDelta += out.nValue; + } + } + vPos.push_back(std::make_pair(tx.GetHash(), pos)); pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); } @@ -3673,6 +3701,35 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin view.PushAnchor(sprout_tree); view.PushAnchor(sapling_tree); if (!fJustCheck) { + // Update pindex with the net change in transparent value and the chain's total + // transparent value. + pindex->nChainSupplyDelta = chainSupplyDelta; + pindex->nTransparentValue = transparentValueDelta; + pindex->nBurnedAmountDelta = burnedAmountDelta; + if (pindex->pprev) { + if (pindex->pprev->nChainTotalSupply) { + pindex->nChainTotalSupply = *pindex->pprev->nChainTotalSupply + chainSupplyDelta; + } else { + pindex->nChainTotalSupply = boost::none; + } + + if (pindex->pprev->nChainTransparentValue) { + pindex->nChainTransparentValue = *pindex->pprev->nChainTransparentValue + transparentValueDelta; + } else { + pindex->nChainTransparentValue = boost::none; + } + + if (pindex->pprev->nChainTotalBurned) { + pindex->nChainTotalBurned = *pindex->pprev->nChainTotalBurned + burnedAmountDelta; + } else { + pindex->nChainTotalBurned = boost::none; + } + } else { + pindex->nChainTotalSupply = chainSupplyDelta; + pindex->nChainTransparentValue = transparentValueDelta; + pindex->nChainTotalBurned = burnedAmountDelta; + } + pindex->hashFinalSproutRoot = sprout_tree.root(); } blockundo.old_sprout_tree_root = old_sprout_tree_root; @@ -4770,9 +4827,27 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl { pindexNew->nTx = block.vtx.size(); pindexNew->nChainTx = 0; + + // the following values are computed here only for the genesis block + CAmount chainSupplyDelta = 0; + CAmount transparentValueDelta = 0; + CAmount burnedAmountDelta = 0; + CAmount sproutValue = 0; CAmount saplingValue = 0; for (auto tx : block.vtx) { + // For the genesis block only, compute the chain supply delta and the transparent + // output total. + if (pindexNew->pprev == nullptr) { + chainSupplyDelta = tx.GetValueOut(); + for (const auto& out : tx.vout) { + if (!out.scriptPubKey.IsUnspendable()) { + transparentValueDelta += out.nValue; + } else { + burnedAmountDelta += out.nValue; + } + } + } // Negative valueBalance "takes" money from the transparent value pool // and adds it to the Sapling value pool. Positive valueBalance "gives" // money to the transparent value pool, removing from the Sapling value @@ -4784,6 +4859,23 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl sproutValue -= js.vpub_new; } } + + // These values can only be computed here for the genesis block. + // For all other blocks, we update them in ConnectBlock instead. + if (pindexNew->pprev == nullptr) { + pindexNew->nChainSupplyDelta = chainSupplyDelta; + pindexNew->nTransparentValue = transparentValueDelta; + pindexNew->nBurnedAmountDelta = burnedAmountDelta; + } else { + pindexNew->nChainSupplyDelta = boost::none; + pindexNew->nTransparentValue = boost::none; + pindexNew->nBurnedAmountDelta = boost::none; + } + + pindexNew->nChainTotalSupply = boost::none; + pindexNew->nChainTransparentValue = boost::none; + pindexNew->nChainTotalBurned = boost::none; + pindexNew->nSproutValue = sproutValue; pindexNew->nChainSproutValue = boost::none; pindexNew->nSaplingValue = saplingValue; @@ -4805,18 +4897,30 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl CBlockIndex *pindex = queue.front(); queue.pop_front(); pindex->nChainTx = (pindex->pprev ? pindex->pprev->nChainTx : 0) + pindex->nTx; + if (pindex->pprev) { + // Transparent value and chain total supply are added to the + // block index only in `ConnectBlock`, because that's the only + // place that we have a valid coins view with which to compute + // the transparent input value and fees. + + // Calculate the block's effect on the Sprout chain value pool balance. if (pindex->pprev->nChainSproutValue && pindex->nSproutValue) { pindex->nChainSproutValue = *pindex->pprev->nChainSproutValue + *pindex->nSproutValue; } else { pindex->nChainSproutValue = boost::none; } + + // calculate the block's effect on the chain's net Sapling value if (pindex->pprev->nChainSaplingValue) { pindex->nChainSaplingValue = *pindex->pprev->nChainSaplingValue + pindex->nSaplingValue; } else { pindex->nChainSaplingValue = boost::none; } } else { + pindex->nChainTotalSupply = pindex->nChainSupplyDelta; + pindex->nChainTransparentValue = pindex->nTransparentValue; + pindex->nChainTotalBurned = pindex->nBurnedAmountDelta; pindex->nChainSproutValue = pindex->nSproutValue; pindex->nChainSaplingValue = pindex->nSaplingValue; } @@ -6135,11 +6239,31 @@ bool static LoadBlockIndexDB() if (pindex->pprev) { if (pindex->pprev->nChainTx) { pindex->nChainTx = pindex->pprev->nChainTx + pindex->nTx; + + if (pindex->pprev->nChainTotalSupply && pindex->nChainSupplyDelta) { + pindex->nChainTotalSupply = *pindex->pprev->nChainTotalSupply + *pindex->nChainSupplyDelta; + } else { + pindex->nChainTotalSupply = boost::none; + } + + if (pindex->pprev->nChainTransparentValue && pindex->nTransparentValue) { + pindex->nChainTransparentValue = *pindex->pprev->nChainTransparentValue + *pindex->nTransparentValue; + } else { + pindex->nChainTransparentValue = boost::none; + } + + if (pindex->pprev->nChainTotalBurned && pindex->nBurnedAmountDelta) { + pindex->nChainTotalBurned = *pindex->pprev->nChainTotalBurned + *pindex->nBurnedAmountDelta; + } else { + pindex->nChainTotalBurned = boost::none; + } + if (pindex->pprev->nChainSproutValue && pindex->nSproutValue) { pindex->nChainSproutValue = *pindex->pprev->nChainSproutValue + *pindex->nSproutValue; } else { pindex->nChainSproutValue = boost::none; } + if (pindex->pprev->nChainSaplingValue) { pindex->nChainSaplingValue = *pindex->pprev->nChainSaplingValue + pindex->nSaplingValue; } else { @@ -6147,12 +6271,18 @@ bool static LoadBlockIndexDB() } } else { pindex->nChainTx = 0; + pindex->nChainTotalSupply = boost::none; + pindex->nChainTransparentValue = boost::none; + pindex->nChainTotalBurned = boost::none; pindex->nChainSproutValue = boost::none; pindex->nChainSaplingValue = boost::none; mapBlocksUnlinked.insert(std::make_pair(pindex->pprev, pindex)); } } else { pindex->nChainTx = pindex->nTx; + pindex->nChainTotalSupply = pindex->nChainSupplyDelta; + pindex->nChainTransparentValue = pindex->nTransparentValue; + pindex->nChainTotalBurned = pindex->nBurnedAmountDelta; pindex->nChainSproutValue = pindex->nSproutValue; pindex->nChainSaplingValue = pindex->nSaplingValue; } diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index bb77c33e..b8c03af3 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -123,12 +123,14 @@ UniValue letsdebug(const UniValue& params, bool fHelp, const CPubKey& mypk) { } static UniValue ValuePoolDesc( - const std::string &name, + const boost::optional name, const boost::optional chainValue, const boost::optional valueDelta) { UniValue rv(UniValue::VOBJ); - rv.push_back(Pair("id", name)); + if (name.is_initialized()) { + rv.pushKV("id", name.value()); + } rv.push_back(Pair("monitored", (bool)chainValue)); if (chainValue) { rv.push_back(Pair("chainValue", ValueFromAmount(*chainValue))); @@ -339,11 +341,12 @@ 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->hashFinalSproutRoot.GetHex())); - result.push_back(Pair("blocktype", "mined")); - + result.pushKV("chainSupply", ValuePoolDesc(boost::none, blockindex->nChainTotalSupply, blockindex->nChainSupplyDelta)); UniValue valuePools(UniValue::VARR); - valuePools.push_back(ValuePoolDesc("sprout", blockindex->nChainSproutValue, blockindex->nSproutValue)); - valuePools.push_back(ValuePoolDesc("sapling", blockindex->nChainSaplingValue, blockindex->nSaplingValue)); + valuePools.push_back(ValuePoolDesc(std::string("transparent"), blockindex->nChainTransparentValue, blockindex->nTransparentValue)); + valuePools.push_back(ValuePoolDesc(std::string("sprout"), blockindex->nChainSproutValue, blockindex->nSproutValue)); + valuePools.push_back(ValuePoolDesc(std::string("sapling"), blockindex->nChainSaplingValue, blockindex->nSaplingValue)); + valuePools.push_back(ValuePoolDesc(std::string("burned"), blockindex->nChainTotalBurned, blockindex->nBurnedAmountDelta)); result.push_back(Pair("valuePools", valuePools)); if (blockindex->pprev) @@ -858,6 +861,23 @@ UniValue getblock(const UniValue& params, bool fHelp, const CPubKey& mypk) " \"nonce\" : n, (numeric) The nonce\n" " \"bits\" : \"1d00ffff\", (string) The bits\n" " \"difficulty\" : x.xxx, (numeric) The difficulty\n" + " \"chainSupply\": { (object) information about the total supply\n" + " \"monitored\": xx, (boolean) true if the total supply is being monitored\n" + " \"chainValue\": xxxxxx, (numeric, optional) total chain supply\n" + " \"chainValueZat\": xxxxxx, (numeric, optional) total chain supply in satoshis\n" + " \"valueDelta\": xxxxxx, (numeric, optional) change to the chain supply produced by this block\n" + " \"valueDeltaZat\": xxxxxx, (numeric, optional) change to the chain supply produced by this block, in satoshis\n" + " }\n" + " \"valuePools\": [ (array) information about each value pool\n" + " {\n" + " \"id\": \"xxxx\", (string) name of the pool\n" + " \"monitored\": xx, (boolean) true if the pool is being monitored\n" + " \"chainValue\": xxxxxx, (numeric, optional) total amount in the pool\n" + " \"chainValueZat\": xxxxxx, (numeric, optional) total amount in the pool in satoshis\n" + " \"valueDelta\": xxxxxx, (numeric, optional) change to the amount in the pool produced by this block\n" + " \"valueDeltaZat\": xxxxxx, (numeric, optional) change to the amount in the pool produced by this block, in satoshis\n" + " }, ...\n" + " ]\n" " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n" "}\n" @@ -1344,6 +1364,19 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp, const CPubKey& my " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" " \"size_on_disk\": xxxxxx, (numeric) the estimated size of the block and undo files on disk\n" " \"commitments\": xxxxxx, (numeric) the current number of note commitments in the commitment tree\n" + " \"chainSupply\": { (object) information about the total supply\n" + " \"monitored\": xx, (boolean) true if the total supply is being monitored\n" + " \"chainValue\": xxxxxx, (numeric, optional) total chain supply\n" + " \"chainValueZat\": xxxxxx, (numeric, optional) total chain supply in satoshis\n" + " }\n" + " \"valuePools\": [ (array) information about each value pool\n" + " {\n" + " \"id\": \"xxxx\", (string) name of the pool\n" + " \"monitored\": xx, (boolean) true if the pool is being monitored\n" + " \"chainValue\": xxxxxx, (numeric, optional) total amount in the pool\n" + " \"chainValueZat\": xxxxxx, (numeric, optional) total amount in the pool in satoshis\n" + " }, ...\n" + " ]\n" " \"softforks\": [ (array) status of softforks in progress\n" " {\n" " \"id\": \"xxxx\", (string) name of softfork\n" @@ -1400,9 +1433,12 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp, const CPubKey& my obj.push_back(Pair("commitments", static_cast(tree.size()))); CBlockIndex* tip = chainActive.Tip(); + obj.pushKV("chainSupply", ValuePoolDesc(boost::none, tip->nChainTotalSupply, boost::none)); UniValue valuePools(UniValue::VARR); - valuePools.push_back(ValuePoolDesc("sprout", tip->nChainSproutValue, boost::none)); - valuePools.push_back(ValuePoolDesc("sapling", tip->nChainSaplingValue, boost::none)); + valuePools.push_back(ValuePoolDesc(std::string("transparent"), tip->nChainTransparentValue, boost::none)); + valuePools.push_back(ValuePoolDesc(std::string("sprout"), tip->nChainSproutValue, boost::none)); + valuePools.push_back(ValuePoolDesc(std::string("sapling"), tip->nChainSaplingValue, boost::none)); + valuePools.push_back(ValuePoolDesc(std::string("burned"), tip->nChainTotalBurned, boost::none)); obj.push_back(Pair("valuePools", valuePools)); const Consensus::Params& consensusParams = Params().GetConsensus(); diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index b4c2736a..c65835da 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -81,7 +81,7 @@ int8_t StakedNotaryID(std::string ¬aryname, char *Raddress); uint64_t komodo_notarypayamount(int32_t nHeight, int64_t notarycount); int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);*/ -#define KOMODO_VERSION "0.8.1" +#define KOMODO_VERSION "0.8.2" extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; extern uint32_t ASSETCHAINS_CC; extern uint32_t ASSETCHAINS_MAGIC,ASSETCHAINS_ALGO; diff --git a/src/test-komodo/test_parse_args.cpp b/src/test-komodo/test_parse_args.cpp index 138695a1..296463e0 100644 --- a/src/test-komodo/test_parse_args.cpp +++ b/src/test-komodo/test_parse_args.cpp @@ -153,7 +153,7 @@ namespace ParseArgumentsTests { {"NINJA", "-ac_name=NINJA -ac_supply=100000000 -addnode=209.222.101.247 -addnode=103.195.100.32 -addnode=209.222.101.247 -addnode=103.195.100.32 -addnode=15.235.204.174 -addnode=148.113.1.52 -addnode=65.21.77.109 -addnode=89.19.26.211 -addnode=89.19.26.212"}, {"PIRATE", "-ac_name=PIRATE -ac_supply=0 -ac_reward=25600000000 -ac_halving=77777 -ac_private=1 -addnode=209.222.101.247 -addnode=103.195.100.32 -addnode=88.99.212.81 -addnode=15.235.204.174 -addnode=148.113.1.52 -addnode=65.21.77.109 -addnode=89.19.26.211 -addnode=89.19.26.212"}, {"SUPERNET", "-ac_name=SUPERNET -ac_supply=816061 -addnode=209.222.101.247 -addnode=103.195.100.32 -addnode=209.222.101.247 -addnode=103.195.100.32 -addnode=15.235.204.174 -addnode=148.113.1.52 -addnode=65.21.77.109 -addnode=89.19.26.211 -addnode=89.19.26.212"}, - {"THC", "-ac_name=THC -ac_supply=251253103 -ac_reward=360000000,300000000,240000000,180000000,150000000,90000000,0 -ac_staked=100 -ac_eras=7 -ac_end=500001,1000001,1500001,2000001,2500001,4500001,0 -ac_perc=233333333 -ac_cc=2 -ac_ccenable=229,236,240 -ac_script=2ea22c8020987fad30df055db6fd922c3a57e55d76601229ed3da3b31340112e773df3d0d28103120c008203000401ccb8 -ac_founders=150 -ac_cbmaturity=1 -ac_sapling=1 -earlytxid=7e4a76259e99c9379551389e9f757fc5f46c33ae922a8644dc2b187af2a6adc1 -addnode=209.222.101.247 -addnode=103.195.100.32 -addnode=157.230.45.184 -addnode=165.22.52.123 -addnode=15.235.204.174 -addnode=148.113.1.52 -addnode=65.21.77.109 -addnode=89.19.26.211 -addnode=89.19.26.212"}, + {"ERA7", "-ac_name=ERA7 -ac_supply=7777777 -ac_reward=700000000,600000000,500000000,400000000,300000000,200000000,0 -ac_staked=100 -ac_eras=7 -ac_end=1000000,2000000,3000000,4000000,5000000,6000000,0 -ac_cc=2 -ac_ccenable=229,236,240 -ac_cbmaturity=1 -ac_sapling=1"}, {"TXX001", "-ac_name=TXX001 -ac_sapling=1 -ac_founders=1 -ac_reward=0,1125000000,562500000 -ac_end=128,340000,5422111 -ac_blocktime=150 -ac_supply=6178674 -ac_halving=129,340000,840000 -ac_cc=2 -ac_cclib=txx001 -ac_ccenable=228,234,235,236,241 -ac_perc=11111111 -ac_eras=3 -ac_script=76a9145eb10cf64f2bab1b457f1f25e658526155928fac88ac -clientname=GoldenSandtrout -addnode=188.165.212.101 -addnode=136.243.227.142 -addnode=5.9.224.250",} }; @@ -169,7 +169,7 @@ namespace ParseArgumentsTests { { "NINJA", {"NINJA", 8426, 8427, -1301311821} }, { "PIRATE", {"PIRATE", 45452, 45453, 397860952} }, { "SUPERNET", {"SUPERNET", 11340, 11341, -1190058922} }, - { "THC", {"THC", 36789, 36790, -1111205507} }, + { "ERA7", {"ERA7", 37332, 37333, -1314352964} }, { "TXX001", {"TXX001", 55965, 55966, 951479465} }, }; diff --git a/src/txdb.cpp b/src/txdb.cpp index c03212de..9ab6f6ad 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -757,6 +757,9 @@ bool CBlockTreeDB::LoadBlockIndexGuts() pindexNew->nStatus = diskindex.nStatus; pindexNew->nCachedBranchId = diskindex.nCachedBranchId; pindexNew->nTx = diskindex.nTx; + pindexNew->nChainSupplyDelta = diskindex.nChainSupplyDelta; + pindexNew->nTransparentValue = diskindex.nTransparentValue; + pindexNew->nBurnedAmountDelta = diskindex.nBurnedAmountDelta; pindexNew->nSproutValue = diskindex.nSproutValue; pindexNew->nSaplingValue = diskindex.nSaplingValue; pindexNew->segid = diskindex.segid; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index e0adf401..353e4fca 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1329,10 +1329,9 @@ int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb) return nRet; } -CWallet::TxItems CWallet::OrderedTxItems(std::list& acentries, std::string strAccount) +CWallet::TxItems CWallet::OrderedTxItems(std::list& acentries, std::string strAccount, CWalletDB *pwalletdbIn) { AssertLockHeld(cs_wallet); // mapWallet - CWalletDB walletdb(strWalletFile); // First: get all CWalletTx and CAccountingEntry into a sorted-by-order multimap. TxItems txOrdered; @@ -1345,12 +1344,15 @@ CWallet::TxItems CWallet::OrderedTxItems(std::list& acentries, txOrdered.insert(make_pair(wtx->nOrderPos, TxPair(wtx, (CAccountingEntry*)0))); //LogPrintf("ordered iter.%d %s\n",(int32_t)wtx->nOrderPos,wtx->GetHash().GetHex().c_str()); } + + CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(strWalletFile); acentries.clear(); - walletdb.ListAccountCreditDebit(strAccount, acentries); + pwalletdb->ListAccountCreditDebit(strAccount, acentries); BOOST_FOREACH(CAccountingEntry& entry, acentries) { txOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry))); } + if (!pwalletdbIn) delete pwalletdb; return txOrdered; } @@ -1523,7 +1525,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future int64_t latestTolerated = latestNow + 300; std::list acentries; - TxItems txOrdered = OrderedTxItems(acentries); + TxItems txOrdered = OrderedTxItems(acentries, "", pwalletdb); for (TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) { CWalletTx *const pwtx = (*it).second.first; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 9a94872c..715aca41 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1169,7 +1169,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * @return multimap of ordered transactions and accounting entries * @warning Returned pointers are *only* valid within the scope of passed acentries */ - TxItems OrderedTxItems(std::list& acentries, std::string strAccount = ""); + TxItems OrderedTxItems(std::list& acentries, std::string strAccount = "", CWalletDB *pwalletdbIn = nullptr); void MarkDirty(); bool UpdateNullifierNoteMap(); diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp index c08a7fac..f4fcda6b 100644 --- a/src/zmq/zmqpublishnotifier.cpp +++ b/src/zmq/zmqpublishnotifier.cpp @@ -98,7 +98,8 @@ bool CZMQAbstractPublishNotifier::Initialize(void *pcontext) void CZMQAbstractPublishNotifier::Shutdown() { - assert(psocket); + // Early return if Initialize was not called + if (!psocket) return; int count = mapPublishNotifiers.count(address); diff --git a/zcutil/clean-help-dev.sh b/zcutil/clean-help-dev.sh index c247fbc6..2adbd1fe 100755 --- a/zcutil/clean-help-dev.sh +++ b/zcutil/clean-help-dev.sh @@ -41,6 +41,8 @@ if [ "$is_git_root" -eq "1" ]; then rm -f ./src/leveldb/libmemenv.a rm -f ./src/leveldb/libleveldb_sse42.a rm -f ./src/leveldb/libleveldb.a + rm -f ./src/qt/qrc_komodo.cpp + rm -f ./src/qt/qrc_komodo_locale.cpp # https://unix.stackexchange.com/questions/84265/linux-shell-find-exec-in-find-exec # https://askubuntu.com/questions/377438/how-can-i-recursively-delete-all-files-of-a-specific-extension-in-the-current-di