diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 1303e6681..7b8a5a7c3 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -353,6 +353,12 @@ public: 715 // total number of tx / (checkpoint block height / (24 * 24)) }; + // Hardcoded fallback value for the Sprout shielded value pool balance + // for nodes that have not reindexed since the introduction of monitoring + // in #2795. + nSproutValuePoolCheckpointHeight = 440329; + nSproutValuePoolCheckpointBalance = 40000029096803; + // Founders reward script expects a vector of 2-of-3 multisig addresses vFoundersRewardAddress = { "t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi", "t2N9PH9Wk9xjqYg9iin1Ua3aekJqfAtE543", "t2NGQjYMQhFndDHguvUw4wZdNdsssA6K7x2", "t2ENg7hHVqqs9JwU5cgjvSbxnT2a9USNfhy", diff --git a/src/chainparams.h b/src/chainparams.h index 2649fa9be..90a0712ae 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -70,6 +70,9 @@ public: const std::vector& AlertKey() const { return vAlertPubKey; } int GetDefaultPort() const { return nDefaultPort; } + CAmount SproutValuePoolCheckpointHeight() const { return nSproutValuePoolCheckpointHeight; } + CAmount SproutValuePoolCheckpointBalance() const { return nSproutValuePoolCheckpointBalance; } + const CBlock& GenesisBlock() const { return genesis; } /** Make miner wait to have peers to avoid wasting work */ bool MiningRequiresPeers() const { return fMiningRequiresPeers; } @@ -125,6 +128,9 @@ protected: bool fTestnetToBeDeprecatedFieldRPC = false; CCheckpointData checkpointData; std::vector vFoundersRewardAddress; + + CAmount nSproutValuePoolCheckpointHeight = 0; + CAmount nSproutValuePoolCheckpointBalance = 0; }; /** diff --git a/src/main.cpp b/src/main.cpp index e11dcbc3c..2aeb9fcfc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3296,9 +3296,34 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block) return pindexNew; } +void FallbackSproutValuePoolBalance( + CBlockIndex *pindex, + const CChainParams& chainparams +) +{ + // Check if the height of this block matches the checkpoint + if (pindex->nHeight == chainparams.SproutValuePoolCheckpointHeight()) { + // Are we monitoring the Sprout pool? + if (!pindex->nChainSproutValue) { + // Apparently not. Introduce the hardcoded value. + pindex->nChainSproutValue = chainparams.SproutValuePoolCheckpointBalance(); + } else { + // Apparently we have been. So, we should expect the current + // value to match the hardcoded one. + assert(*pindex->nChainSproutValue == chainparams.SproutValuePoolCheckpointBalance()); + // And we should expect non-none for the delta stored in the block index here, + // or the checkpoint is too early. + assert(pindex->nSproutValue != boost::none); + } + } +} + /** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos) { + const CChainParams& chainparams = Params(); + bool this_is_testnet = chainparams.NetworkIDString() == "test"; + pindexNew->nTx = block.vtx.size(); pindexNew->nChainTx = 0; CAmount sproutValue = 0; @@ -3351,6 +3376,13 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl pindex->nChainSproutValue = pindex->nSproutValue; pindex->nChainSaplingValue = pindex->nSaplingValue; } + + // Fall back to hardcoded Sprout value pool balance if we're on + // testnet. + if (this_is_testnet) { + FallbackSproutValuePoolBalance(pindex, chainparams); + } + { LOCK(cs_nBlockSequenceId); pindex->nSequenceId = nBlockSequenceId++; @@ -4003,6 +4035,8 @@ CBlockIndex * InsertBlockIndex(uint256 hash) bool static LoadBlockIndexDB() { const CChainParams& chainparams = Params(); + bool this_is_testnet = chainparams.NetworkIDString() == "test"; + if (!pblocktree->LoadBlockIndexGuts()) return false; @@ -4032,6 +4066,7 @@ bool static LoadBlockIndexDB() } else { pindex->nChainSproutValue = boost::none; } + if (pindex->pprev->nChainSaplingValue) { pindex->nChainSaplingValue = *pindex->pprev->nChainSaplingValue + pindex->nSaplingValue; } else { @@ -4048,6 +4083,12 @@ bool static LoadBlockIndexDB() pindex->nChainSproutValue = pindex->nSproutValue; pindex->nChainSaplingValue = pindex->nSaplingValue; } + + // Fall back to hardcoded Sprout value pool balance if we're on + // testnet. + if (this_is_testnet) { + FallbackSproutValuePoolBalance(pindex, chainparams); + } } // Construct in-memory chain of branch IDs. // Relies on invariant: a block that does not activate a network upgrade