From 4e1fc11fbbff975687fa915fe3ad4c3cd8562556 Mon Sep 17 00:00:00 2001 From: ComputerGenie Date: Fri, 5 Jan 2024 07:49:11 -0600 Subject: [PATCH] sync with KO static-experimental fixes 'ERROR: ConnectBlock: ac_staked chain failed slow komodo_checkPOW' among other things squashed 00f8aa...820b99 add zk-SNARK proofs related comments zmq: Fix due to invalid argument and multiple notifiers fix value pools calculations (#63) https://github.com/KomodoPlatform/komodo/issues/604 depends: patch boost to ignore -Wnonnull new gcc 11 warnings (#64) this patch fixes errors like: ``` include/boost/concept/detail/general.hpp:39:47: warning: 'this' pointer null [-Wnonnull] 39 | static void failed() { ((Model*)0)->~Model(); } ``` during build with gcc 11.x, more details can be found here: - https://github.com/boostorg/concept_check/issues/27 - https://github.com/boostorg/concept_check/pull/28 build: proper clean of ./src/qt/qrc_*.cpp in clean-help Add chain supply and transparent value to block index. Co-authored-by: Jack Grigg Co-authored-by: Kris Nuttycombe Co-authored-by: Daira Hopwood bump version [0.8.1.3] from 0.8.1.3 diskblockindex have new fields, related to chain supply caused by this block and delta in the transparent pool produced by the action of the transparent inputs to and outputs from transactions in this block. See the: TRANSPARENT_VALUE_VERSION constant. fix transparent pool addition for unspendable outputs chain.h: change std::nullopt to boost::none in comments introduce burned coins value pool burned coins refer to the value sent for OP_RETURN scripts: ``` "vout": [ ... { "value": 2.00000000, "valueZat": 200000000, "n": 1, "scriptPubKey": { "asm": "OP_RETURN 6465636b6572", "hex": "6a066465636b6572", "type": "nulldata" } } ], "vjoinsplit": [ ] ``` burned coins are also excluded from transparent pool. bump version [0.8.1.4] this update activates burned coins value pool, see: BURNED_VALUE_VERSION revert fMiningRequiresPeers change on CMainParams The change was made solely for debugging purposes and was accidentally included in the PR. We are now reverting that change. remove unused CompareBlocksByHeightMain comparator bump COPYRIGHT_YEAR to 2024 --- configure.ac | 4 +- depends/packages/boost.mk | 3 +- .../boost/ignore_wnonnull_gcc_11.patch | 68 ++++++++ src/chain.h | 64 ++++++- src/coins.cpp | 7 +- src/coins.h | 15 +- src/main.cpp | 162 ++++++++++++++++-- src/rpc/blockchain.cpp | 52 +++++- src/txdb.cpp | 3 + src/zmq/zmqpublishnotifier.cpp | 3 +- zcutil/clean-help-dev.sh | 2 + 11 files changed, 350 insertions(+), 33 deletions(-) create mode 100644 depends/patches/boost/ignore_wnonnull_gcc_11.patch diff --git a/configure.ac b/configure.ac index f280cb87..255e1fd8 100644 --- a/configure.ac +++ b/configure.ac @@ -3,11 +3,11 @@ 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_BUILD, 4) 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/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/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/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/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