diff --git a/configure.ac b/configure.ac index 4a99208dac3..a654ff3b722 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 8) define(_CLIENT_VERSION_REVISION, 1) -define(_CLIENT_VERSION_BUILD, 2) +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) diff --git a/src/chain.h b/src/chain.h index 56bedb0c04a..9eef9f61e0f 100644 --- a/src/chain.h +++ b/src/chain.h @@ -39,6 +39,8 @@ extern CCriticalSection cs_main; 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 @@ -193,6 +195,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; @@ -249,6 +289,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; @@ -443,6 +490,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/clientversion.h b/src/clientversion.h index 95beac6e3b7..b92ce4f37dd 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -33,7 +33,7 @@ #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 8 #define CLIENT_VERSION_REVISION 1 -#define CLIENT_VERSION_BUILD 2 +#define CLIENT_VERSION_BUILD 4 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/coins.cpp b/src/coins.cpp index c2e7ff4c64a..11c4526cbe6 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 d26dd792de7..5f6beae4235 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 a3468c3d636..0c30306074d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2145,20 +2145,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 @@ -3506,6 +3492,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++) @@ -3525,6 +3514,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"), @@ -3579,9 +3574,21 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin fprintf(stderr,"valueout %.8f too big\n",(double)valueout/COIN); return state.DoS(100, error("ConnectBlock(): GetValueOut too big"),REJECT_INVALID,"tx valueout is too big"); } - 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; @@ -3632,6 +3639,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); } @@ -3643,6 +3660,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; @@ -4694,9 +4740,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 @@ -4708,6 +4772,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; @@ -4729,18 +4810,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; } @@ -6048,11 +6141,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 { @@ -6060,12 +6173,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 3eb9b11422d..88355bb5e65 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -119,12 +119,14 @@ double GetNetworkDifficulty(const CBlockIndex* blockindex) } 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))); @@ -335,11 +337,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) @@ -854,6 +857,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" @@ -1339,6 +1359,19 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp, const CPubKey& my " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n" " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\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" @@ -1394,9 +1427,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 b87d3487439..357943285f7 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -738,6 +738,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;