mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-22 06:52:36 +01:00
Merge #21391: [Bundle 5/n] Prune g_chainman usage in RPC modules
586190f0b4
rpc/rest: Take and reuse local Chain/ChainState obj (Carl Dong)bc3bd36902
rpc: style: Improve BuriedForkDescPushBack signature (Carl Dong)f99913969f
rpc: Remove unnecessary casting of block height (Carl Dong)6a3d192020
rpc: Tidy up local references (see commit message) (Carl Dong)038854f31e
rest/rpc: Remove now-unused old Ensure functions (Carl Dong)6fb65b49f4
scripted-diff: rest/rpc: Use renamed EnsureAny*() (Carl Dong)1570c7ee98
rpc: Add renamed EnsureAny*() functions (Carl Dong)306b1cd3ee
rpc: Add alt Ensure* functions acepting NodeContext (Carl Dong)d7824acdb9
rest: Use existing NodeContext (Carl Dong)3f08934799
rest: Pass in NodeContext to rest_block (Carl Dong)7be0671b95
rpc/rawtx: Use existing NodeContext (Carl Dong)60dc05afc6
rpc/mining: Use existing NodeContext (Carl Dong)d485e815e2
rpc/blockchain: Use existing NodeContext (Carl Dong)d0abf0bf42
rpc/*,rest: Add review-only assertion to EnsureChainman (Carl Dong)cced0f46c9
miner: Pass in previous CBlockIndex to RegenerateCommitments (Carl Dong) Pull request description: Overall PR: #20158 (tree-wide: De-globalize ChainstateManager) Based on: - [x] #21270 | [Bundle 4/n] Prune g_chainman usage in validation-adjacent modules - [x] #21525 | [Bundle 4.5/n] Followup fixups to bundle 4 Note to reviewers: 1. This bundle may _apparently_ introduce usage of `g_chainman` or `::Chain(state|)Active()` globals, but these are resolved later on in the overall PR. [Commits of overall PR](https://github.com/bitcoin/bitcoin/pull/20158/commits) 2. There may be seemingly obvious local references to `ChainstateManager` or other validation objects which are not being used in callers of the current function in question, this is done intentionally to **_keep each commit centered around one function/method_** to ease review and to make the overall change systematic. We don't assume anything about our callers. Rest assured that once we are considering that particular caller in later commits, we will use the obvious local references. [Commits of overall PR](https://github.com/bitcoin/bitcoin/pull/20158/commits) 3. When changing a function/method that has many callers (e.g. `LookupBlockIndex` with 55 callers), it is sometimes easier (and less error-prone) to use a scripted-diff. When doing so, there will be 3 commits in sequence so that every commit compiles like so: 1. Add `new_function`, make `old_function` a wrapper of `new_function`, divert all calls to `old_function` to `new_function` **in the local module only** 2. Scripted-diff to divert all calls to `old_function` to `new_function` **in the rest of the codebase** 3. Remove `old_function` ACKs for top commit: ryanofsky: Code review ACK586190f0b4
. Since last review, no changes to existing commits, just some simple new commits added: three new commits renaming std::any Ensure functions (scripted diff commit and manual pre/post commits), and one new commit factoring out a repeated `ActiveChain()` call made in a loop. Thanks for the updates! jnewbery: utACK586190f0b4
MarcoFalke: review ACK586190f0b4
🍯 Tree-SHA512: 64b677fb50141805b55c3f1afe68fcd298f9a071a359bdcd63256d52e334f83e462f31fb3ebee9b630da8f1d912a03a128cfc38179e7aaec29a055744a98478c
This commit is contained in:
commit
0dd7b23489
9 changed files with 271 additions and 183 deletions
|
@ -39,13 +39,14 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam
|
|||
return nNewTime - nOldTime;
|
||||
}
|
||||
|
||||
void RegenerateCommitments(CBlock& block, BlockManager& blockman)
|
||||
void RegenerateCommitments(CBlock& block, CBlockIndex* prev_block)
|
||||
{
|
||||
CMutableTransaction tx{*block.vtx.at(0)};
|
||||
tx.vout.erase(tx.vout.begin() + GetWitnessCommitmentIndex(block));
|
||||
block.vtx.at(0) = MakeTransactionRef(tx);
|
||||
|
||||
GenerateCoinbaseCommitment(block, WITH_LOCK(::cs_main, assert(std::addressof(g_chainman.m_blockman) == std::addressof(blockman)); return blockman.LookupBlockIndex(block.hashPrevBlock)), Params().GetConsensus());
|
||||
WITH_LOCK(::cs_main, assert(g_chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock) == prev_block));
|
||||
GenerateCoinbaseCommitment(block, prev_block, Params().GetConsensus());
|
||||
|
||||
block.hashMerkleRoot = BlockMerkleRoot(block);
|
||||
}
|
||||
|
|
|
@ -202,8 +202,7 @@ private:
|
|||
void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
|
||||
int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev);
|
||||
|
||||
// TODO just accept a CBlockIndex*
|
||||
/** Update an old GenerateCoinbaseCommitment from CreateNewBlock after the block txs have changed */
|
||||
void RegenerateCommitments(CBlock& block, BlockManager& blockman);
|
||||
void RegenerateCommitments(CBlock& block, CBlockIndex* prev_block);
|
||||
|
||||
#endif // BITCOIN_MINER_H
|
||||
|
|
41
src/rest.cpp
41
src/rest.cpp
|
@ -181,14 +181,16 @@ static bool rest_headers(const std::any& context,
|
|||
std::vector<const CBlockIndex *> headers;
|
||||
headers.reserve(count);
|
||||
{
|
||||
ChainstateManager& chainman = EnsureAnyChainman(context);
|
||||
LOCK(cs_main);
|
||||
tip = ::ChainActive().Tip();
|
||||
const CBlockIndex* pindex = g_chainman.m_blockman.LookupBlockIndex(hash);
|
||||
while (pindex != nullptr && ::ChainActive().Contains(pindex)) {
|
||||
CChain& active_chain = chainman.ActiveChain();
|
||||
tip = active_chain.Tip();
|
||||
const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(hash);
|
||||
while (pindex != nullptr && active_chain.Contains(pindex)) {
|
||||
headers.push_back(pindex);
|
||||
if (headers.size() == (unsigned long)count)
|
||||
break;
|
||||
pindex = ::ChainActive().Next(pindex);
|
||||
pindex = active_chain.Next(pindex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,7 +234,8 @@ static bool rest_headers(const std::any& context,
|
|||
}
|
||||
}
|
||||
|
||||
static bool rest_block(HTTPRequest* req,
|
||||
static bool rest_block(const std::any& context,
|
||||
HTTPRequest* req,
|
||||
const std::string& strURIPart,
|
||||
bool showTxDetails)
|
||||
{
|
||||
|
@ -249,9 +252,10 @@ static bool rest_block(HTTPRequest* req,
|
|||
CBlockIndex* pblockindex = nullptr;
|
||||
CBlockIndex* tip = nullptr;
|
||||
{
|
||||
ChainstateManager& chainman = EnsureAnyChainman(context);
|
||||
LOCK(cs_main);
|
||||
tip = ::ChainActive().Tip();
|
||||
pblockindex = g_chainman.m_blockman.LookupBlockIndex(hash);
|
||||
tip = chainman.ActiveChain().Tip();
|
||||
pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
|
||||
if (!pblockindex) {
|
||||
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
|
||||
}
|
||||
|
@ -298,12 +302,12 @@ static bool rest_block(HTTPRequest* req,
|
|||
|
||||
static bool rest_block_extended(const std::any& context, HTTPRequest* req, const std::string& strURIPart)
|
||||
{
|
||||
return rest_block(req, strURIPart, true);
|
||||
return rest_block(context, req, strURIPart, true);
|
||||
}
|
||||
|
||||
static bool rest_block_notxdetails(const std::any& context, HTTPRequest* req, const std::string& strURIPart)
|
||||
{
|
||||
return rest_block(req, strURIPart, false);
|
||||
return rest_block(context, req, strURIPart, false);
|
||||
}
|
||||
|
||||
// A bit of a hack - dependency on a function defined in rpc/blockchain.cpp
|
||||
|
@ -537,6 +541,7 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std::
|
|||
std::string bitmapStringRepresentation;
|
||||
std::vector<bool> hits;
|
||||
bitmap.resize((vOutPoints.size() + 7) / 8);
|
||||
ChainstateManager& chainman = EnsureAnyChainman(context);
|
||||
{
|
||||
auto process_utxos = [&vOutPoints, &outs, &hits](const CCoinsView& view, const CTxMemPool& mempool) {
|
||||
for (const COutPoint& vOutPoint : vOutPoints) {
|
||||
|
@ -552,12 +557,12 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std::
|
|||
if (!mempool) return false;
|
||||
// use db+mempool as cache backend in case user likes to query mempool
|
||||
LOCK2(cs_main, mempool->cs);
|
||||
CCoinsViewCache& viewChain = ::ChainstateActive().CoinsTip();
|
||||
CCoinsViewCache& viewChain = chainman.ActiveChainstate().CoinsTip();
|
||||
CCoinsViewMemPool viewMempool(&viewChain, *mempool);
|
||||
process_utxos(viewMempool, *mempool);
|
||||
} else {
|
||||
LOCK(cs_main); // no need to lock mempool!
|
||||
process_utxos(::ChainstateActive().CoinsTip(), CTxMemPool());
|
||||
process_utxos(chainman.ActiveChainstate().CoinsTip(), CTxMemPool());
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < hits.size(); ++i) {
|
||||
|
@ -572,7 +577,7 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std::
|
|||
// serialize data
|
||||
// use exact same output as mentioned in Bip64
|
||||
CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ssGetUTXOResponse << ::ChainActive().Height() << ::ChainActive().Tip()->GetBlockHash() << bitmap << outs;
|
||||
ssGetUTXOResponse << chainman.ActiveChain().Height() << chainman.ActiveChain().Tip()->GetBlockHash() << bitmap << outs;
|
||||
std::string ssGetUTXOResponseString = ssGetUTXOResponse.str();
|
||||
|
||||
req->WriteHeader("Content-Type", "application/octet-stream");
|
||||
|
@ -582,7 +587,7 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std::
|
|||
|
||||
case RetFormat::HEX: {
|
||||
CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ssGetUTXOResponse << ::ChainActive().Height() << ::ChainActive().Tip()->GetBlockHash() << bitmap << outs;
|
||||
ssGetUTXOResponse << chainman.ActiveChain().Height() << chainman.ActiveChain().Tip()->GetBlockHash() << bitmap << outs;
|
||||
std::string strHex = HexStr(ssGetUTXOResponse) + "\n";
|
||||
|
||||
req->WriteHeader("Content-Type", "text/plain");
|
||||
|
@ -595,8 +600,8 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std::
|
|||
|
||||
// pack in some essentials
|
||||
// use more or less the same output as mentioned in Bip64
|
||||
objGetUTXOResponse.pushKV("chainHeight", ::ChainActive().Height());
|
||||
objGetUTXOResponse.pushKV("chaintipHash", ::ChainActive().Tip()->GetBlockHash().GetHex());
|
||||
objGetUTXOResponse.pushKV("chainHeight", chainman.ActiveChain().Height());
|
||||
objGetUTXOResponse.pushKV("chaintipHash", chainman.ActiveChain().Tip()->GetBlockHash().GetHex());
|
||||
objGetUTXOResponse.pushKV("bitmap", bitmapStringRepresentation);
|
||||
|
||||
UniValue utxos(UniValue::VARR);
|
||||
|
@ -639,11 +644,13 @@ static bool rest_blockhash_by_height(const std::any& context, HTTPRequest* req,
|
|||
|
||||
CBlockIndex* pblockindex = nullptr;
|
||||
{
|
||||
ChainstateManager& chainman = EnsureAnyChainman(context);
|
||||
LOCK(cs_main);
|
||||
if (blockheight > ::ChainActive().Height()) {
|
||||
const CChain& active_chain = chainman.ActiveChain();
|
||||
if (blockheight > active_chain.Height()) {
|
||||
return RESTERR(req, HTTP_NOT_FOUND, "Block height out of range");
|
||||
}
|
||||
pblockindex = ::ChainActive()[blockheight];
|
||||
pblockindex = active_chain[blockheight];
|
||||
}
|
||||
switch (rf) {
|
||||
case RetFormat::BINARY: {
|
||||
|
|
|
@ -56,7 +56,7 @@ static Mutex cs_blockchange;
|
|||
static std::condition_variable cond_blockchange;
|
||||
static CUpdatedBlock latestblock GUARDED_BY(cs_blockchange);
|
||||
|
||||
NodeContext& EnsureNodeContext(const std::any& context)
|
||||
NodeContext& EnsureAnyNodeContext(const std::any& context)
|
||||
{
|
||||
auto node_context = util::AnyPtr<NodeContext>(context);
|
||||
if (!node_context) {
|
||||
|
@ -65,33 +65,46 @@ NodeContext& EnsureNodeContext(const std::any& context)
|
|||
return *node_context;
|
||||
}
|
||||
|
||||
CTxMemPool& EnsureMemPool(const std::any& context)
|
||||
CTxMemPool& EnsureMemPool(const NodeContext& node)
|
||||
{
|
||||
const NodeContext& node = EnsureNodeContext(context);
|
||||
if (!node.mempool) {
|
||||
throw JSONRPCError(RPC_CLIENT_MEMPOOL_DISABLED, "Mempool disabled or instance not found");
|
||||
}
|
||||
return *node.mempool;
|
||||
}
|
||||
|
||||
ChainstateManager& EnsureChainman(const std::any& context)
|
||||
CTxMemPool& EnsureAnyMemPool(const std::any& context)
|
||||
{
|
||||
return EnsureMemPool(EnsureAnyNodeContext(context));
|
||||
}
|
||||
|
||||
ChainstateManager& EnsureChainman(const NodeContext& node)
|
||||
{
|
||||
const NodeContext& node = EnsureNodeContext(context);
|
||||
if (!node.chainman) {
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Node chainman not found");
|
||||
}
|
||||
WITH_LOCK(::cs_main, CHECK_NONFATAL(std::addressof(g_chainman) == std::addressof(*node.chainman)));
|
||||
return *node.chainman;
|
||||
}
|
||||
|
||||
CBlockPolicyEstimator& EnsureFeeEstimator(const std::any& context)
|
||||
ChainstateManager& EnsureAnyChainman(const std::any& context)
|
||||
{
|
||||
return EnsureChainman(EnsureAnyNodeContext(context));
|
||||
}
|
||||
|
||||
CBlockPolicyEstimator& EnsureFeeEstimator(const NodeContext& node)
|
||||
{
|
||||
NodeContext& node = EnsureNodeContext(context);
|
||||
if (!node.fee_estimator) {
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Fee estimation disabled");
|
||||
}
|
||||
return *node.fee_estimator;
|
||||
}
|
||||
|
||||
CBlockPolicyEstimator& EnsureAnyFeeEstimator(const std::any& context)
|
||||
{
|
||||
return EnsureFeeEstimator(EnsureAnyNodeContext(context));
|
||||
}
|
||||
|
||||
/* Calculate the difficulty for a given block index.
|
||||
*/
|
||||
double GetDifficulty(const CBlockIndex* blockindex)
|
||||
|
@ -198,8 +211,9 @@ static RPCHelpMan getblockcount()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
LOCK(cs_main);
|
||||
return ::ChainActive().Height();
|
||||
return chainman.ActiveChain().Height();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -217,8 +231,9 @@ static RPCHelpMan getbestblockhash()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
LOCK(cs_main);
|
||||
return ::ChainActive().Tip()->GetBlockHash().GetHex();
|
||||
return chainman.ActiveChain().Tip()->GetBlockHash().GetHex();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -398,8 +413,9 @@ static RPCHelpMan getdifficulty()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
LOCK(cs_main);
|
||||
return GetDifficulty(::ChainActive().Tip());
|
||||
return GetDifficulty(chainman.ActiveChain().Tip());
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -581,7 +597,7 @@ static RPCHelpMan getrawmempool()
|
|||
include_mempool_sequence = request.params[1].get_bool();
|
||||
}
|
||||
|
||||
return MempoolToJSON(EnsureMemPool(request.context), fVerbose, include_mempool_sequence);
|
||||
return MempoolToJSON(EnsureAnyMemPool(request.context), fVerbose, include_mempool_sequence);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -616,7 +632,7 @@ static RPCHelpMan getmempoolancestors()
|
|||
|
||||
uint256 hash = ParseHashV(request.params[0], "parameter 1");
|
||||
|
||||
const CTxMemPool& mempool = EnsureMemPool(request.context);
|
||||
const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
|
||||
LOCK(mempool.cs);
|
||||
|
||||
CTxMemPool::txiter it = mempool.mapTx.find(hash);
|
||||
|
@ -680,7 +696,7 @@ static RPCHelpMan getmempooldescendants()
|
|||
|
||||
uint256 hash = ParseHashV(request.params[0], "parameter 1");
|
||||
|
||||
const CTxMemPool& mempool = EnsureMemPool(request.context);
|
||||
const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
|
||||
LOCK(mempool.cs);
|
||||
|
||||
CTxMemPool::txiter it = mempool.mapTx.find(hash);
|
||||
|
@ -732,7 +748,7 @@ static RPCHelpMan getmempoolentry()
|
|||
{
|
||||
uint256 hash = ParseHashV(request.params[0], "parameter 1");
|
||||
|
||||
const CTxMemPool& mempool = EnsureMemPool(request.context);
|
||||
const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
|
||||
LOCK(mempool.cs);
|
||||
|
||||
CTxMemPool::txiter it = mempool.mapTx.find(hash);
|
||||
|
@ -763,13 +779,15 @@ static RPCHelpMan getblockhash()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
LOCK(cs_main);
|
||||
const CChain& active_chain = chainman.ActiveChain();
|
||||
|
||||
int nHeight = request.params[0].get_int();
|
||||
if (nHeight < 0 || nHeight > ::ChainActive().Height())
|
||||
if (nHeight < 0 || nHeight > active_chain.Height())
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
|
||||
|
||||
CBlockIndex* pblockindex = ::ChainActive()[nHeight];
|
||||
CBlockIndex* pblockindex = active_chain[nHeight];
|
||||
return pblockindex->GetBlockHash().GetHex();
|
||||
},
|
||||
};
|
||||
|
@ -822,9 +840,10 @@ static RPCHelpMan getblockheader()
|
|||
const CBlockIndex* pblockindex;
|
||||
const CBlockIndex* tip;
|
||||
{
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
LOCK(cs_main);
|
||||
pblockindex = g_chainman.m_blockman.LookupBlockIndex(hash);
|
||||
tip = ::ChainActive().Tip();
|
||||
pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
|
||||
tip = chainman.ActiveChain().Tip();
|
||||
}
|
||||
|
||||
if (!pblockindex) {
|
||||
|
@ -946,9 +965,10 @@ static RPCHelpMan getblock()
|
|||
const CBlockIndex* pblockindex;
|
||||
const CBlockIndex* tip;
|
||||
{
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
LOCK(cs_main);
|
||||
pblockindex = g_chainman.m_blockman.LookupBlockIndex(hash);
|
||||
tip = ::ChainActive().Tip();
|
||||
pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
|
||||
tip = chainman.ActiveChain().Tip();
|
||||
|
||||
if (!pblockindex) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
||||
|
@ -988,7 +1008,10 @@ static RPCHelpMan pruneblockchain()
|
|||
if (!fPruneMode)
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "Cannot prune blocks because node is not in prune mode.");
|
||||
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
LOCK(cs_main);
|
||||
CChainState& active_chainstate = chainman.ActiveChainstate();
|
||||
CChain& active_chain = active_chainstate.m_chain;
|
||||
|
||||
int heightParam = request.params[0].get_int();
|
||||
if (heightParam < 0)
|
||||
|
@ -998,7 +1021,7 @@ static RPCHelpMan pruneblockchain()
|
|||
// too low to be a block time (corresponds to timestamp from Sep 2001).
|
||||
if (heightParam > 1000000000) {
|
||||
// Add a 2 hour buffer to include blocks which might have had old timestamps
|
||||
CBlockIndex* pindex = ::ChainActive().FindEarliestAtLeast(heightParam - TIMESTAMP_WINDOW, 0);
|
||||
CBlockIndex* pindex = active_chain.FindEarliestAtLeast(heightParam - TIMESTAMP_WINDOW, 0);
|
||||
if (!pindex) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Could not find block with at least the specified timestamp.");
|
||||
}
|
||||
|
@ -1006,7 +1029,7 @@ static RPCHelpMan pruneblockchain()
|
|||
}
|
||||
|
||||
unsigned int height = (unsigned int) heightParam;
|
||||
unsigned int chainHeight = (unsigned int) ::ChainActive().Height();
|
||||
unsigned int chainHeight = (unsigned int) active_chain.Height();
|
||||
if (chainHeight < Params().PruneAfterHeight())
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "Blockchain is too short for pruning.");
|
||||
else if (height > chainHeight)
|
||||
|
@ -1016,8 +1039,8 @@ static RPCHelpMan pruneblockchain()
|
|||
height = chainHeight - MIN_BLOCKS_TO_KEEP;
|
||||
}
|
||||
|
||||
PruneBlockFilesManual(::ChainstateActive(), height);
|
||||
const CBlockIndex* block = ::ChainActive().Tip();
|
||||
PruneBlockFilesManual(active_chainstate, height);
|
||||
const CBlockIndex* block = active_chain.Tip();
|
||||
CHECK_NONFATAL(block);
|
||||
while (block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) {
|
||||
block = block->pprev;
|
||||
|
@ -1070,13 +1093,21 @@ static RPCHelpMan gettxoutsetinfo()
|
|||
UniValue ret(UniValue::VOBJ);
|
||||
|
||||
CCoinsStats stats;
|
||||
::ChainstateActive().ForceFlushStateToDisk();
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
ChainstateManager& chainman = EnsureChainman(node);
|
||||
CChainState& active_chainstate = chainman.ActiveChainstate();
|
||||
active_chainstate.ForceFlushStateToDisk();
|
||||
|
||||
const CoinStatsHashType hash_type{request.params[0].isNull() ? CoinStatsHashType::HASH_SERIALIZED : ParseHashType(request.params[0].get_str())};
|
||||
|
||||
CCoinsView* coins_view = WITH_LOCK(::cs_main, return &::ChainstateActive().CoinsDB());
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
if (GetUTXOStats(coins_view, WITH_LOCK(::cs_main, return std::ref(g_chainman.m_blockman)), stats, hash_type, node.rpc_interruption_point)) {
|
||||
CCoinsView* coins_view;
|
||||
BlockManager* blockman;
|
||||
{
|
||||
LOCK(::cs_main);
|
||||
coins_view = &active_chainstate.CoinsDB();
|
||||
blockman = &active_chainstate.m_blockman;
|
||||
}
|
||||
if (GetUTXOStats(coins_view, *blockman, stats, hash_type, node.rpc_interruption_point)) {
|
||||
ret.pushKV("height", (int64_t)stats.nHeight);
|
||||
ret.pushKV("bestblock", stats.hashBlock.GetHex());
|
||||
ret.pushKV("transactions", (int64_t)stats.nTransactions);
|
||||
|
@ -1135,6 +1166,8 @@ static RPCHelpMan gettxout()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
ChainstateManager& chainman = EnsureChainman(node);
|
||||
LOCK(cs_main);
|
||||
|
||||
UniValue ret(UniValue::VOBJ);
|
||||
|
@ -1147,10 +1180,11 @@ static RPCHelpMan gettxout()
|
|||
fMempool = request.params[2].get_bool();
|
||||
|
||||
Coin coin;
|
||||
CCoinsViewCache* coins_view = &::ChainstateActive().CoinsTip();
|
||||
CChainState& active_chainstate = chainman.ActiveChainstate();
|
||||
CCoinsViewCache* coins_view = &active_chainstate.CoinsTip();
|
||||
|
||||
if (fMempool) {
|
||||
const CTxMemPool& mempool = EnsureMemPool(request.context);
|
||||
const CTxMemPool& mempool = EnsureMemPool(node);
|
||||
LOCK(mempool.cs);
|
||||
CCoinsViewMemPool view(coins_view, mempool);
|
||||
if (!view.GetCoin(out, coin) || mempool.isSpent(out)) {
|
||||
|
@ -1162,7 +1196,7 @@ static RPCHelpMan gettxout()
|
|||
}
|
||||
}
|
||||
|
||||
const CBlockIndex* pindex = g_chainman.m_blockman.LookupBlockIndex(coins_view->GetBestBlock());
|
||||
const CBlockIndex* pindex = active_chainstate.m_blockman.LookupBlockIndex(coins_view->GetBestBlock());
|
||||
ret.pushKV("bestblock", pindex->GetBlockHash().GetHex());
|
||||
if (coin.nHeight == MEMPOOL_HEIGHT) {
|
||||
ret.pushKV("confirmations", 0);
|
||||
|
@ -1200,39 +1234,41 @@ static RPCHelpMan verifychain()
|
|||
const int check_level(request.params[0].isNull() ? DEFAULT_CHECKLEVEL : request.params[0].get_int());
|
||||
const int check_depth{request.params[1].isNull() ? DEFAULT_CHECKBLOCKS : request.params[1].get_int()};
|
||||
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
LOCK(cs_main);
|
||||
|
||||
return CVerifyDB().VerifyDB(Params(), ::ChainstateActive(), &::ChainstateActive().CoinsTip(), check_level, check_depth);
|
||||
CChainState& active_chainstate = chainman.ActiveChainstate();
|
||||
return CVerifyDB().VerifyDB(Params(), active_chainstate, &active_chainstate.CoinsTip(), check_level, check_depth);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static void BuriedForkDescPushBack(UniValue& softforks, const std::string &name, int height) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
static void BuriedForkDescPushBack(UniValue& softforks, const std::string &name, int softfork_height, int tip_height) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
// For buried deployments.
|
||||
// A buried deployment is one where the height of the activation has been hardcoded into
|
||||
// the client implementation long after the consensus change has activated. See BIP 90.
|
||||
// Buried deployments with activation height value of
|
||||
// std::numeric_limits<int>::max() are disabled and thus hidden.
|
||||
if (height == std::numeric_limits<int>::max()) return;
|
||||
if (softfork_height == std::numeric_limits<int>::max()) return;
|
||||
|
||||
UniValue rv(UniValue::VOBJ);
|
||||
rv.pushKV("type", "buried");
|
||||
// getblockchaininfo reports the softfork as active from when the chain height is
|
||||
// one below the activation height
|
||||
rv.pushKV("active", ::ChainActive().Tip()->nHeight + 1 >= height);
|
||||
rv.pushKV("height", height);
|
||||
rv.pushKV("active", tip_height + 1 >= softfork_height);
|
||||
rv.pushKV("height", softfork_height);
|
||||
softforks.pushKV(name, rv);
|
||||
}
|
||||
|
||||
static void BIP9SoftForkDescPushBack(UniValue& softforks, const std::string &name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
static void BIP9SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& softforks, const std::string &name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
// For BIP9 deployments.
|
||||
// Deployments that are never active are hidden.
|
||||
if (consensusParams.vDeployments[id].nStartTime == Consensus::BIP9Deployment::NEVER_ACTIVE) return;
|
||||
|
||||
UniValue bip9(UniValue::VOBJ);
|
||||
const ThresholdState thresholdState = VersionBitsState(::ChainActive().Tip(), consensusParams, id, versionbitscache);
|
||||
const ThresholdState thresholdState = VersionBitsState(active_chain_tip, consensusParams, id, versionbitscache);
|
||||
switch (thresholdState) {
|
||||
case ThresholdState::DEFINED: bip9.pushKV("status", "defined"); break;
|
||||
case ThresholdState::STARTED: bip9.pushKV("status", "started"); break;
|
||||
|
@ -1246,12 +1282,12 @@ static void BIP9SoftForkDescPushBack(UniValue& softforks, const std::string &nam
|
|||
}
|
||||
bip9.pushKV("start_time", consensusParams.vDeployments[id].nStartTime);
|
||||
bip9.pushKV("timeout", consensusParams.vDeployments[id].nTimeout);
|
||||
int64_t since_height = VersionBitsStateSinceHeight(::ChainActive().Tip(), consensusParams, id, versionbitscache);
|
||||
int64_t since_height = VersionBitsStateSinceHeight(active_chain_tip, consensusParams, id, versionbitscache);
|
||||
bip9.pushKV("since", since_height);
|
||||
if (ThresholdState::STARTED == thresholdState)
|
||||
{
|
||||
UniValue statsUV(UniValue::VOBJ);
|
||||
BIP9Stats statsStruct = VersionBitsStatistics(::ChainActive().Tip(), consensusParams, id);
|
||||
BIP9Stats statsStruct = VersionBitsStatistics(active_chain_tip, consensusParams, id);
|
||||
statsUV.pushKV("period", statsStruct.period);
|
||||
statsUV.pushKV("threshold", statsStruct.threshold);
|
||||
statsUV.pushKV("elapsed", statsStruct.elapsed);
|
||||
|
@ -1328,18 +1364,22 @@ RPCHelpMan getblockchaininfo()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
LOCK(cs_main);
|
||||
CChainState& active_chainstate = chainman.ActiveChainstate();
|
||||
|
||||
const CBlockIndex* tip = ::ChainActive().Tip();
|
||||
const CBlockIndex* tip = active_chainstate.m_chain.Tip();
|
||||
CHECK_NONFATAL(tip);
|
||||
const int height = tip->nHeight;
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.pushKV("chain", Params().NetworkIDString());
|
||||
obj.pushKV("blocks", (int)::ChainActive().Height());
|
||||
obj.pushKV("blocks", height);
|
||||
obj.pushKV("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1);
|
||||
obj.pushKV("bestblockhash", tip->GetBlockHash().GetHex());
|
||||
obj.pushKV("difficulty", (double)GetDifficulty(tip));
|
||||
obj.pushKV("mediantime", (int64_t)tip->GetMedianTimePast());
|
||||
obj.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), tip));
|
||||
obj.pushKV("initialblockdownload", ::ChainstateActive().IsInitialBlockDownload());
|
||||
obj.pushKV("initialblockdownload", active_chainstate.IsInitialBlockDownload());
|
||||
obj.pushKV("chainwork", tip->nChainWork.GetHex());
|
||||
obj.pushKV("size_on_disk", CalculateCurrentUsage());
|
||||
obj.pushKV("pruned", fPruneMode);
|
||||
|
@ -1362,13 +1402,13 @@ RPCHelpMan getblockchaininfo()
|
|||
|
||||
const Consensus::Params& consensusParams = Params().GetConsensus();
|
||||
UniValue softforks(UniValue::VOBJ);
|
||||
BuriedForkDescPushBack(softforks, "bip34", consensusParams.BIP34Height);
|
||||
BuriedForkDescPushBack(softforks, "bip66", consensusParams.BIP66Height);
|
||||
BuriedForkDescPushBack(softforks, "bip65", consensusParams.BIP65Height);
|
||||
BuriedForkDescPushBack(softforks, "csv", consensusParams.CSVHeight);
|
||||
BuriedForkDescPushBack(softforks, "segwit", consensusParams.SegwitHeight);
|
||||
BIP9SoftForkDescPushBack(softforks, "testdummy", consensusParams, Consensus::DEPLOYMENT_TESTDUMMY);
|
||||
BIP9SoftForkDescPushBack(softforks, "taproot", consensusParams, Consensus::DEPLOYMENT_TAPROOT);
|
||||
BuriedForkDescPushBack(softforks, "bip34", consensusParams.BIP34Height, height);
|
||||
BuriedForkDescPushBack(softforks, "bip66", consensusParams.BIP66Height, height);
|
||||
BuriedForkDescPushBack(softforks, "bip65", consensusParams.BIP65Height, height);
|
||||
BuriedForkDescPushBack(softforks, "csv", consensusParams.CSVHeight, height);
|
||||
BuriedForkDescPushBack(softforks, "segwit", consensusParams.SegwitHeight, height);
|
||||
BIP9SoftForkDescPushBack(tip, softforks, "testdummy", consensusParams, Consensus::DEPLOYMENT_TESTDUMMY);
|
||||
BIP9SoftForkDescPushBack(tip, softforks, "taproot", consensusParams, Consensus::DEPLOYMENT_TAPROOT);
|
||||
obj.pushKV("softforks", softforks);
|
||||
|
||||
obj.pushKV("warnings", GetWarnings(false).original);
|
||||
|
@ -1419,8 +1459,9 @@ static RPCHelpMan getchaintips()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
ChainstateManager& chainman = EnsureChainman(request.context);
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
LOCK(cs_main);
|
||||
CChain& active_chain = chainman.ActiveChain();
|
||||
|
||||
/*
|
||||
* Idea: The set of chain tips is the active chain tip, plus orphan blocks which do not have another orphan building off of them.
|
||||
|
@ -1434,7 +1475,7 @@ static RPCHelpMan getchaintips()
|
|||
std::set<const CBlockIndex*> setPrevs;
|
||||
|
||||
for (const std::pair<const uint256, CBlockIndex*>& item : chainman.BlockIndex()) {
|
||||
if (!chainman.ActiveChain().Contains(item.second)) {
|
||||
if (!active_chain.Contains(item.second)) {
|
||||
setOrphans.insert(item.second);
|
||||
setPrevs.insert(item.second->pprev);
|
||||
}
|
||||
|
@ -1447,7 +1488,7 @@ static RPCHelpMan getchaintips()
|
|||
}
|
||||
|
||||
// Always report the currently active tip.
|
||||
setTips.insert(chainman.ActiveChain().Tip());
|
||||
setTips.insert(active_chain.Tip());
|
||||
|
||||
/* Construct the output array. */
|
||||
UniValue res(UniValue::VARR);
|
||||
|
@ -1456,11 +1497,11 @@ static RPCHelpMan getchaintips()
|
|||
obj.pushKV("height", block->nHeight);
|
||||
obj.pushKV("hash", block->phashBlock->GetHex());
|
||||
|
||||
const int branchLen = block->nHeight - chainman.ActiveChain().FindFork(block)->nHeight;
|
||||
const int branchLen = block->nHeight - active_chain.FindFork(block)->nHeight;
|
||||
obj.pushKV("branchlen", branchLen);
|
||||
|
||||
std::string status;
|
||||
if (chainman.ActiveChain().Contains(block)) {
|
||||
if (active_chain.Contains(block)) {
|
||||
// This block is part of the currently active chain.
|
||||
status = "active";
|
||||
} else if (block->nStatus & BLOCK_FAILED_MASK) {
|
||||
|
@ -1531,7 +1572,7 @@ static RPCHelpMan getmempoolinfo()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
return MempoolInfoToJSON(EnsureMemPool(request.context));
|
||||
return MempoolInfoToJSON(EnsureAnyMemPool(request.context));
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1555,16 +1596,17 @@ static RPCHelpMan preciousblock()
|
|||
uint256 hash(ParseHashV(request.params[0], "blockhash"));
|
||||
CBlockIndex* pblockindex;
|
||||
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
{
|
||||
LOCK(cs_main);
|
||||
pblockindex = g_chainman.m_blockman.LookupBlockIndex(hash);
|
||||
pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
|
||||
if (!pblockindex) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
||||
}
|
||||
}
|
||||
|
||||
BlockValidationState state;
|
||||
::ChainstateActive().PreciousBlock(state, Params(), pblockindex);
|
||||
chainman.ActiveChainstate().PreciousBlock(state, Params(), pblockindex);
|
||||
|
||||
if (!state.IsValid()) {
|
||||
throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString());
|
||||
|
@ -1592,18 +1634,19 @@ static RPCHelpMan invalidateblock()
|
|||
uint256 hash(ParseHashV(request.params[0], "blockhash"));
|
||||
BlockValidationState state;
|
||||
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
CBlockIndex* pblockindex;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
pblockindex = g_chainman.m_blockman.LookupBlockIndex(hash);
|
||||
pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
|
||||
if (!pblockindex) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
||||
}
|
||||
}
|
||||
::ChainstateActive().InvalidateBlock(state, Params(), pblockindex);
|
||||
chainman.ActiveChainstate().InvalidateBlock(state, Params(), pblockindex);
|
||||
|
||||
if (state.IsValid()) {
|
||||
::ChainstateActive().ActivateBestChain(state, Params());
|
||||
chainman.ActiveChainstate().ActivateBestChain(state, Params());
|
||||
}
|
||||
|
||||
if (!state.IsValid()) {
|
||||
|
@ -1630,20 +1673,21 @@ static RPCHelpMan reconsiderblock()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
uint256 hash(ParseHashV(request.params[0], "blockhash"));
|
||||
|
||||
{
|
||||
LOCK(cs_main);
|
||||
CBlockIndex* pblockindex = g_chainman.m_blockman.LookupBlockIndex(hash);
|
||||
CBlockIndex* pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
|
||||
if (!pblockindex) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
||||
}
|
||||
|
||||
::ChainstateActive().ResetBlockFailureFlags(pblockindex);
|
||||
chainman.ActiveChainstate().ResetBlockFailureFlags(pblockindex);
|
||||
}
|
||||
|
||||
BlockValidationState state;
|
||||
::ChainstateActive().ActivateBestChain(state, Params());
|
||||
chainman.ActiveChainstate().ActivateBestChain(state, Params());
|
||||
|
||||
if (!state.IsValid()) {
|
||||
throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString());
|
||||
|
@ -1680,20 +1724,21 @@ static RPCHelpMan getchaintxstats()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
const CBlockIndex* pindex;
|
||||
int blockcount = 30 * 24 * 60 * 60 / Params().GetConsensus().nPowTargetSpacing; // By default: 1 month
|
||||
|
||||
if (request.params[1].isNull()) {
|
||||
LOCK(cs_main);
|
||||
pindex = ::ChainActive().Tip();
|
||||
pindex = chainman.ActiveChain().Tip();
|
||||
} else {
|
||||
uint256 hash(ParseHashV(request.params[1], "blockhash"));
|
||||
LOCK(cs_main);
|
||||
pindex = g_chainman.m_blockman.LookupBlockIndex(hash);
|
||||
pindex = chainman.m_blockman.LookupBlockIndex(hash);
|
||||
if (!pindex) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
||||
}
|
||||
if (!::ChainActive().Contains(pindex)) {
|
||||
if (!chainman.ActiveChain().Contains(pindex)) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block is not in main chain");
|
||||
}
|
||||
}
|
||||
|
@ -1861,12 +1906,14 @@ static RPCHelpMan getblockstats()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
LOCK(cs_main);
|
||||
CChain& active_chain = chainman.ActiveChain();
|
||||
|
||||
CBlockIndex* pindex;
|
||||
if (request.params[0].isNum()) {
|
||||
const int height = request.params[0].get_int();
|
||||
const int current_tip = ::ChainActive().Height();
|
||||
const int current_tip = active_chain.Height();
|
||||
if (height < 0) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Target block height %d is negative", height));
|
||||
}
|
||||
|
@ -1874,14 +1921,14 @@ static RPCHelpMan getblockstats()
|
|||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Target block height %d after current tip %d", height, current_tip));
|
||||
}
|
||||
|
||||
pindex = ::ChainActive()[height];
|
||||
pindex = active_chain[height];
|
||||
} else {
|
||||
const uint256 hash(ParseHashV(request.params[0], "hash_or_height"));
|
||||
pindex = g_chainman.m_blockman.LookupBlockIndex(hash);
|
||||
pindex = chainman.m_blockman.LookupBlockIndex(hash);
|
||||
if (!pindex) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
||||
}
|
||||
if (!::ChainActive().Contains(pindex)) {
|
||||
if (!active_chain.Contains(pindex)) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Block is not in chain %s", Params().NetworkIDString()));
|
||||
}
|
||||
}
|
||||
|
@ -2072,7 +2119,7 @@ static RPCHelpMan savemempool()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
const CTxMemPool& mempool = EnsureMemPool(request.context);
|
||||
const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
|
||||
|
||||
if (!mempool.IsLoaded()) {
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "The mempool was not loaded yet");
|
||||
|
@ -2262,15 +2309,17 @@ static RPCHelpMan scantxoutset()
|
|||
int64_t count = 0;
|
||||
std::unique_ptr<CCoinsViewCursor> pcursor;
|
||||
CBlockIndex* tip;
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
{
|
||||
ChainstateManager& chainman = EnsureChainman(node);
|
||||
LOCK(cs_main);
|
||||
::ChainstateActive().ForceFlushStateToDisk();
|
||||
pcursor = std::unique_ptr<CCoinsViewCursor>(::ChainstateActive().CoinsDB().Cursor());
|
||||
CChainState& active_chainstate = chainman.ActiveChainstate();
|
||||
active_chainstate.ForceFlushStateToDisk();
|
||||
pcursor = std::unique_ptr<CCoinsViewCursor>(active_chainstate.CoinsDB().Cursor());
|
||||
CHECK_NONFATAL(pcursor);
|
||||
tip = ::ChainActive().Tip();
|
||||
tip = active_chainstate.m_chain.Tip();
|
||||
CHECK_NONFATAL(tip);
|
||||
}
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
bool res = FindScriptPubKey(g_scan_progress, g_should_abort_scan, count, pcursor.get(), needles, coins, node.rpc_interruption_point);
|
||||
result.pushKV("success", res);
|
||||
result.pushKV("txouts", count);
|
||||
|
@ -2343,8 +2392,9 @@ static RPCHelpMan getblockfilter()
|
|||
const CBlockIndex* block_index;
|
||||
bool block_was_connected;
|
||||
{
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
LOCK(cs_main);
|
||||
block_index = g_chainman.m_blockman.LookupBlockIndex(block_hash);
|
||||
block_index = chainman.m_blockman.LookupBlockIndex(block_hash);
|
||||
if (!block_index) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
||||
}
|
||||
|
@ -2427,7 +2477,7 @@ static RPCHelpMan dumptxoutset()
|
|||
|
||||
FILE* file{fsbridge::fopen(temppath, "wb")};
|
||||
CAutoFile afile{file, SER_DISK, CLIENT_VERSION};
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
UniValue result = CreateUTXOSnapshot(node, node.chainman->ActiveChainstate(), afile);
|
||||
fs::rename(temppath, path);
|
||||
|
||||
|
@ -2465,7 +2515,7 @@ UniValue CreateUTXOSnapshot(NodeContext& node, CChainState& chainstate, CAutoFil
|
|||
}
|
||||
|
||||
pcursor = std::unique_ptr<CCoinsViewCursor>(chainstate.CoinsDB().Cursor());
|
||||
tip = g_chainman.m_blockman.LookupBlockIndex(stats.hashBlock);
|
||||
tip = chainstate.m_blockman.LookupBlockIndex(stats.hashBlock);
|
||||
CHECK_NONFATAL(tip);
|
||||
}
|
||||
|
||||
|
|
|
@ -56,10 +56,13 @@ void CalculatePercentilesByWeight(CAmount result[NUM_GETBLOCKSTATS_PERCENTILES],
|
|||
void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
|
||||
void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex = true, int serialize_flags = 0, const CTxUndo* txundo = nullptr);
|
||||
|
||||
NodeContext& EnsureNodeContext(const std::any& context);
|
||||
CTxMemPool& EnsureMemPool(const std::any& context);
|
||||
ChainstateManager& EnsureChainman(const std::any& context);
|
||||
CBlockPolicyEstimator& EnsureFeeEstimator(const std::any& context);
|
||||
NodeContext& EnsureAnyNodeContext(const std::any& context);
|
||||
CTxMemPool& EnsureMemPool(const NodeContext& node);
|
||||
CTxMemPool& EnsureAnyMemPool(const std::any& context);
|
||||
ChainstateManager& EnsureChainman(const NodeContext& node);
|
||||
ChainstateManager& EnsureAnyChainman(const std::any& context);
|
||||
CBlockPolicyEstimator& EnsureFeeEstimator(const NodeContext& node);
|
||||
CBlockPolicyEstimator& EnsureAnyFeeEstimator(const std::any& context);
|
||||
|
||||
/**
|
||||
* Helper to create UTXO snapshots given a chainstate and a file handle.
|
||||
|
|
|
@ -44,11 +44,12 @@
|
|||
* or from the last difficulty change if 'lookup' is nonpositive.
|
||||
* If 'height' is nonnegative, compute the estimate at the time when a given block was found.
|
||||
*/
|
||||
static UniValue GetNetworkHashPS(int lookup, int height) {
|
||||
CBlockIndex *pb = ::ChainActive().Tip();
|
||||
static UniValue GetNetworkHashPS(int lookup, int height, const CChain& active_chain) {
|
||||
const CBlockIndex* pb = active_chain.Tip();
|
||||
|
||||
if (height >= 0 && height < ::ChainActive().Height())
|
||||
pb = ::ChainActive()[height];
|
||||
if (height >= 0 && height < active_chain.Height()) {
|
||||
pb = active_chain[height];
|
||||
}
|
||||
|
||||
if (pb == nullptr || !pb->nHeight)
|
||||
return 0;
|
||||
|
@ -61,7 +62,7 @@ static UniValue GetNetworkHashPS(int lookup, int height) {
|
|||
if (lookup > pb->nHeight)
|
||||
lookup = pb->nHeight;
|
||||
|
||||
CBlockIndex *pb0 = pb;
|
||||
const CBlockIndex* pb0 = pb;
|
||||
int64_t minTime = pb0->GetBlockTime();
|
||||
int64_t maxTime = minTime;
|
||||
for (int i = 0; i < lookup; i++) {
|
||||
|
@ -99,8 +100,9 @@ static RPCHelpMan getnetworkhashps()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
LOCK(cs_main);
|
||||
return GetNetworkHashPS(!request.params[0].isNull() ? request.params[0].get_int() : 120, !request.params[1].isNull() ? request.params[1].get_int() : -1);
|
||||
return GetNetworkHashPS(!request.params[0].isNull() ? request.params[0].get_int() : 120, !request.params[1].isNull() ? request.params[1].get_int() : -1, chainman.ActiveChain());
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -111,7 +113,8 @@ static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t&
|
|||
|
||||
{
|
||||
LOCK(cs_main);
|
||||
IncrementExtraNonce(&block, ::ChainActive().Tip(), extra_nonce);
|
||||
CHECK_NONFATAL(std::addressof(::ChainActive()) == std::addressof(chainman.ActiveChain()));
|
||||
IncrementExtraNonce(&block, chainman.ActiveChain().Tip(), extra_nonce);
|
||||
}
|
||||
|
||||
CChainParams chainparams(Params());
|
||||
|
@ -143,7 +146,8 @@ static UniValue generateBlocks(ChainstateManager& chainman, const CTxMemPool& me
|
|||
|
||||
{ // Don't keep cs_main locked
|
||||
LOCK(cs_main);
|
||||
nHeight = ::ChainActive().Height();
|
||||
CHECK_NONFATAL(std::addressof(::ChainActive()) == std::addressof(chainman.ActiveChain()));
|
||||
nHeight = chainman.ActiveChain().Height();
|
||||
nHeightEnd = nHeight+nGenerate;
|
||||
}
|
||||
unsigned int nExtraNonce = 0;
|
||||
|
@ -231,8 +235,9 @@ static RPCHelpMan generatetodescriptor()
|
|||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error);
|
||||
}
|
||||
|
||||
const CTxMemPool& mempool = EnsureMemPool(request.context);
|
||||
ChainstateManager& chainman = EnsureChainman(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
const CTxMemPool& mempool = EnsureMemPool(node);
|
||||
ChainstateManager& chainman = EnsureChainman(node);
|
||||
|
||||
return generateBlocks(chainman, mempool, coinbase_script, num_blocks, max_tries);
|
||||
},
|
||||
|
@ -276,8 +281,9 @@ static RPCHelpMan generatetoaddress()
|
|||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address");
|
||||
}
|
||||
|
||||
const CTxMemPool& mempool = EnsureMemPool(request.context);
|
||||
ChainstateManager& chainman = EnsureChainman(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
const CTxMemPool& mempool = EnsureMemPool(node);
|
||||
ChainstateManager& chainman = EnsureChainman(node);
|
||||
|
||||
CScript coinbase_script = GetScriptForDestination(destination);
|
||||
|
||||
|
@ -325,7 +331,8 @@ static RPCHelpMan generateblock()
|
|||
coinbase_script = GetScriptForDestination(destination);
|
||||
}
|
||||
|
||||
const CTxMemPool& mempool = EnsureMemPool(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
const CTxMemPool& mempool = EnsureMemPool(node);
|
||||
|
||||
std::vector<CTransactionRef> txs;
|
||||
const auto raw_txs_or_txids = request.params[1].get_array();
|
||||
|
@ -354,11 +361,12 @@ static RPCHelpMan generateblock()
|
|||
CChainParams chainparams(Params());
|
||||
CBlock block;
|
||||
|
||||
ChainstateManager& chainman = EnsureChainman(node);
|
||||
{
|
||||
LOCK(cs_main);
|
||||
|
||||
CTxMemPool empty_mempool;
|
||||
std::unique_ptr<CBlockTemplate> blocktemplate(BlockAssembler(::ChainstateActive(), empty_mempool, chainparams).CreateNewBlock(coinbase_script));
|
||||
std::unique_ptr<CBlockTemplate> blocktemplate(BlockAssembler(chainman.ActiveChainstate(), empty_mempool, chainparams).CreateNewBlock(coinbase_script));
|
||||
if (!blocktemplate) {
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
|
||||
}
|
||||
|
@ -369,13 +377,14 @@ static RPCHelpMan generateblock()
|
|||
|
||||
// Add transactions
|
||||
block.vtx.insert(block.vtx.end(), txs.begin(), txs.end());
|
||||
RegenerateCommitments(block, WITH_LOCK(::cs_main, return std::ref(g_chainman.m_blockman)));
|
||||
CBlockIndex* prev_block = WITH_LOCK(::cs_main, return chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock));
|
||||
RegenerateCommitments(block, prev_block);
|
||||
|
||||
{
|
||||
LOCK(cs_main);
|
||||
|
||||
BlockValidationState state;
|
||||
if (!TestBlockValidity(state, chainparams, ::ChainstateActive(), block, g_chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock), false, false)) {
|
||||
if (!TestBlockValidity(state, chainparams, chainman.ActiveChainstate(), block, chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock), false, false)) {
|
||||
throw JSONRPCError(RPC_VERIFY_ERROR, strprintf("TestBlockValidity failed: %s", state.ToString()));
|
||||
}
|
||||
}
|
||||
|
@ -384,7 +393,7 @@ static RPCHelpMan generateblock()
|
|||
uint64_t max_tries{DEFAULT_MAX_TRIES};
|
||||
unsigned int extra_nonce{0};
|
||||
|
||||
if (!GenerateBlock(EnsureChainman(request.context), block, max_tries, extra_nonce, block_hash) || block_hash.IsNull()) {
|
||||
if (!GenerateBlock(chainman, block, max_tries, extra_nonce, block_hash) || block_hash.IsNull()) {
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "Failed to make block.");
|
||||
}
|
||||
|
||||
|
@ -418,14 +427,17 @@ static RPCHelpMan getmininginfo()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
const CTxMemPool& mempool = EnsureMemPool(node);
|
||||
ChainstateManager& chainman = EnsureChainman(node);
|
||||
LOCK(cs_main);
|
||||
const CTxMemPool& mempool = EnsureMemPool(request.context);
|
||||
const CChain& active_chain = chainman.ActiveChain();
|
||||
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.pushKV("blocks", (int)::ChainActive().Height());
|
||||
obj.pushKV("blocks", active_chain.Height());
|
||||
if (BlockAssembler::m_last_block_weight) obj.pushKV("currentblockweight", *BlockAssembler::m_last_block_weight);
|
||||
if (BlockAssembler::m_last_block_num_txs) obj.pushKV("currentblocktx", *BlockAssembler::m_last_block_num_txs);
|
||||
obj.pushKV("difficulty", (double)GetDifficulty(::ChainActive().Tip()));
|
||||
obj.pushKV("difficulty", (double)GetDifficulty(active_chain.Tip()));
|
||||
obj.pushKV("networkhashps", getnetworkhashps().HandleRequest(request));
|
||||
obj.pushKV("pooledtx", (uint64_t)mempool.size());
|
||||
obj.pushKV("chain", Params().NetworkIDString());
|
||||
|
@ -467,7 +479,7 @@ static RPCHelpMan prioritisetransaction()
|
|||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Priority is no longer supported, dummy argument to prioritisetransaction must be 0.");
|
||||
}
|
||||
|
||||
EnsureMemPool(request.context).PrioritiseTransaction(hash, nAmount);
|
||||
EnsureAnyMemPool(request.context).PrioritiseTransaction(hash, nAmount);
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
@ -588,12 +600,16 @@ static RPCHelpMan getblocktemplate()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
ChainstateManager& chainman = EnsureChainman(node);
|
||||
LOCK(cs_main);
|
||||
|
||||
std::string strMode = "template";
|
||||
UniValue lpval = NullUniValue;
|
||||
std::set<std::string> setClientRules;
|
||||
int64_t nMaxVersionPreVB = -1;
|
||||
CChainState& active_chainstate = chainman.ActiveChainstate();
|
||||
CChain& active_chain = active_chainstate.m_chain;
|
||||
if (!request.params[0].isNull())
|
||||
{
|
||||
const UniValue& oparam = request.params[0].get_obj();
|
||||
|
@ -619,7 +635,7 @@ static RPCHelpMan getblocktemplate()
|
|||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
|
||||
|
||||
uint256 hash = block.GetHash();
|
||||
const CBlockIndex* pindex = g_chainman.m_blockman.LookupBlockIndex(hash);
|
||||
const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(hash);
|
||||
if (pindex) {
|
||||
if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
|
||||
return "duplicate";
|
||||
|
@ -628,12 +644,12 @@ static RPCHelpMan getblocktemplate()
|
|||
return "duplicate-inconclusive";
|
||||
}
|
||||
|
||||
CBlockIndex* const pindexPrev = ::ChainActive().Tip();
|
||||
CBlockIndex* const pindexPrev = active_chain.Tip();
|
||||
// TestBlockValidity only supports blocks built on the current Tip
|
||||
if (block.hashPrevBlock != pindexPrev->GetBlockHash())
|
||||
return "inconclusive-not-best-prevblk";
|
||||
BlockValidationState state;
|
||||
TestBlockValidity(state, Params(), ::ChainstateActive(), block, pindexPrev, false, true);
|
||||
TestBlockValidity(state, Params(), active_chainstate, block, pindexPrev, false, true);
|
||||
return BIP22ValidationResult(state);
|
||||
}
|
||||
|
||||
|
@ -655,7 +671,6 @@ static RPCHelpMan getblocktemplate()
|
|||
if (strMode != "template")
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
|
||||
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
if(!node.connman)
|
||||
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
|
||||
|
||||
|
@ -664,13 +679,13 @@ static RPCHelpMan getblocktemplate()
|
|||
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, PACKAGE_NAME " is not connected!");
|
||||
}
|
||||
|
||||
if (::ChainstateActive().IsInitialBlockDownload()) {
|
||||
if (active_chainstate.IsInitialBlockDownload()) {
|
||||
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, PACKAGE_NAME " is in initial sync and waiting for blocks...");
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int nTransactionsUpdatedLast;
|
||||
const CTxMemPool& mempool = EnsureMemPool(request.context);
|
||||
const CTxMemPool& mempool = EnsureMemPool(node);
|
||||
|
||||
if (!lpval.isNull())
|
||||
{
|
||||
|
@ -690,7 +705,7 @@ static RPCHelpMan getblocktemplate()
|
|||
else
|
||||
{
|
||||
// NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
|
||||
hashWatchedChain = ::ChainActive().Tip()->GetBlockHash();
|
||||
hashWatchedChain = active_chain.Tip()->GetBlockHash();
|
||||
nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
|
||||
}
|
||||
|
||||
|
@ -735,7 +750,7 @@ static RPCHelpMan getblocktemplate()
|
|||
static CBlockIndex* pindexPrev;
|
||||
static int64_t nStart;
|
||||
static std::unique_ptr<CBlockTemplate> pblocktemplate;
|
||||
if (pindexPrev != ::ChainActive().Tip() ||
|
||||
if (pindexPrev != active_chain.Tip() ||
|
||||
(mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5))
|
||||
{
|
||||
// Clear pindexPrev so future calls make a new block, despite any failures from here on
|
||||
|
@ -743,12 +758,12 @@ static RPCHelpMan getblocktemplate()
|
|||
|
||||
// Store the pindexBest used before CreateNewBlock, to avoid races
|
||||
nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
|
||||
CBlockIndex* pindexPrevNew = ::ChainActive().Tip();
|
||||
CBlockIndex* pindexPrevNew = active_chain.Tip();
|
||||
nStart = GetTime();
|
||||
|
||||
// Create new block
|
||||
CScript scriptDummy = CScript() << OP_TRUE;
|
||||
pblocktemplate = BlockAssembler(::ChainstateActive(), mempool, Params()).CreateNewBlock(scriptDummy);
|
||||
pblocktemplate = BlockAssembler(active_chainstate, mempool, Params()).CreateNewBlock(scriptDummy);
|
||||
if (!pblocktemplate)
|
||||
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
|
||||
|
||||
|
@ -884,7 +899,7 @@ static RPCHelpMan getblocktemplate()
|
|||
result.pushKV("transactions", transactions);
|
||||
result.pushKV("coinbaseaux", aux);
|
||||
result.pushKV("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue);
|
||||
result.pushKV("longpollid", ::ChainActive().Tip()->GetBlockHash().GetHex() + ToString(nTransactionsUpdatedLast));
|
||||
result.pushKV("longpollid", active_chain.Tip()->GetBlockHash().GetHex() + ToString(nTransactionsUpdatedLast));
|
||||
result.pushKV("target", hashTarget.GetHex());
|
||||
result.pushKV("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1);
|
||||
result.pushKV("mutable", aMutable);
|
||||
|
@ -967,10 +982,11 @@ static RPCHelpMan submitblock()
|
|||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block does not start with a coinbase");
|
||||
}
|
||||
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
uint256 hash = block.GetHash();
|
||||
{
|
||||
LOCK(cs_main);
|
||||
const CBlockIndex* pindex = g_chainman.m_blockman.LookupBlockIndex(hash);
|
||||
const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(hash);
|
||||
if (pindex) {
|
||||
if (pindex->IsValid(BLOCK_VALID_SCRIPTS)) {
|
||||
return "duplicate";
|
||||
|
@ -983,7 +999,7 @@ static RPCHelpMan submitblock()
|
|||
|
||||
{
|
||||
LOCK(cs_main);
|
||||
const CBlockIndex* pindex = g_chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock);
|
||||
const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock);
|
||||
if (pindex) {
|
||||
UpdateUncommittedBlockStructures(block, pindex, Params().GetConsensus());
|
||||
}
|
||||
|
@ -992,7 +1008,7 @@ static RPCHelpMan submitblock()
|
|||
bool new_block;
|
||||
auto sc = std::make_shared<submitblock_StateCatcher>(block.GetHash());
|
||||
RegisterSharedValidationInterface(sc);
|
||||
bool accepted = EnsureChainman(request.context).ProcessNewBlock(Params(), blockptr, /* fForceProcessing */ true, /* fNewBlock */ &new_block);
|
||||
bool accepted = chainman.ProcessNewBlock(Params(), blockptr, /* fForceProcessing */ true, /* fNewBlock */ &new_block);
|
||||
UnregisterSharedValidationInterface(sc);
|
||||
if (!new_block && accepted) {
|
||||
return "duplicate";
|
||||
|
@ -1025,15 +1041,16 @@ static RPCHelpMan submitheader()
|
|||
if (!DecodeHexBlockHeader(h, request.params[0].get_str())) {
|
||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block header decode failed");
|
||||
}
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
{
|
||||
LOCK(cs_main);
|
||||
if (!g_chainman.m_blockman.LookupBlockIndex(h.hashPrevBlock)) {
|
||||
if (!chainman.m_blockman.LookupBlockIndex(h.hashPrevBlock)) {
|
||||
throw JSONRPCError(RPC_VERIFY_ERROR, "Must submit previous header (" + h.hashPrevBlock.GetHex() + ") first");
|
||||
}
|
||||
}
|
||||
|
||||
BlockValidationState state;
|
||||
EnsureChainman(request.context).ProcessNewBlockHeaders({h}, state, Params());
|
||||
chainman.ProcessNewBlockHeaders({h}, state, Params());
|
||||
if (state.IsValid()) return NullUniValue;
|
||||
if (state.IsError()) {
|
||||
throw JSONRPCError(RPC_VERIFY_ERROR, state.ToString());
|
||||
|
@ -1082,7 +1099,7 @@ static RPCHelpMan estimatesmartfee()
|
|||
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VSTR});
|
||||
RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
|
||||
|
||||
CBlockPolicyEstimator& fee_estimator = EnsureFeeEstimator(request.context);
|
||||
CBlockPolicyEstimator& fee_estimator = EnsureAnyFeeEstimator(request.context);
|
||||
|
||||
unsigned int max_target = fee_estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
|
||||
unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target);
|
||||
|
@ -1170,7 +1187,7 @@ static RPCHelpMan estimaterawfee()
|
|||
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM}, true);
|
||||
RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
|
||||
|
||||
CBlockPolicyEstimator& fee_estimator = EnsureFeeEstimator(request.context);
|
||||
CBlockPolicyEstimator& fee_estimator = EnsureAnyFeeEstimator(request.context);
|
||||
|
||||
unsigned int max_target = fee_estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
|
||||
unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target);
|
||||
|
|
|
@ -53,7 +53,7 @@ static RPCHelpMan getconnectioncount()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
if(!node.connman)
|
||||
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
|
||||
|
||||
|
@ -76,7 +76,7 @@ static RPCHelpMan ping()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
if (!node.peerman) {
|
||||
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ static RPCHelpMan getpeerinfo()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
if(!node.connman || !node.peerman) {
|
||||
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
|
||||
}
|
||||
|
@ -285,7 +285,7 @@ static RPCHelpMan addnode()
|
|||
self.ToString());
|
||||
}
|
||||
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
if(!node.connman)
|
||||
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
|
||||
|
||||
|
@ -350,7 +350,7 @@ static RPCHelpMan addconnection()
|
|||
throw JSONRPCError(RPC_INVALID_PARAMETER, self.ToString());
|
||||
}
|
||||
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
if (!node.connman) {
|
||||
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled.");
|
||||
}
|
||||
|
@ -388,7 +388,7 @@ static RPCHelpMan disconnectnode()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
if(!node.connman)
|
||||
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
|
||||
|
||||
|
@ -448,7 +448,7 @@ static RPCHelpMan getaddednodeinfo()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
if(!node.connman)
|
||||
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
|
||||
|
||||
|
@ -519,7 +519,7 @@ static RPCHelpMan getnettotals()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
if(!node.connman)
|
||||
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
|
||||
|
||||
|
@ -618,7 +618,7 @@ static RPCHelpMan getnetworkinfo()
|
|||
obj.pushKV("version", CLIENT_VERSION);
|
||||
obj.pushKV("subversion", strSubVersion);
|
||||
obj.pushKV("protocolversion",PROTOCOL_VERSION);
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
if (node.connman) {
|
||||
ServiceFlags services = node.connman->GetLocalServices();
|
||||
obj.pushKV("localservices", strprintf("%016x", services));
|
||||
|
@ -680,7 +680,7 @@ static RPCHelpMan setban()
|
|||
if (strCommand != "add" && strCommand != "remove") {
|
||||
throw std::runtime_error(help.ToString());
|
||||
}
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
if (!node.banman) {
|
||||
throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
|
||||
}
|
||||
|
@ -762,7 +762,7 @@ static RPCHelpMan listbanned()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
if(!node.banman) {
|
||||
throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
|
||||
}
|
||||
|
@ -802,7 +802,7 @@ static RPCHelpMan clearbanned()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
if (!node.banman) {
|
||||
throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
|
||||
}
|
||||
|
@ -825,7 +825,7 @@ static RPCHelpMan setnetworkactive()
|
|||
RPCExamples{""},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
if (!node.connman) {
|
||||
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
|
||||
}
|
||||
|
@ -863,7 +863,7 @@ static RPCHelpMan getnodeaddresses()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
if (!node.connman) {
|
||||
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
|
||||
}
|
||||
|
@ -909,7 +909,7 @@ static RPCHelpMan addpeeraddress()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
if (!node.addrman) {
|
||||
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Address manager functionality missing or disabled");
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
#include <univalue.h>
|
||||
|
||||
static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
|
||||
static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry, CChainState& active_chainstate)
|
||||
{
|
||||
// Call into TxToUniv() in bitcoin-common to decode the transaction hex.
|
||||
//
|
||||
|
@ -54,10 +54,10 @@ static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue&
|
|||
LOCK(cs_main);
|
||||
|
||||
entry.pushKV("blockhash", hashBlock.GetHex());
|
||||
CBlockIndex* pindex = g_chainman.m_blockman.LookupBlockIndex(hashBlock);
|
||||
CBlockIndex* pindex = active_chainstate.m_blockman.LookupBlockIndex(hashBlock);
|
||||
if (pindex) {
|
||||
if (::ChainActive().Contains(pindex)) {
|
||||
entry.pushKV("confirmations", 1 + ::ChainActive().Height() - pindex->nHeight);
|
||||
if (active_chainstate.m_chain.Contains(pindex)) {
|
||||
entry.pushKV("confirmations", 1 + active_chainstate.m_chain.Height() - pindex->nHeight);
|
||||
entry.pushKV("time", pindex->GetBlockTime());
|
||||
entry.pushKV("blocktime", pindex->GetBlockTime());
|
||||
}
|
||||
|
@ -158,7 +158,8 @@ static RPCHelpMan getrawtransaction()
|
|||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
const NodeContext& node = EnsureNodeContext(request.context);
|
||||
const NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
ChainstateManager& chainman = EnsureChainman(node);
|
||||
|
||||
bool in_active_chain = true;
|
||||
uint256 hash = ParseHashV(request.params[0], "parameter 1");
|
||||
|
@ -179,11 +180,11 @@ static RPCHelpMan getrawtransaction()
|
|||
LOCK(cs_main);
|
||||
|
||||
uint256 blockhash = ParseHashV(request.params[2], "parameter 3");
|
||||
blockindex = g_chainman.m_blockman.LookupBlockIndex(blockhash);
|
||||
blockindex = chainman.m_blockman.LookupBlockIndex(blockhash);
|
||||
if (!blockindex) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block hash not found");
|
||||
}
|
||||
in_active_chain = ::ChainActive().Contains(blockindex);
|
||||
in_active_chain = chainman.ActiveChain().Contains(blockindex);
|
||||
}
|
||||
|
||||
bool f_txindex_ready = false;
|
||||
|
@ -216,7 +217,7 @@ static RPCHelpMan getrawtransaction()
|
|||
|
||||
UniValue result(UniValue::VOBJ);
|
||||
if (blockindex) result.pushKV("in_active_chain", in_active_chain);
|
||||
TxToJSON(*tx, hash_block, result);
|
||||
TxToJSON(*tx, hash_block, result, chainman.ActiveChainstate());
|
||||
return result;
|
||||
},
|
||||
};
|
||||
|
@ -258,21 +259,23 @@ static RPCHelpMan gettxoutproof()
|
|||
|
||||
CBlockIndex* pblockindex = nullptr;
|
||||
uint256 hashBlock;
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
if (!request.params[1].isNull()) {
|
||||
LOCK(cs_main);
|
||||
hashBlock = ParseHashV(request.params[1], "blockhash");
|
||||
pblockindex = g_chainman.m_blockman.LookupBlockIndex(hashBlock);
|
||||
pblockindex = chainman.m_blockman.LookupBlockIndex(hashBlock);
|
||||
if (!pblockindex) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
||||
}
|
||||
} else {
|
||||
LOCK(cs_main);
|
||||
CChainState& active_chainstate = chainman.ActiveChainstate();
|
||||
|
||||
// Loop through txids and try to find which block they're in. Exit loop once a block is found.
|
||||
for (const auto& tx : setTxids) {
|
||||
const Coin& coin = AccessByTxid(::ChainstateActive().CoinsTip(), tx);
|
||||
const Coin& coin = AccessByTxid(active_chainstate.CoinsTip(), tx);
|
||||
if (!coin.IsSpent()) {
|
||||
pblockindex = ::ChainActive()[coin.nHeight];
|
||||
pblockindex = active_chainstate.m_chain[coin.nHeight];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -291,7 +294,7 @@ static RPCHelpMan gettxoutproof()
|
|||
if (!tx || hashBlock.IsNull()) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not yet in block");
|
||||
}
|
||||
pblockindex = g_chainman.m_blockman.LookupBlockIndex(hashBlock);
|
||||
pblockindex = chainman.m_blockman.LookupBlockIndex(hashBlock);
|
||||
if (!pblockindex) {
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction index corrupt");
|
||||
}
|
||||
|
@ -349,10 +352,11 @@ static RPCHelpMan verifytxoutproof()
|
|||
if (merkleBlock.txn.ExtractMatches(vMatch, vIndex) != merkleBlock.header.hashMerkleRoot)
|
||||
return res;
|
||||
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
LOCK(cs_main);
|
||||
|
||||
const CBlockIndex* pindex = g_chainman.m_blockman.LookupBlockIndex(merkleBlock.header.GetHash());
|
||||
if (!pindex || !::ChainActive().Contains(pindex) || pindex->nTx == 0) {
|
||||
const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(merkleBlock.header.GetHash());
|
||||
if (!pindex || !chainman.ActiveChain().Contains(pindex) || pindex->nTx == 0) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain");
|
||||
}
|
||||
|
||||
|
@ -676,10 +680,11 @@ static RPCHelpMan combinerawtransaction()
|
|||
CCoinsView viewDummy;
|
||||
CCoinsViewCache view(&viewDummy);
|
||||
{
|
||||
const CTxMemPool& mempool = EnsureMemPool(request.context);
|
||||
LOCK(cs_main);
|
||||
LOCK(mempool.cs);
|
||||
CCoinsViewCache &viewChain = ::ChainstateActive().CoinsTip();
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
const CTxMemPool& mempool = EnsureMemPool(node);
|
||||
ChainstateManager& chainman = EnsureChainman(node);
|
||||
LOCK2(cs_main, mempool.cs);
|
||||
CCoinsViewCache &viewChain = chainman.ActiveChainstate().CoinsTip();
|
||||
CCoinsViewMemPool viewMempool(&viewChain, mempool);
|
||||
view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view
|
||||
|
||||
|
@ -803,7 +808,7 @@ static RPCHelpMan signrawtransactionwithkey()
|
|||
for (const CTxIn& txin : mtx.vin) {
|
||||
coins[txin.prevout]; // Create empty map entry keyed by prevout.
|
||||
}
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
FindCoins(node, coins);
|
||||
|
||||
// Parse the prevtxs array
|
||||
|
@ -866,7 +871,7 @@ static RPCHelpMan sendrawtransaction()
|
|||
|
||||
std::string err_string;
|
||||
AssertLockNotHeld(cs_main);
|
||||
NodeContext& node = EnsureNodeContext(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
const TransactionError err = BroadcastTransaction(node, tx, err_string, max_raw_tx_fee, /*relay*/ true, /*wait_callback*/ true);
|
||||
if (TransactionError::OK != err) {
|
||||
throw JSONRPCTransactionError(err, err_string);
|
||||
|
@ -941,7 +946,9 @@ static RPCHelpMan testmempoolaccept()
|
|||
DEFAULT_MAX_RAW_TX_FEE_RATE :
|
||||
CFeeRate(AmountFromValue(request.params[1]));
|
||||
|
||||
CTxMemPool& mempool = EnsureMemPool(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
|
||||
CTxMemPool& mempool = EnsureMemPool(node);
|
||||
int64_t virtual_size = GetVirtualTransactionSize(*tx);
|
||||
CAmount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size);
|
||||
|
||||
|
@ -950,7 +957,8 @@ static RPCHelpMan testmempoolaccept()
|
|||
result_0.pushKV("txid", tx->GetHash().GetHex());
|
||||
result_0.pushKV("wtxid", tx->GetWitnessHash().GetHex());
|
||||
|
||||
const MempoolAcceptResult accept_result = WITH_LOCK(cs_main, return AcceptToMemoryPool(::ChainstateActive(), mempool, std::move(tx),
|
||||
ChainstateManager& chainman = EnsureChainman(node);
|
||||
const MempoolAcceptResult accept_result = WITH_LOCK(cs_main, return AcceptToMemoryPool(chainman.ActiveChainstate(), mempool, std::move(tx),
|
||||
false /* bypass_limits */, /* test_accept */ true));
|
||||
|
||||
// Only return the fee and vsize if the transaction would pass ATMP.
|
||||
|
@ -1599,9 +1607,11 @@ static RPCHelpMan utxoupdatepsbt()
|
|||
CCoinsView viewDummy;
|
||||
CCoinsViewCache view(&viewDummy);
|
||||
{
|
||||
const CTxMemPool& mempool = EnsureMemPool(request.context);
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
const CTxMemPool& mempool = EnsureMemPool(node);
|
||||
ChainstateManager& chainman = EnsureChainman(node);
|
||||
LOCK2(cs_main, mempool.cs);
|
||||
CCoinsViewCache &viewChain = ::ChainstateActive().CoinsTip();
|
||||
CCoinsViewCache &viewChain = chainman.ActiveChainstate().CoinsTip();
|
||||
CCoinsViewMemPool viewMempool(&viewChain, mempool);
|
||||
view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view
|
||||
|
||||
|
|
|
@ -242,7 +242,8 @@ CBlock TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransa
|
|||
for (const CMutableTransaction& tx : txns) {
|
||||
block.vtx.push_back(MakeTransactionRef(tx));
|
||||
}
|
||||
RegenerateCommitments(block, WITH_LOCK(::cs_main, return std::ref(g_chainman.m_blockman)));
|
||||
CBlockIndex* prev_block = WITH_LOCK(::cs_main, return g_chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock));
|
||||
RegenerateCommitments(block, prev_block);
|
||||
|
||||
while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue