mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-19 13:27:35 +02:00
Merge 0dd7b23489 into merged_master (Bitcoin PR #21391)
This commit is contained in:
commit
13aa8af68b
9 changed files with 275 additions and 187 deletions
|
|
@ -51,11 +51,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;
|
||||
|
|
@ -68,7 +69,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++) {
|
||||
|
|
@ -106,8 +107,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());
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
@ -118,7 +120,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());
|
||||
|
|
@ -163,7 +166,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;
|
||||
|
|
@ -251,8 +255,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);
|
||||
},
|
||||
|
|
@ -296,8 +301,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);
|
||||
|
||||
|
|
@ -345,7 +351,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();
|
||||
|
|
@ -374,11 +381,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");
|
||||
}
|
||||
|
|
@ -389,13 +397,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()));
|
||||
}
|
||||
}
|
||||
|
|
@ -404,7 +413,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.");
|
||||
}
|
||||
|
||||
|
|
@ -438,15 +447,18 @@ 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);
|
||||
if (!g_signed_blocks) {
|
||||
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());
|
||||
|
|
@ -489,7 +501,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;
|
||||
},
|
||||
};
|
||||
|
|
@ -610,12 +622,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();
|
||||
|
|
@ -641,7 +657,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";
|
||||
|
|
@ -650,12 +666,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);
|
||||
}
|
||||
|
||||
|
|
@ -677,7 +693,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");
|
||||
|
||||
|
|
@ -686,13 +701,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())
|
||||
{
|
||||
|
|
@ -712,7 +727,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;
|
||||
}
|
||||
|
||||
|
|
@ -757,7 +772,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
|
||||
|
|
@ -765,12 +780,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");
|
||||
|
||||
|
|
@ -906,7 +921,7 @@ static RPCHelpMan getblocktemplate()
|
|||
result.pushKV("transactions", transactions);
|
||||
result.pushKV("coinbaseaux", aux);
|
||||
result.pushKV("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue.GetAmount());
|
||||
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);
|
||||
|
|
@ -989,10 +1004,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";
|
||||
|
|
@ -1005,7 +1021,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());
|
||||
}
|
||||
|
|
@ -1014,7 +1030,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";
|
||||
|
|
@ -1047,15 +1063,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());
|
||||
|
|
@ -1104,7 +1121,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);
|
||||
|
|
@ -1192,7 +1209,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);
|
||||
|
|
@ -1340,7 +1357,7 @@ static RPCHelpMan getnewblockhex()
|
|||
|
||||
CScript feeDestinationScript = Params().GetConsensus().mandatory_coinbase_destination;
|
||||
if (feeDestinationScript == CScript()) feeDestinationScript = CScript() << OP_TRUE;
|
||||
const NodeContext& node = EnsureNodeContext(request.context);
|
||||
const NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(::ChainstateActive(), *node.mempool, Params()).CreateNewBlock(feeDestinationScript, std::chrono::seconds(required_wait), &proposed, data_commitment.empty() ? nullptr : &data_commitment));
|
||||
if (!pblocktemplate.get()) {
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet keypool empty");
|
||||
|
|
@ -1516,7 +1533,7 @@ static RPCHelpMan consumecompactsketch()
|
|||
CBlockHeaderAndShortTxIDs cmpctblock;
|
||||
ssBlock >> cmpctblock;
|
||||
|
||||
const NodeContext& node = EnsureNodeContext(request.context);
|
||||
const NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
LOCK(node.mempool->cs);
|
||||
PartiallyDownloadedBlock partialBlock(node.mempool.get());
|
||||
const std::vector<std::pair<uint256, CTransactionRef>> dummy;
|
||||
|
|
@ -1695,7 +1712,7 @@ static RPCHelpMan testproposedblock()
|
|||
if (!DecodeHexBlk(block, request.params[0].get_str()))
|
||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
|
||||
|
||||
ChainstateManager& chainman = EnsureChainman(request.context);
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
LOCK(cs_main);
|
||||
|
||||
uint256 hash = block.GetHash();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue