mirror of
https://github.com/bitcoin/bitcoin.git
synced 2024-11-20 10:38:42 +01:00
Merge #21270: [Bundle 4/n] Prune g_chainman usage in validation-adjacent modules
a67983cd6d
net_processing: Add review-only assertion to PeerManager (Carl Dong)272d993e75
scripted-diff: net_processing: Use existing chainman (Carl Dong)021a04a469
net_processing: Move some static functions to PeerManager (Carl Dong)91c5b68acd
node/ifaces: ChainImpl: Use existing NodeContext member (Carl Dong)8a1d580b21
node/ifaces: NodeImpl: Use existing NodeContext member (Carl Dong)4cde4a701b
node: Use existing NodeContext (Carl Dong)106bcd4f39
node/coinstats: Pass in BlockManager to GetUTXOStats (Carl Dong)2c3ba00693
miner: Pass in blockman to ::RegenerateCommitments (Carl Dong)2afcf24408
miner: Remove old CreateNewBlock w/o chainstate param (Carl Dong)46b7f29340
scripted-diff: Invoke CreateNewBlock with chainstate (Carl Dong)d0de61b764
miner: Pass in chainstate to BlockAssembler::CreateNewBlock (Carl Dong)a04aac493f
validation: Remove extraneous LoadGenesisBlock function prototype (Carl Dong) Pull request description: Overall PR: #20158 (tree-wide: De-globalize ChainstateManager) Based on: - [x] #21055 | [Bundle 3/n] Prune g_chainman usage in mempool-related validation functions 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: laanwj: Code review ACKa67983cd6d
ryanofsky: Code review ACKa67983cd6d
. Only change since last review new first commit fixing header declaration, and rebase glozow: code review ACKa67983cd6d
Tree-SHA512: dce182a18b88be80cbf50978d4ba8fa6ab0f01e861d09bae0ae9364051bb78f9334859d164b185b07f1d70a583e739557fab6d820cac8c37b3855b85c2a6771b
This commit is contained in:
commit
767bb7d5c5
@ -39,13 +39,13 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam
|
|||||||
return nNewTime - nOldTime;
|
return nNewTime - nOldTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegenerateCommitments(CBlock& block)
|
void RegenerateCommitments(CBlock& block, BlockManager& blockman)
|
||||||
{
|
{
|
||||||
CMutableTransaction tx{*block.vtx.at(0)};
|
CMutableTransaction tx{*block.vtx.at(0)};
|
||||||
tx.vout.erase(tx.vout.begin() + GetWitnessCommitmentIndex(block));
|
tx.vout.erase(tx.vout.begin() + GetWitnessCommitmentIndex(block));
|
||||||
block.vtx.at(0) = MakeTransactionRef(tx);
|
block.vtx.at(0) = MakeTransactionRef(tx);
|
||||||
|
|
||||||
GenerateCoinbaseCommitment(block, WITH_LOCK(cs_main, return g_chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock)), Params().GetConsensus());
|
GenerateCoinbaseCommitment(block, WITH_LOCK(::cs_main, assert(std::addressof(g_chainman.m_blockman) == std::addressof(blockman)); return blockman.LookupBlockIndex(block.hashPrevBlock)), Params().GetConsensus());
|
||||||
|
|
||||||
block.hashMerkleRoot = BlockMerkleRoot(block);
|
block.hashMerkleRoot = BlockMerkleRoot(block);
|
||||||
}
|
}
|
||||||
@ -99,7 +99,7 @@ void BlockAssembler::resetBlock()
|
|||||||
Optional<int64_t> BlockAssembler::m_last_block_num_txs{nullopt};
|
Optional<int64_t> BlockAssembler::m_last_block_num_txs{nullopt};
|
||||||
Optional<int64_t> BlockAssembler::m_last_block_weight{nullopt};
|
Optional<int64_t> BlockAssembler::m_last_block_weight{nullopt};
|
||||||
|
|
||||||
std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn)
|
std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(CChainState& chainstate, const CScript& scriptPubKeyIn)
|
||||||
{
|
{
|
||||||
int64_t nTimeStart = GetTimeMicros();
|
int64_t nTimeStart = GetTimeMicros();
|
||||||
|
|
||||||
@ -117,7 +117,8 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
|
|||||||
pblocktemplate->vTxSigOpsCost.push_back(-1); // updated at end
|
pblocktemplate->vTxSigOpsCost.push_back(-1); // updated at end
|
||||||
|
|
||||||
LOCK2(cs_main, m_mempool.cs);
|
LOCK2(cs_main, m_mempool.cs);
|
||||||
CBlockIndex* pindexPrev = ::ChainActive().Tip();
|
assert(std::addressof(*::ChainActive().Tip()) == std::addressof(*chainstate.m_chain.Tip()));
|
||||||
|
CBlockIndex* pindexPrev = chainstate.m_chain.Tip();
|
||||||
assert(pindexPrev != nullptr);
|
assert(pindexPrev != nullptr);
|
||||||
nHeight = pindexPrev->nHeight + 1;
|
nHeight = pindexPrev->nHeight + 1;
|
||||||
|
|
||||||
@ -176,7 +177,8 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
|
|||||||
pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]);
|
pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]);
|
||||||
|
|
||||||
BlockValidationState state;
|
BlockValidationState state;
|
||||||
if (!TestBlockValidity(state, chainparams, ::ChainstateActive(), *pblock, pindexPrev, false, false)) {
|
assert(std::addressof(::ChainstateActive()) == std::addressof(chainstate));
|
||||||
|
if (!TestBlockValidity(state, chainparams, chainstate, *pblock, pindexPrev, false, false)) {
|
||||||
throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, state.ToString()));
|
throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, state.ToString()));
|
||||||
}
|
}
|
||||||
int64_t nTime2 = GetTimeMicros();
|
int64_t nTime2 = GetTimeMicros();
|
||||||
|
@ -158,7 +158,7 @@ public:
|
|||||||
explicit BlockAssembler(const CTxMemPool& mempool, const CChainParams& params, const Options& options);
|
explicit BlockAssembler(const CTxMemPool& mempool, const CChainParams& params, const Options& options);
|
||||||
|
|
||||||
/** Construct a new block template with coinbase to scriptPubKeyIn */
|
/** Construct a new block template with coinbase to scriptPubKeyIn */
|
||||||
std::unique_ptr<CBlockTemplate> CreateNewBlock(const CScript& scriptPubKeyIn);
|
std::unique_ptr<CBlockTemplate> CreateNewBlock(CChainState& chainstate, const CScript& scriptPubKeyIn);
|
||||||
|
|
||||||
static Optional<int64_t> m_last_block_num_txs;
|
static Optional<int64_t> m_last_block_num_txs;
|
||||||
static Optional<int64_t> m_last_block_weight;
|
static Optional<int64_t> m_last_block_weight;
|
||||||
@ -202,6 +202,6 @@ void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned
|
|||||||
int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev);
|
int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev);
|
||||||
|
|
||||||
/** Update an old GenerateCoinbaseCommitment from CreateNewBlock after the block txs have changed */
|
/** Update an old GenerateCoinbaseCommitment from CreateNewBlock after the block txs have changed */
|
||||||
void RegenerateCommitments(CBlock& block);
|
void RegenerateCommitments(CBlock& block, BlockManager& blockman);
|
||||||
|
|
||||||
#endif // BITCOIN_MINER_H
|
#endif // BITCOIN_MINER_H
|
||||||
|
@ -472,6 +472,24 @@ private:
|
|||||||
std::vector<std::pair<uint256, CTransactionRef>> vExtraTxnForCompact GUARDED_BY(g_cs_orphans);
|
std::vector<std::pair<uint256, CTransactionRef>> vExtraTxnForCompact GUARDED_BY(g_cs_orphans);
|
||||||
/** Offset into vExtraTxnForCompact to insert the next tx */
|
/** Offset into vExtraTxnForCompact to insert the next tx */
|
||||||
size_t vExtraTxnForCompactIt GUARDED_BY(g_cs_orphans) = 0;
|
size_t vExtraTxnForCompactIt GUARDED_BY(g_cs_orphans) = 0;
|
||||||
|
|
||||||
|
void ProcessBlockAvailability(NodeId nodeid) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||||
|
void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||||
|
bool CanDirectFetch(const Consensus::Params &consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||||
|
bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||||
|
bool AlreadyHaveBlock(const uint256& block_hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||||
|
void ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChainParams& chainparams, const CInv& inv, CConnman& connman);
|
||||||
|
bool PrepareBlockFilterRequest(CNode& peer, const CChainParams& chain_params,
|
||||||
|
BlockFilterType filter_type, uint32_t start_height,
|
||||||
|
const uint256& stop_hash, uint32_t max_height_diff,
|
||||||
|
const CBlockIndex*& stop_index,
|
||||||
|
BlockFilterIndex*& filter_index);
|
||||||
|
void ProcessGetCFilters(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
|
||||||
|
CConnman& connman);
|
||||||
|
void ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
|
||||||
|
CConnman& connman);
|
||||||
|
void ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
|
||||||
|
CConnman& connman);
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@ -665,41 +683,6 @@ bool PeerManagerImpl::MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, co
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Check whether the last unknown block a peer advertised is not yet known. */
|
|
||||||
static void ProcessBlockAvailability(NodeId nodeid) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
|
|
||||||
CNodeState *state = State(nodeid);
|
|
||||||
assert(state != nullptr);
|
|
||||||
|
|
||||||
if (!state->hashLastUnknownBlock.IsNull()) {
|
|
||||||
const CBlockIndex* pindex = g_chainman.m_blockman.LookupBlockIndex(state->hashLastUnknownBlock);
|
|
||||||
if (pindex && pindex->nChainWork > 0) {
|
|
||||||
if (state->pindexBestKnownBlock == nullptr || pindex->nChainWork >= state->pindexBestKnownBlock->nChainWork) {
|
|
||||||
state->pindexBestKnownBlock = pindex;
|
|
||||||
}
|
|
||||||
state->hashLastUnknownBlock.SetNull();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Update tracking information about which blocks a peer is assumed to have. */
|
|
||||||
static void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
|
|
||||||
CNodeState *state = State(nodeid);
|
|
||||||
assert(state != nullptr);
|
|
||||||
|
|
||||||
ProcessBlockAvailability(nodeid);
|
|
||||||
|
|
||||||
const CBlockIndex* pindex = g_chainman.m_blockman.LookupBlockIndex(hash);
|
|
||||||
if (pindex && pindex->nChainWork > 0) {
|
|
||||||
// An actually better block was announced.
|
|
||||||
if (state->pindexBestKnownBlock == nullptr || pindex->nChainWork >= state->pindexBestKnownBlock->nChainWork) {
|
|
||||||
state->pindexBestKnownBlock = pindex;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// An unknown block was announced; just assume that the latest one is the best one.
|
|
||||||
state->hashLastUnknownBlock = hash;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid)
|
void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
@ -749,9 +732,9 @@ bool PeerManagerImpl::TipMayBeStale()
|
|||||||
return m_last_tip_update < GetTime() - consensusParams.nPowTargetSpacing * 3 && mapBlocksInFlight.empty();
|
return m_last_tip_update < GetTime() - consensusParams.nPowTargetSpacing * 3 && mapBlocksInFlight.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool CanDirectFetch(const Consensus::Params &consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
bool PeerManagerImpl::CanDirectFetch(const Consensus::Params &consensusParams)
|
||||||
{
|
{
|
||||||
return ::ChainActive().Tip()->GetBlockTime() > GetAdjustedTime() - consensusParams.nPowTargetSpacing * 20;
|
return m_chainman.ActiveChain().Tip()->GetBlockTime() > GetAdjustedTime() - consensusParams.nPowTargetSpacing * 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
static bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||||
@ -763,6 +746,41 @@ static bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex) EXCLUSIV
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Check whether the last unknown block a peer advertised is not yet known. */
|
||||||
|
void PeerManagerImpl::ProcessBlockAvailability(NodeId nodeid) {
|
||||||
|
CNodeState *state = State(nodeid);
|
||||||
|
assert(state != nullptr);
|
||||||
|
|
||||||
|
if (!state->hashLastUnknownBlock.IsNull()) {
|
||||||
|
const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(state->hashLastUnknownBlock);
|
||||||
|
if (pindex && pindex->nChainWork > 0) {
|
||||||
|
if (state->pindexBestKnownBlock == nullptr || pindex->nChainWork >= state->pindexBestKnownBlock->nChainWork) {
|
||||||
|
state->pindexBestKnownBlock = pindex;
|
||||||
|
}
|
||||||
|
state->hashLastUnknownBlock.SetNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Update tracking information about which blocks a peer is assumed to have. */
|
||||||
|
void PeerManagerImpl::UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) {
|
||||||
|
CNodeState *state = State(nodeid);
|
||||||
|
assert(state != nullptr);
|
||||||
|
|
||||||
|
ProcessBlockAvailability(nodeid);
|
||||||
|
|
||||||
|
const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(hash);
|
||||||
|
if (pindex && pindex->nChainWork > 0) {
|
||||||
|
// An actually better block was announced.
|
||||||
|
if (state->pindexBestKnownBlock == nullptr || pindex->nChainWork >= state->pindexBestKnownBlock->nChainWork) {
|
||||||
|
state->pindexBestKnownBlock = pindex;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// An unknown block was announced; just assume that the latest one is the best one.
|
||||||
|
state->hashLastUnknownBlock = hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PeerManagerImpl::FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<const CBlockIndex*>& vBlocks, NodeId& nodeStaller)
|
void PeerManagerImpl::FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<const CBlockIndex*>& vBlocks, NodeId& nodeStaller)
|
||||||
{
|
{
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
@ -775,7 +793,7 @@ void PeerManagerImpl::FindNextBlocksToDownload(NodeId nodeid, unsigned int count
|
|||||||
// Make sure pindexBestKnownBlock is up to date, we'll need it.
|
// Make sure pindexBestKnownBlock is up to date, we'll need it.
|
||||||
ProcessBlockAvailability(nodeid);
|
ProcessBlockAvailability(nodeid);
|
||||||
|
|
||||||
if (state->pindexBestKnownBlock == nullptr || state->pindexBestKnownBlock->nChainWork < ::ChainActive().Tip()->nChainWork || state->pindexBestKnownBlock->nChainWork < nMinimumChainWork) {
|
if (state->pindexBestKnownBlock == nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.ActiveChain().Tip()->nChainWork || state->pindexBestKnownBlock->nChainWork < nMinimumChainWork) {
|
||||||
// This peer has nothing interesting.
|
// This peer has nothing interesting.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -783,7 +801,7 @@ void PeerManagerImpl::FindNextBlocksToDownload(NodeId nodeid, unsigned int count
|
|||||||
if (state->pindexLastCommonBlock == nullptr) {
|
if (state->pindexLastCommonBlock == nullptr) {
|
||||||
// Bootstrap quickly by guessing a parent of our best tip is the forking point.
|
// Bootstrap quickly by guessing a parent of our best tip is the forking point.
|
||||||
// Guessing wrong in either direction is not a problem.
|
// Guessing wrong in either direction is not a problem.
|
||||||
state->pindexLastCommonBlock = ::ChainActive()[std::min(state->pindexBestKnownBlock->nHeight, ::ChainActive().Height())];
|
state->pindexLastCommonBlock = m_chainman.ActiveChain()[std::min(state->pindexBestKnownBlock->nHeight, m_chainman.ActiveChain().Height())];
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the peer reorganized, our previous pindexLastCommonBlock may not be an ancestor
|
// If the peer reorganized, our previous pindexLastCommonBlock may not be an ancestor
|
||||||
@ -826,7 +844,7 @@ void PeerManagerImpl::FindNextBlocksToDownload(NodeId nodeid, unsigned int count
|
|||||||
// We wouldn't download this block or its descendants from this peer.
|
// We wouldn't download this block or its descendants from this peer.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (pindex->nStatus & BLOCK_HAVE_DATA || ::ChainActive().Contains(pindex)) {
|
if (pindex->nStatus & BLOCK_HAVE_DATA || m_chainman.ActiveChain().Contains(pindex)) {
|
||||||
if (pindex->HaveTxsDownloaded())
|
if (pindex->HaveTxsDownloaded())
|
||||||
state->pindexLastCommonBlock = pindex;
|
state->pindexLastCommonBlock = pindex;
|
||||||
} else if (mapBlocksInFlight.count(pindex->GetBlockHash()) == 0) {
|
} else if (mapBlocksInFlight.count(pindex->GetBlockHash()) == 0) {
|
||||||
@ -1179,10 +1197,10 @@ bool PeerManagerImpl::MaybePunishNodeForTx(NodeId nodeid, const TxValidationStat
|
|||||||
// active chain if they are no more than a month older (both in time, and in
|
// active chain if they are no more than a month older (both in time, and in
|
||||||
// best equivalent proof of work) than the best header chain we know about and
|
// best equivalent proof of work) than the best header chain we know about and
|
||||||
// we fully-validated them at some point.
|
// we fully-validated them at some point.
|
||||||
static bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
bool PeerManagerImpl::BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Params& consensusParams)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
if (::ChainActive().Contains(pindex)) return true;
|
if (m_chainman.ActiveChain().Contains(pindex)) return true;
|
||||||
return pindex->IsValid(BLOCK_VALID_SCRIPTS) && (pindexBestHeader != nullptr) &&
|
return pindex->IsValid(BLOCK_VALID_SCRIPTS) && (pindexBestHeader != nullptr) &&
|
||||||
(pindexBestHeader->GetBlockTime() - pindex->GetBlockTime() < STALE_RELAY_AGE_LIMIT) &&
|
(pindexBestHeader->GetBlockTime() - pindex->GetBlockTime() < STALE_RELAY_AGE_LIMIT) &&
|
||||||
(GetBlockProofEquivalentTime(*pindexBestHeader, *pindex, *pindexBestHeader, consensusParams) < STALE_RELAY_AGE_LIMIT);
|
(GetBlockProofEquivalentTime(*pindexBestHeader, *pindex, *pindexBestHeader, consensusParams) < STALE_RELAY_AGE_LIMIT);
|
||||||
@ -1206,6 +1224,7 @@ PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& conn
|
|||||||
m_stale_tip_check_time(0),
|
m_stale_tip_check_time(0),
|
||||||
m_ignore_incoming_txs(ignore_incoming_txs)
|
m_ignore_incoming_txs(ignore_incoming_txs)
|
||||||
{
|
{
|
||||||
|
assert(std::addressof(g_chainman) == std::addressof(m_chainman));
|
||||||
// Initialize global variables that cannot be constructed at startup.
|
// Initialize global variables that cannot be constructed at startup.
|
||||||
recentRejects.reset(new CRollingBloomFilter(120000, 0.000001));
|
recentRejects.reset(new CRollingBloomFilter(120000, 0.000001));
|
||||||
|
|
||||||
@ -1331,7 +1350,7 @@ void PeerManagerImpl::NewPoWValidBlock(const CBlockIndex *pindex, const std::sha
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Update our best height and announce any block hashes which weren't previously
|
* Update our best height and announce any block hashes which weren't previously
|
||||||
* in ::ChainActive() to our peers.
|
* in m_chainman.ActiveChain() to our peers.
|
||||||
*/
|
*/
|
||||||
void PeerManagerImpl::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
|
void PeerManagerImpl::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
|
||||||
{
|
{
|
||||||
@ -1393,7 +1412,7 @@ void PeerManagerImpl::BlockChecked(const CBlock& block, const BlockValidationSta
|
|||||||
// the tip yet so we have no way to check this directly here. Instead we
|
// the tip yet so we have no way to check this directly here. Instead we
|
||||||
// just check that there are currently no other blocks in flight.
|
// just check that there are currently no other blocks in flight.
|
||||||
else if (state.IsValid() &&
|
else if (state.IsValid() &&
|
||||||
!::ChainstateActive().IsInitialBlockDownload() &&
|
!m_chainman.ActiveChainstate().IsInitialBlockDownload() &&
|
||||||
mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
|
mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
|
||||||
if (it != mapBlockSource.end()) {
|
if (it != mapBlockSource.end()) {
|
||||||
MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
|
MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
|
||||||
@ -1412,12 +1431,12 @@ void PeerManagerImpl::BlockChecked(const CBlock& block, const BlockValidationSta
|
|||||||
bool PeerManagerImpl::AlreadyHaveTx(const GenTxid& gtxid)
|
bool PeerManagerImpl::AlreadyHaveTx(const GenTxid& gtxid)
|
||||||
{
|
{
|
||||||
assert(recentRejects);
|
assert(recentRejects);
|
||||||
if (::ChainActive().Tip()->GetBlockHash() != hashRecentRejectsChainTip) {
|
if (m_chainman.ActiveChain().Tip()->GetBlockHash() != hashRecentRejectsChainTip) {
|
||||||
// If the chain tip has changed previously rejected transactions
|
// If the chain tip has changed previously rejected transactions
|
||||||
// might be now valid, e.g. due to a nLockTime'd tx becoming valid,
|
// might be now valid, e.g. due to a nLockTime'd tx becoming valid,
|
||||||
// or a double-spend. Reset the rejects filter and give those
|
// or a double-spend. Reset the rejects filter and give those
|
||||||
// txs a second chance.
|
// txs a second chance.
|
||||||
hashRecentRejectsChainTip = ::ChainActive().Tip()->GetBlockHash();
|
hashRecentRejectsChainTip = m_chainman.ActiveChain().Tip()->GetBlockHash();
|
||||||
recentRejects->reset();
|
recentRejects->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1433,9 +1452,9 @@ bool PeerManagerImpl::AlreadyHaveTx(const GenTxid& gtxid)
|
|||||||
return recentRejects->contains(hash) || m_mempool.exists(gtxid);
|
return recentRejects->contains(hash) || m_mempool.exists(gtxid);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool static AlreadyHaveBlock(const uint256& block_hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
bool PeerManagerImpl::AlreadyHaveBlock(const uint256& block_hash)
|
||||||
{
|
{
|
||||||
return g_chainman.m_blockman.LookupBlockIndex(block_hash) != nullptr;
|
return m_chainman.m_blockman.LookupBlockIndex(block_hash) != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerManagerImpl::SendPings()
|
void PeerManagerImpl::SendPings()
|
||||||
@ -1514,7 +1533,7 @@ static void RelayAddress(const CNode& originator,
|
|||||||
connman.ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
|
connman.ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
|
||||||
}
|
}
|
||||||
|
|
||||||
void static ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChainParams& chainparams, const CInv& inv, CConnman& connman)
|
void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChainParams& chainparams, const CInv& inv, CConnman& connman)
|
||||||
{
|
{
|
||||||
bool send = false;
|
bool send = false;
|
||||||
std::shared_ptr<const CBlock> a_recent_block;
|
std::shared_ptr<const CBlock> a_recent_block;
|
||||||
@ -1531,7 +1550,7 @@ void static ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChainParams& ch
|
|||||||
bool need_activate_chain = false;
|
bool need_activate_chain = false;
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
const CBlockIndex* pindex = g_chainman.m_blockman.LookupBlockIndex(inv.hash);
|
const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(inv.hash);
|
||||||
if (pindex) {
|
if (pindex) {
|
||||||
if (pindex->HaveTxsDownloaded() && !pindex->IsValid(BLOCK_VALID_SCRIPTS) &&
|
if (pindex->HaveTxsDownloaded() && !pindex->IsValid(BLOCK_VALID_SCRIPTS) &&
|
||||||
pindex->IsValid(BLOCK_VALID_TREE)) {
|
pindex->IsValid(BLOCK_VALID_TREE)) {
|
||||||
@ -1546,13 +1565,13 @@ void static ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChainParams& ch
|
|||||||
} // release cs_main before calling ActivateBestChain
|
} // release cs_main before calling ActivateBestChain
|
||||||
if (need_activate_chain) {
|
if (need_activate_chain) {
|
||||||
BlockValidationState state;
|
BlockValidationState state;
|
||||||
if (!::ChainstateActive().ActivateBestChain(state, chainparams, a_recent_block)) {
|
if (!m_chainman.ActiveChainstate().ActivateBestChain(state, chainparams, a_recent_block)) {
|
||||||
LogPrint(BCLog::NET, "failed to activate chain (%s)\n", state.ToString());
|
LogPrint(BCLog::NET, "failed to activate chain (%s)\n", state.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
const CBlockIndex* pindex = g_chainman.m_blockman.LookupBlockIndex(inv.hash);
|
const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(inv.hash);
|
||||||
if (pindex) {
|
if (pindex) {
|
||||||
send = BlockRequestAllowed(pindex, consensusParams);
|
send = BlockRequestAllowed(pindex, consensusParams);
|
||||||
if (!send) {
|
if (!send) {
|
||||||
@ -1574,7 +1593,7 @@ void static ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChainParams& ch
|
|||||||
}
|
}
|
||||||
// Avoid leaking prune-height by never sending blocks below the NODE_NETWORK_LIMITED threshold
|
// Avoid leaking prune-height by never sending blocks below the NODE_NETWORK_LIMITED threshold
|
||||||
if (send && !pfrom.HasPermission(PF_NOBAN) && (
|
if (send && !pfrom.HasPermission(PF_NOBAN) && (
|
||||||
(((pfrom.GetLocalServices() & NODE_NETWORK_LIMITED) == NODE_NETWORK_LIMITED) && ((pfrom.GetLocalServices() & NODE_NETWORK) != NODE_NETWORK) && (::ChainActive().Tip()->nHeight - pindex->nHeight > (int)NODE_NETWORK_LIMITED_MIN_BLOCKS + 2 /* add two blocks buffer extension for possible races */) )
|
(((pfrom.GetLocalServices() & NODE_NETWORK_LIMITED) == NODE_NETWORK_LIMITED) && ((pfrom.GetLocalServices() & NODE_NETWORK) != NODE_NETWORK) && (m_chainman.ActiveChain().Tip()->nHeight - pindex->nHeight > (int)NODE_NETWORK_LIMITED_MIN_BLOCKS + 2 /* add two blocks buffer extension for possible races */) )
|
||||||
)) {
|
)) {
|
||||||
LogPrint(BCLog::NET, "Ignore block request below NODE_NETWORK_LIMITED threshold from peer=%d\n", pfrom.GetId());
|
LogPrint(BCLog::NET, "Ignore block request below NODE_NETWORK_LIMITED threshold from peer=%d\n", pfrom.GetId());
|
||||||
|
|
||||||
@ -1641,7 +1660,7 @@ void static ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChainParams& ch
|
|||||||
// instead we respond with the full, non-compact block.
|
// instead we respond with the full, non-compact block.
|
||||||
bool fPeerWantsWitness = State(pfrom.GetId())->fWantsCmpctWitness;
|
bool fPeerWantsWitness = State(pfrom.GetId())->fWantsCmpctWitness;
|
||||||
int nSendFlags = fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
|
int nSendFlags = fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
|
||||||
if (CanDirectFetch(consensusParams) && pindex->nHeight >= ::ChainActive().Height() - MAX_CMPCTBLOCK_DEPTH) {
|
if (CanDirectFetch(consensusParams) && pindex->nHeight >= m_chainman.ActiveChain().Height() - MAX_CMPCTBLOCK_DEPTH) {
|
||||||
if ((fPeerWantsWitness || !fWitnessesPresentInARecentCompactBlock) && a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->GetBlockHash()) {
|
if ((fPeerWantsWitness || !fWitnessesPresentInARecentCompactBlock) && a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->GetBlockHash()) {
|
||||||
connman.PushMessage(&pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *a_recent_compact_block));
|
connman.PushMessage(&pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *a_recent_compact_block));
|
||||||
} else {
|
} else {
|
||||||
@ -1662,7 +1681,7 @@ void static ProcessGetBlockData(CNode& pfrom, Peer& peer, const CChainParams& ch
|
|||||||
// and we want it right after the last block so they don't
|
// and we want it right after the last block so they don't
|
||||||
// wait for other stuff first.
|
// wait for other stuff first.
|
||||||
std::vector<CInv> vInv;
|
std::vector<CInv> vInv;
|
||||||
vInv.push_back(CInv(MSG_BLOCK, ::ChainActive().Tip()->GetBlockHash()));
|
vInv.push_back(CInv(MSG_BLOCK, m_chainman.ActiveChain().Tip()->GetBlockHash()));
|
||||||
connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::INV, vInv));
|
connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::INV, vInv));
|
||||||
peer.m_continuation_block.SetNull();
|
peer.m_continuation_block.SetNull();
|
||||||
}
|
}
|
||||||
@ -1841,9 +1860,9 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
|
|||||||
// don't connect before giving DoS points
|
// don't connect before giving DoS points
|
||||||
// - Once a headers message is received that is valid and does connect,
|
// - Once a headers message is received that is valid and does connect,
|
||||||
// nUnconnectingHeaders gets reset back to 0.
|
// nUnconnectingHeaders gets reset back to 0.
|
||||||
if (!g_chainman.m_blockman.LookupBlockIndex(headers[0].hashPrevBlock) && nCount < MAX_BLOCKS_TO_ANNOUNCE) {
|
if (!m_chainman.m_blockman.LookupBlockIndex(headers[0].hashPrevBlock) && nCount < MAX_BLOCKS_TO_ANNOUNCE) {
|
||||||
nodestate->nUnconnectingHeaders++;
|
nodestate->nUnconnectingHeaders++;
|
||||||
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, ::ChainActive().GetLocator(pindexBestHeader), uint256()));
|
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(pindexBestHeader), uint256()));
|
||||||
LogPrint(BCLog::NET, "received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n",
|
LogPrint(BCLog::NET, "received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n",
|
||||||
headers[0].GetHash().ToString(),
|
headers[0].GetHash().ToString(),
|
||||||
headers[0].hashPrevBlock.ToString(),
|
headers[0].hashPrevBlock.ToString(),
|
||||||
@ -1871,7 +1890,7 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
|
|||||||
|
|
||||||
// If we don't have the last header, then they'll have given us
|
// If we don't have the last header, then they'll have given us
|
||||||
// something new (if these headers are valid).
|
// something new (if these headers are valid).
|
||||||
if (!g_chainman.m_blockman.LookupBlockIndex(hashLastBlock)) {
|
if (!m_chainman.m_blockman.LookupBlockIndex(hashLastBlock)) {
|
||||||
received_new_header = true;
|
received_new_header = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1899,27 +1918,27 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
|
|||||||
// because it is set in UpdateBlockAvailability. Some nullptr checks
|
// because it is set in UpdateBlockAvailability. Some nullptr checks
|
||||||
// are still present, however, as belt-and-suspenders.
|
// are still present, however, as belt-and-suspenders.
|
||||||
|
|
||||||
if (received_new_header && pindexLast->nChainWork > ::ChainActive().Tip()->nChainWork) {
|
if (received_new_header && pindexLast->nChainWork > m_chainman.ActiveChain().Tip()->nChainWork) {
|
||||||
nodestate->m_last_block_announcement = GetTime();
|
nodestate->m_last_block_announcement = GetTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nCount == MAX_HEADERS_RESULTS) {
|
if (nCount == MAX_HEADERS_RESULTS) {
|
||||||
// Headers message had its maximum size; the peer may have more headers.
|
// Headers message had its maximum size; the peer may have more headers.
|
||||||
// TODO: optimize: if pindexLast is an ancestor of ::ChainActive().Tip or pindexBestHeader, continue
|
// TODO: optimize: if pindexLast is an ancestor of m_chainman.ActiveChain().Tip or pindexBestHeader, continue
|
||||||
// from there instead.
|
// from there instead.
|
||||||
LogPrint(BCLog::NET, "more getheaders (%d) to end to peer=%d (startheight:%d)\n",
|
LogPrint(BCLog::NET, "more getheaders (%d) to end to peer=%d (startheight:%d)\n",
|
||||||
pindexLast->nHeight, pfrom.GetId(), peer.m_starting_height);
|
pindexLast->nHeight, pfrom.GetId(), peer.m_starting_height);
|
||||||
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, ::ChainActive().GetLocator(pindexLast), uint256()));
|
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(pindexLast), uint256()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fCanDirectFetch = CanDirectFetch(m_chainparams.GetConsensus());
|
bool fCanDirectFetch = CanDirectFetch(m_chainparams.GetConsensus());
|
||||||
// If this set of headers is valid and ends in a block with at least as
|
// If this set of headers is valid and ends in a block with at least as
|
||||||
// much work as our tip, download as much as possible.
|
// much work as our tip, download as much as possible.
|
||||||
if (fCanDirectFetch && pindexLast->IsValid(BLOCK_VALID_TREE) && ::ChainActive().Tip()->nChainWork <= pindexLast->nChainWork) {
|
if (fCanDirectFetch && pindexLast->IsValid(BLOCK_VALID_TREE) && m_chainman.ActiveChain().Tip()->nChainWork <= pindexLast->nChainWork) {
|
||||||
std::vector<const CBlockIndex*> vToFetch;
|
std::vector<const CBlockIndex*> vToFetch;
|
||||||
const CBlockIndex *pindexWalk = pindexLast;
|
const CBlockIndex *pindexWalk = pindexLast;
|
||||||
// Calculate all the blocks we'd need to switch to pindexLast, up to a limit.
|
// Calculate all the blocks we'd need to switch to pindexLast, up to a limit.
|
||||||
while (pindexWalk && !::ChainActive().Contains(pindexWalk) && vToFetch.size() <= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
|
while (pindexWalk && !m_chainman.ActiveChain().Contains(pindexWalk) && vToFetch.size() <= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
|
||||||
if (!(pindexWalk->nStatus & BLOCK_HAVE_DATA) &&
|
if (!(pindexWalk->nStatus & BLOCK_HAVE_DATA) &&
|
||||||
!mapBlocksInFlight.count(pindexWalk->GetBlockHash()) &&
|
!mapBlocksInFlight.count(pindexWalk->GetBlockHash()) &&
|
||||||
(!IsWitnessEnabled(pindexWalk->pprev, m_chainparams.GetConsensus()) || State(pfrom.GetId())->fHaveWitness)) {
|
(!IsWitnessEnabled(pindexWalk->pprev, m_chainparams.GetConsensus()) || State(pfrom.GetId())->fHaveWitness)) {
|
||||||
@ -1932,7 +1951,7 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
|
|||||||
// very large reorg at a time we think we're close to caught up to
|
// very large reorg at a time we think we're close to caught up to
|
||||||
// the main chain -- this shouldn't really happen. Bail out on the
|
// the main chain -- this shouldn't really happen. Bail out on the
|
||||||
// direct fetch and rely on parallel download instead.
|
// direct fetch and rely on parallel download instead.
|
||||||
if (!::ChainActive().Contains(pindexWalk)) {
|
if (!m_chainman.ActiveChain().Contains(pindexWalk)) {
|
||||||
LogPrint(BCLog::NET, "Large reorg, won't direct fetch to %s (%d)\n",
|
LogPrint(BCLog::NET, "Large reorg, won't direct fetch to %s (%d)\n",
|
||||||
pindexLast->GetBlockHash().ToString(),
|
pindexLast->GetBlockHash().ToString(),
|
||||||
pindexLast->nHeight);
|
pindexLast->nHeight);
|
||||||
@ -1965,7 +1984,7 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
|
|||||||
}
|
}
|
||||||
// If we're in IBD, we want outbound peers that will serve us a useful
|
// If we're in IBD, we want outbound peers that will serve us a useful
|
||||||
// chain. Disconnect peers that are on chains with insufficient work.
|
// chain. Disconnect peers that are on chains with insufficient work.
|
||||||
if (::ChainstateActive().IsInitialBlockDownload() && nCount != MAX_HEADERS_RESULTS) {
|
if (m_chainman.ActiveChainstate().IsInitialBlockDownload() && nCount != MAX_HEADERS_RESULTS) {
|
||||||
// When nCount < MAX_HEADERS_RESULTS, we know we have no more
|
// When nCount < MAX_HEADERS_RESULTS, we know we have no more
|
||||||
// headers to fetch from this peer.
|
// headers to fetch from this peer.
|
||||||
if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < nMinimumChainWork) {
|
if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < nMinimumChainWork) {
|
||||||
@ -1973,7 +1992,7 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
|
|||||||
// us sync -- disconnect if it is an outbound disconnection
|
// us sync -- disconnect if it is an outbound disconnection
|
||||||
// candidate.
|
// candidate.
|
||||||
// Note: We compare their tip to nMinimumChainWork (rather than
|
// Note: We compare their tip to nMinimumChainWork (rather than
|
||||||
// ::ChainActive().Tip()) because we won't start block download
|
// m_chainman.ActiveChain().Tip()) because we won't start block download
|
||||||
// until we have a headers chain that has at least
|
// until we have a headers chain that has at least
|
||||||
// nMinimumChainWork, even if a peer has a chain past our tip,
|
// nMinimumChainWork, even if a peer has a chain past our tip,
|
||||||
// as an anti-DoS measure.
|
// as an anti-DoS measure.
|
||||||
@ -1990,7 +2009,7 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
|
|||||||
// thus always subject to eviction under the bad/lagging chain logic.
|
// thus always subject to eviction under the bad/lagging chain logic.
|
||||||
// See ChainSyncTimeoutState.
|
// See ChainSyncTimeoutState.
|
||||||
if (!pfrom.fDisconnect && pfrom.IsFullOutboundConn() && nodestate->pindexBestKnownBlock != nullptr) {
|
if (!pfrom.fDisconnect && pfrom.IsFullOutboundConn() && nodestate->pindexBestKnownBlock != nullptr) {
|
||||||
if (m_outbound_peers_with_protect_from_disconnect < MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT && nodestate->pindexBestKnownBlock->nChainWork >= ::ChainActive().Tip()->nChainWork && !nodestate->m_chain_sync.m_protect) {
|
if (m_outbound_peers_with_protect_from_disconnect < MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT && nodestate->pindexBestKnownBlock->nChainWork >= m_chainman.ActiveChain().Tip()->nChainWork && !nodestate->m_chain_sync.m_protect) {
|
||||||
LogPrint(BCLog::NET, "Protecting outbound peer=%d from eviction\n", pfrom.GetId());
|
LogPrint(BCLog::NET, "Protecting outbound peer=%d from eviction\n", pfrom.GetId());
|
||||||
nodestate->m_chain_sync.m_protect = true;
|
nodestate->m_chain_sync.m_protect = true;
|
||||||
++m_outbound_peers_with_protect_from_disconnect;
|
++m_outbound_peers_with_protect_from_disconnect;
|
||||||
@ -2021,7 +2040,7 @@ void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
|
|||||||
const auto [porphanTx, from_peer] = m_orphanage.GetTx(orphanHash);
|
const auto [porphanTx, from_peer] = m_orphanage.GetTx(orphanHash);
|
||||||
if (porphanTx == nullptr) continue;
|
if (porphanTx == nullptr) continue;
|
||||||
|
|
||||||
const MempoolAcceptResult result = AcceptToMemoryPool(::ChainstateActive(), m_mempool, porphanTx, false /* bypass_limits */);
|
const MempoolAcceptResult result = AcceptToMemoryPool(m_chainman.ActiveChainstate(), m_mempool, porphanTx, false /* bypass_limits */);
|
||||||
const TxValidationState& state = result.m_state;
|
const TxValidationState& state = result.m_state;
|
||||||
|
|
||||||
if (result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
|
if (result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
|
||||||
@ -2097,7 +2116,7 @@ void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
|
|||||||
* @param[out] filter_index The filter index, if the request can be serviced.
|
* @param[out] filter_index The filter index, if the request can be serviced.
|
||||||
* @return True if the request can be serviced.
|
* @return True if the request can be serviced.
|
||||||
*/
|
*/
|
||||||
static bool PrepareBlockFilterRequest(CNode& peer, const CChainParams& chain_params,
|
bool PeerManagerImpl::PrepareBlockFilterRequest(CNode& peer, const CChainParams& chain_params,
|
||||||
BlockFilterType filter_type, uint32_t start_height,
|
BlockFilterType filter_type, uint32_t start_height,
|
||||||
const uint256& stop_hash, uint32_t max_height_diff,
|
const uint256& stop_hash, uint32_t max_height_diff,
|
||||||
const CBlockIndex*& stop_index,
|
const CBlockIndex*& stop_index,
|
||||||
@ -2115,7 +2134,7 @@ static bool PrepareBlockFilterRequest(CNode& peer, const CChainParams& chain_par
|
|||||||
|
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
stop_index = g_chainman.m_blockman.LookupBlockIndex(stop_hash);
|
stop_index = m_chainman.m_blockman.LookupBlockIndex(stop_hash);
|
||||||
|
|
||||||
// Check that the stop block exists and the peer would be allowed to fetch it.
|
// Check that the stop block exists and the peer would be allowed to fetch it.
|
||||||
if (!stop_index || !BlockRequestAllowed(stop_index, chain_params.GetConsensus())) {
|
if (!stop_index || !BlockRequestAllowed(stop_index, chain_params.GetConsensus())) {
|
||||||
@ -2160,7 +2179,7 @@ static bool PrepareBlockFilterRequest(CNode& peer, const CChainParams& chain_par
|
|||||||
* @param[in] chain_params Chain parameters
|
* @param[in] chain_params Chain parameters
|
||||||
* @param[in] connman Pointer to the connection manager
|
* @param[in] connman Pointer to the connection manager
|
||||||
*/
|
*/
|
||||||
static void ProcessGetCFilters(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
|
void PeerManagerImpl::ProcessGetCFilters(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
|
||||||
CConnman& connman)
|
CConnman& connman)
|
||||||
{
|
{
|
||||||
uint8_t filter_type_ser;
|
uint8_t filter_type_ser;
|
||||||
@ -2202,7 +2221,7 @@ static void ProcessGetCFilters(CNode& peer, CDataStream& vRecv, const CChainPara
|
|||||||
* @param[in] chain_params Chain parameters
|
* @param[in] chain_params Chain parameters
|
||||||
* @param[in] connman Pointer to the connection manager
|
* @param[in] connman Pointer to the connection manager
|
||||||
*/
|
*/
|
||||||
static void ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
|
void PeerManagerImpl::ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
|
||||||
CConnman& connman)
|
CConnman& connman)
|
||||||
{
|
{
|
||||||
uint8_t filter_type_ser;
|
uint8_t filter_type_ser;
|
||||||
@ -2257,7 +2276,7 @@ static void ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv, const CChainPar
|
|||||||
* @param[in] chain_params Chain parameters
|
* @param[in] chain_params Chain parameters
|
||||||
* @param[in] connman Pointer to the connection manager
|
* @param[in] connman Pointer to the connection manager
|
||||||
*/
|
*/
|
||||||
static void ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
|
void PeerManagerImpl::ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv, const CChainParams& chain_params,
|
||||||
CConnman& connman)
|
CConnman& connman)
|
||||||
{
|
{
|
||||||
uint8_t filter_type_ser;
|
uint8_t filter_type_ser;
|
||||||
@ -2440,7 +2459,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||||||
//
|
//
|
||||||
// We skip this for block-relay-only peers to avoid potentially leaking
|
// We skip this for block-relay-only peers to avoid potentially leaking
|
||||||
// information about our block-relay-only connections via address relay.
|
// information about our block-relay-only connections via address relay.
|
||||||
if (fListen && !::ChainstateActive().IsInitialBlockDownload())
|
if (fListen && !m_chainman.ActiveChainstate().IsInitialBlockDownload())
|
||||||
{
|
{
|
||||||
CAddress addr = GetLocalAddress(&pfrom.addr, pfrom.GetLocalServices());
|
CAddress addr = GetLocalAddress(&pfrom.addr, pfrom.GetLocalServices());
|
||||||
FastRandomContext insecure_rand;
|
FastRandomContext insecure_rand;
|
||||||
@ -2757,7 +2776,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (best_block != nullptr) {
|
if (best_block != nullptr) {
|
||||||
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, ::ChainActive().GetLocator(pindexBestHeader), *best_block));
|
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(pindexBestHeader), *best_block));
|
||||||
LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, best_block->ToString(), pfrom.GetId());
|
LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, best_block->ToString(), pfrom.GetId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2813,7 +2832,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||||||
a_recent_block = most_recent_block;
|
a_recent_block = most_recent_block;
|
||||||
}
|
}
|
||||||
BlockValidationState state;
|
BlockValidationState state;
|
||||||
if (!::ChainstateActive().ActivateBestChain(state, m_chainparams, a_recent_block)) {
|
if (!m_chainman.ActiveChainstate().ActivateBestChain(state, m_chainparams, a_recent_block)) {
|
||||||
LogPrint(BCLog::NET, "failed to activate chain (%s)\n", state.ToString());
|
LogPrint(BCLog::NET, "failed to activate chain (%s)\n", state.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2821,14 +2840,14 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
// Find the last block the caller has in the main chain
|
// Find the last block the caller has in the main chain
|
||||||
const CBlockIndex* pindex = g_chainman.m_blockman.FindForkInGlobalIndex(::ChainActive(), locator);
|
const CBlockIndex* pindex = m_chainman.m_blockman.FindForkInGlobalIndex(m_chainman.ActiveChain(), locator);
|
||||||
|
|
||||||
// Send the rest of the chain
|
// Send the rest of the chain
|
||||||
if (pindex)
|
if (pindex)
|
||||||
pindex = ::ChainActive().Next(pindex);
|
pindex = m_chainman.ActiveChain().Next(pindex);
|
||||||
int nLimit = 500;
|
int nLimit = 500;
|
||||||
LogPrint(BCLog::NET, "getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), nLimit, pfrom.GetId());
|
LogPrint(BCLog::NET, "getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), nLimit, pfrom.GetId());
|
||||||
for (; pindex; pindex = ::ChainActive().Next(pindex))
|
for (; pindex; pindex = m_chainman.ActiveChain().Next(pindex))
|
||||||
{
|
{
|
||||||
if (pindex->GetBlockHash() == hashStop)
|
if (pindex->GetBlockHash() == hashStop)
|
||||||
{
|
{
|
||||||
@ -2838,7 +2857,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||||||
// If pruning, don't inv blocks unless we have on disk and are likely to still have
|
// If pruning, don't inv blocks unless we have on disk and are likely to still have
|
||||||
// for some reasonable time window (1 hour) that block relay might require.
|
// for some reasonable time window (1 hour) that block relay might require.
|
||||||
const int nPrunedBlocksLikelyToHave = MIN_BLOCKS_TO_KEEP - 3600 / m_chainparams.GetConsensus().nPowTargetSpacing;
|
const int nPrunedBlocksLikelyToHave = MIN_BLOCKS_TO_KEEP - 3600 / m_chainparams.GetConsensus().nPowTargetSpacing;
|
||||||
if (fPruneMode && (!(pindex->nStatus & BLOCK_HAVE_DATA) || pindex->nHeight <= ::ChainActive().Tip()->nHeight - nPrunedBlocksLikelyToHave))
|
if (fPruneMode && (!(pindex->nStatus & BLOCK_HAVE_DATA) || pindex->nHeight <= m_chainman.ActiveChain().Tip()->nHeight - nPrunedBlocksLikelyToHave))
|
||||||
{
|
{
|
||||||
LogPrint(BCLog::NET, " getblocks stopping, pruned or too old block at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
|
LogPrint(BCLog::NET, " getblocks stopping, pruned or too old block at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
|
||||||
break;
|
break;
|
||||||
@ -2874,13 +2893,13 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
const CBlockIndex* pindex = g_chainman.m_blockman.LookupBlockIndex(req.blockhash);
|
const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(req.blockhash);
|
||||||
if (!pindex || !(pindex->nStatus & BLOCK_HAVE_DATA)) {
|
if (!pindex || !(pindex->nStatus & BLOCK_HAVE_DATA)) {
|
||||||
LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block we don't have\n", pfrom.GetId());
|
LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block we don't have\n", pfrom.GetId());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pindex->nHeight >= ::ChainActive().Height() - MAX_BLOCKTXN_DEPTH) {
|
if (pindex->nHeight >= m_chainman.ActiveChain().Height() - MAX_BLOCKTXN_DEPTH) {
|
||||||
CBlock block;
|
CBlock block;
|
||||||
bool ret = ReadBlockFromDisk(block, pindex, m_chainparams.GetConsensus());
|
bool ret = ReadBlockFromDisk(block, pindex, m_chainparams.GetConsensus());
|
||||||
assert(ret);
|
assert(ret);
|
||||||
@ -2918,7 +2937,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
if (::ChainstateActive().IsInitialBlockDownload() && !pfrom.HasPermission(PF_DOWNLOAD)) {
|
if (m_chainman.ActiveChainstate().IsInitialBlockDownload() && !pfrom.HasPermission(PF_DOWNLOAD)) {
|
||||||
LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d because node is in initial block download\n", pfrom.GetId());
|
LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d because node is in initial block download\n", pfrom.GetId());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2928,7 +2947,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||||||
if (locator.IsNull())
|
if (locator.IsNull())
|
||||||
{
|
{
|
||||||
// If locator is null, return the hashStop block
|
// If locator is null, return the hashStop block
|
||||||
pindex = g_chainman.m_blockman.LookupBlockIndex(hashStop);
|
pindex = m_chainman.m_blockman.LookupBlockIndex(hashStop);
|
||||||
if (!pindex) {
|
if (!pindex) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2941,23 +2960,23 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Find the last block the caller has in the main chain
|
// Find the last block the caller has in the main chain
|
||||||
pindex = g_chainman.m_blockman.FindForkInGlobalIndex(::ChainActive(), locator);
|
pindex = m_chainman.m_blockman.FindForkInGlobalIndex(m_chainman.ActiveChain(), locator);
|
||||||
if (pindex)
|
if (pindex)
|
||||||
pindex = ::ChainActive().Next(pindex);
|
pindex = m_chainman.ActiveChain().Next(pindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end
|
// we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end
|
||||||
std::vector<CBlock> vHeaders;
|
std::vector<CBlock> vHeaders;
|
||||||
int nLimit = MAX_HEADERS_RESULTS;
|
int nLimit = MAX_HEADERS_RESULTS;
|
||||||
LogPrint(BCLog::NET, "getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), pfrom.GetId());
|
LogPrint(BCLog::NET, "getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), pfrom.GetId());
|
||||||
for (; pindex; pindex = ::ChainActive().Next(pindex))
|
for (; pindex; pindex = m_chainman.ActiveChain().Next(pindex))
|
||||||
{
|
{
|
||||||
vHeaders.push_back(pindex->GetBlockHeader());
|
vHeaders.push_back(pindex->GetBlockHeader());
|
||||||
if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
|
if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// pindex can be nullptr either if we sent ::ChainActive().Tip() OR
|
// pindex can be nullptr either if we sent m_chainman.ActiveChain().Tip() OR
|
||||||
// if our peer has ::ChainActive().Tip() (and thus we are sending an empty
|
// if our peer has m_chainman.ActiveChain().Tip() (and thus we are sending an empty
|
||||||
// headers message). In both cases it's safe to update
|
// headers message). In both cases it's safe to update
|
||||||
// pindexBestHeaderSent to be our tip.
|
// pindexBestHeaderSent to be our tip.
|
||||||
//
|
//
|
||||||
@ -2968,7 +2987,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||||||
// without the new block. By resetting the BestHeaderSent, we ensure we
|
// without the new block. By resetting the BestHeaderSent, we ensure we
|
||||||
// will re-announce the new block via headers (or compact blocks again)
|
// will re-announce the new block via headers (or compact blocks again)
|
||||||
// in the SendMessages logic.
|
// in the SendMessages logic.
|
||||||
nodestate->pindexBestHeaderSent = pindex ? pindex : ::ChainActive().Tip();
|
nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.ActiveChain().Tip();
|
||||||
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::HEADERS, vHeaders));
|
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::HEADERS, vHeaders));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3036,7 +3055,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MempoolAcceptResult result = AcceptToMemoryPool(::ChainstateActive(), m_mempool, ptx, false /* bypass_limits */);
|
const MempoolAcceptResult result = AcceptToMemoryPool(m_chainman.ActiveChainstate(), m_mempool, ptx, false /* bypass_limits */);
|
||||||
const TxValidationState& state = result.m_state;
|
const TxValidationState& state = result.m_state;
|
||||||
|
|
||||||
if (result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
|
if (result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
|
||||||
@ -3201,14 +3220,14 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
if (!g_chainman.m_blockman.LookupBlockIndex(cmpctblock.header.hashPrevBlock)) {
|
if (!m_chainman.m_blockman.LookupBlockIndex(cmpctblock.header.hashPrevBlock)) {
|
||||||
// Doesn't connect (or is genesis), instead of DoSing in AcceptBlockHeader, request deeper headers
|
// Doesn't connect (or is genesis), instead of DoSing in AcceptBlockHeader, request deeper headers
|
||||||
if (!::ChainstateActive().IsInitialBlockDownload())
|
if (!m_chainman.ActiveChainstate().IsInitialBlockDownload())
|
||||||
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, ::ChainActive().GetLocator(pindexBestHeader), uint256()));
|
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(pindexBestHeader), uint256()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_chainman.m_blockman.LookupBlockIndex(cmpctblock.header.GetHash())) {
|
if (!m_chainman.m_blockman.LookupBlockIndex(cmpctblock.header.GetHash())) {
|
||||||
received_new_header = true;
|
received_new_header = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3248,7 +3267,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||||||
|
|
||||||
// If this was a new header with more work than our tip, update the
|
// If this was a new header with more work than our tip, update the
|
||||||
// peer's last block announcement time
|
// peer's last block announcement time
|
||||||
if (received_new_header && pindex->nChainWork > ::ChainActive().Tip()->nChainWork) {
|
if (received_new_header && pindex->nChainWork > m_chainman.ActiveChain().Tip()->nChainWork) {
|
||||||
nodestate->m_last_block_announcement = GetTime();
|
nodestate->m_last_block_announcement = GetTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3258,7 +3277,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||||||
if (pindex->nStatus & BLOCK_HAVE_DATA) // Nothing to do here
|
if (pindex->nStatus & BLOCK_HAVE_DATA) // Nothing to do here
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (pindex->nChainWork <= ::ChainActive().Tip()->nChainWork || // We know something better
|
if (pindex->nChainWork <= m_chainman.ActiveChain().Tip()->nChainWork || // We know something better
|
||||||
pindex->nTx != 0) { // We had this block at some point, but pruned it
|
pindex->nTx != 0) { // We had this block at some point, but pruned it
|
||||||
if (fAlreadyInFlight) {
|
if (fAlreadyInFlight) {
|
||||||
// We requested this block for some reason, but our mempool will probably be useless
|
// We requested this block for some reason, but our mempool will probably be useless
|
||||||
@ -3282,7 +3301,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||||||
|
|
||||||
// We want to be a bit conservative just to be extra careful about DoS
|
// We want to be a bit conservative just to be extra careful about DoS
|
||||||
// possibilities in compact block processing...
|
// possibilities in compact block processing...
|
||||||
if (pindex->nHeight <= ::ChainActive().Height() + 2) {
|
if (pindex->nHeight <= m_chainman.ActiveChain().Height() + 2) {
|
||||||
if ((!fAlreadyInFlight && nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) ||
|
if ((!fAlreadyInFlight && nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) ||
|
||||||
(fAlreadyInFlight && blockInFlightIt->second.first == pfrom.GetId())) {
|
(fAlreadyInFlight && blockInFlightIt->second.first == pfrom.GetId())) {
|
||||||
std::list<QueuedBlock>::iterator* queuedBlockIt = nullptr;
|
std::list<QueuedBlock>::iterator* queuedBlockIt = nullptr;
|
||||||
@ -3930,7 +3949,7 @@ void PeerManagerImpl::ConsiderEviction(CNode& pto, int64_t time_in_seconds)
|
|||||||
// their chain has more work than ours, we should sync to it,
|
// their chain has more work than ours, we should sync to it,
|
||||||
// unless it's invalid, in which case we should find that out and
|
// unless it's invalid, in which case we should find that out and
|
||||||
// disconnect from them elsewhere).
|
// disconnect from them elsewhere).
|
||||||
if (state.pindexBestKnownBlock != nullptr && state.pindexBestKnownBlock->nChainWork >= ::ChainActive().Tip()->nChainWork) {
|
if (state.pindexBestKnownBlock != nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.ActiveChain().Tip()->nChainWork) {
|
||||||
if (state.m_chain_sync.m_timeout != 0) {
|
if (state.m_chain_sync.m_timeout != 0) {
|
||||||
state.m_chain_sync.m_timeout = 0;
|
state.m_chain_sync.m_timeout = 0;
|
||||||
state.m_chain_sync.m_work_header = nullptr;
|
state.m_chain_sync.m_work_header = nullptr;
|
||||||
@ -3942,7 +3961,7 @@ void PeerManagerImpl::ConsiderEviction(CNode& pto, int64_t time_in_seconds)
|
|||||||
// where we checked against our tip.
|
// where we checked against our tip.
|
||||||
// Either way, set a new timeout based on current tip.
|
// Either way, set a new timeout based on current tip.
|
||||||
state.m_chain_sync.m_timeout = time_in_seconds + CHAIN_SYNC_TIMEOUT;
|
state.m_chain_sync.m_timeout = time_in_seconds + CHAIN_SYNC_TIMEOUT;
|
||||||
state.m_chain_sync.m_work_header = ::ChainActive().Tip();
|
state.m_chain_sync.m_work_header = m_chainman.ActiveChain().Tip();
|
||||||
state.m_chain_sync.m_sent_getheaders = false;
|
state.m_chain_sync.m_sent_getheaders = false;
|
||||||
} else if (state.m_chain_sync.m_timeout > 0 && time_in_seconds > state.m_chain_sync.m_timeout) {
|
} else if (state.m_chain_sync.m_timeout > 0 && time_in_seconds > state.m_chain_sync.m_timeout) {
|
||||||
// No evidence yet that our peer has synced to a chain with work equal to that
|
// No evidence yet that our peer has synced to a chain with work equal to that
|
||||||
@ -3955,7 +3974,7 @@ void PeerManagerImpl::ConsiderEviction(CNode& pto, int64_t time_in_seconds)
|
|||||||
} else {
|
} else {
|
||||||
assert(state.m_chain_sync.m_work_header);
|
assert(state.m_chain_sync.m_work_header);
|
||||||
LogPrint(BCLog::NET, "sending getheaders to outbound peer=%d to verify chain work (current best known block:%s, benchmark blockhash: %s)\n", pto.GetId(), state.pindexBestKnownBlock != nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() : "<none>", state.m_chain_sync.m_work_header->GetBlockHash().ToString());
|
LogPrint(BCLog::NET, "sending getheaders to outbound peer=%d to verify chain work (current best known block:%s, benchmark blockhash: %s)\n", pto.GetId(), state.pindexBestKnownBlock != nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() : "<none>", state.m_chain_sync.m_work_header->GetBlockHash().ToString());
|
||||||
m_connman.PushMessage(&pto, msgMaker.Make(NetMsgType::GETHEADERS, ::ChainActive().GetLocator(state.m_chain_sync.m_work_header->pprev), uint256()));
|
m_connman.PushMessage(&pto, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(state.m_chain_sync.m_work_header->pprev), uint256()));
|
||||||
state.m_chain_sync.m_sent_getheaders = true;
|
state.m_chain_sync.m_sent_getheaders = true;
|
||||||
constexpr int64_t HEADERS_RESPONSE_TIME = 120; // 2 minutes
|
constexpr int64_t HEADERS_RESPONSE_TIME = 120; // 2 minutes
|
||||||
// Bump the timeout to allow a response, which could clear the timeout
|
// Bump the timeout to allow a response, which could clear the timeout
|
||||||
@ -4192,7 +4211,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
|||||||
auto current_time = GetTime<std::chrono::microseconds>();
|
auto current_time = GetTime<std::chrono::microseconds>();
|
||||||
|
|
||||||
if (fListen && pto->RelayAddrsWithConn() &&
|
if (fListen && pto->RelayAddrsWithConn() &&
|
||||||
!::ChainstateActive().IsInitialBlockDownload() &&
|
!m_chainman.ActiveChainstate().IsInitialBlockDownload() &&
|
||||||
pto->m_next_local_addr_send < current_time) {
|
pto->m_next_local_addr_send < current_time) {
|
||||||
// If we've sent before, clear the bloom filter for the peer, so that our
|
// If we've sent before, clear the bloom filter for the peer, so that our
|
||||||
// self-announcement will actually go out.
|
// self-announcement will actually go out.
|
||||||
@ -4253,7 +4272,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
|||||||
|
|
||||||
// Start block sync
|
// Start block sync
|
||||||
if (pindexBestHeader == nullptr)
|
if (pindexBestHeader == nullptr)
|
||||||
pindexBestHeader = ::ChainActive().Tip();
|
pindexBestHeader = m_chainman.ActiveChain().Tip();
|
||||||
bool fFetch = state.fPreferredDownload || (nPreferredDownload == 0 && !pto->fClient && !pto->IsAddrFetchConn()); // Download if this is a nice peer, or we have no nice peers and this one might do.
|
bool fFetch = state.fPreferredDownload || (nPreferredDownload == 0 && !pto->fClient && !pto->IsAddrFetchConn()); // Download if this is a nice peer, or we have no nice peers and this one might do.
|
||||||
if (!state.fSyncStarted && !pto->fClient && !fImporting && !fReindex) {
|
if (!state.fSyncStarted && !pto->fClient && !fImporting && !fReindex) {
|
||||||
// Only actively request headers from a single peer, unless we're close to today.
|
// Only actively request headers from a single peer, unless we're close to today.
|
||||||
@ -4278,7 +4297,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
|||||||
if (pindexStart->pprev)
|
if (pindexStart->pprev)
|
||||||
pindexStart = pindexStart->pprev;
|
pindexStart = pindexStart->pprev;
|
||||||
LogPrint(BCLog::NET, "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->GetId(), peer->m_starting_height);
|
LogPrint(BCLog::NET, "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->GetId(), peer->m_starting_height);
|
||||||
m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETHEADERS, ::ChainActive().GetLocator(pindexStart), uint256()));
|
m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(pindexStart), uint256()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4305,11 +4324,11 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
|||||||
bool fFoundStartingHeader = false;
|
bool fFoundStartingHeader = false;
|
||||||
// Try to find first header that our peer doesn't have, and
|
// Try to find first header that our peer doesn't have, and
|
||||||
// then send all headers past that one. If we come across any
|
// then send all headers past that one. If we come across any
|
||||||
// headers that aren't on ::ChainActive(), give up.
|
// headers that aren't on m_chainman.ActiveChain(), give up.
|
||||||
for (const uint256& hash : peer->m_blocks_for_headers_relay) {
|
for (const uint256& hash : peer->m_blocks_for_headers_relay) {
|
||||||
const CBlockIndex* pindex = g_chainman.m_blockman.LookupBlockIndex(hash);
|
const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(hash);
|
||||||
assert(pindex);
|
assert(pindex);
|
||||||
if (::ChainActive()[pindex->nHeight] != pindex) {
|
if (m_chainman.ActiveChain()[pindex->nHeight] != pindex) {
|
||||||
// Bail out if we reorged away from this block
|
// Bail out if we reorged away from this block
|
||||||
fRevertToInv = true;
|
fRevertToInv = true;
|
||||||
break;
|
break;
|
||||||
@ -4399,15 +4418,15 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
|||||||
// in the past.
|
// in the past.
|
||||||
if (!peer->m_blocks_for_headers_relay.empty()) {
|
if (!peer->m_blocks_for_headers_relay.empty()) {
|
||||||
const uint256& hashToAnnounce = peer->m_blocks_for_headers_relay.back();
|
const uint256& hashToAnnounce = peer->m_blocks_for_headers_relay.back();
|
||||||
const CBlockIndex* pindex = g_chainman.m_blockman.LookupBlockIndex(hashToAnnounce);
|
const CBlockIndex* pindex = m_chainman.m_blockman.LookupBlockIndex(hashToAnnounce);
|
||||||
assert(pindex);
|
assert(pindex);
|
||||||
|
|
||||||
// Warn if we're announcing a block that is not on the main chain.
|
// Warn if we're announcing a block that is not on the main chain.
|
||||||
// This should be very rare and could be optimized out.
|
// This should be very rare and could be optimized out.
|
||||||
// Just log for now.
|
// Just log for now.
|
||||||
if (::ChainActive()[pindex->nHeight] != pindex) {
|
if (m_chainman.ActiveChain()[pindex->nHeight] != pindex) {
|
||||||
LogPrint(BCLog::NET, "Announcing block %s not on main chain (tip=%s)\n",
|
LogPrint(BCLog::NET, "Announcing block %s not on main chain (tip=%s)\n",
|
||||||
hashToAnnounce.ToString(), ::ChainActive().Tip()->GetBlockHash().ToString());
|
hashToAnnounce.ToString(), m_chainman.ActiveChain().Tip()->GetBlockHash().ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the peer's chain has this block, don't inv it back.
|
// If the peer's chain has this block, don't inv it back.
|
||||||
@ -4637,7 +4656,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
|||||||
// Message: getdata (blocks)
|
// Message: getdata (blocks)
|
||||||
//
|
//
|
||||||
std::vector<CInv> vGetData;
|
std::vector<CInv> vGetData;
|
||||||
if (!pto->fClient && ((fFetch && !pto->m_limited_node) || !::ChainstateActive().IsInitialBlockDownload()) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
|
if (!pto->fClient && ((fFetch && !pto->m_limited_node) || !m_chainman.ActiveChainstate().IsInitialBlockDownload()) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
|
||||||
std::vector<const CBlockIndex*> vToDownload;
|
std::vector<const CBlockIndex*> vToDownload;
|
||||||
NodeId staller = -1;
|
NodeId staller = -1;
|
||||||
FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller);
|
FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller);
|
||||||
@ -4726,4 +4745,3 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
|||||||
} // release cs_main
|
} // release cs_main
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,8 @@ void FindCoins(const NodeContext& node, std::map<COutPoint, Coin>& coins)
|
|||||||
{
|
{
|
||||||
assert(node.mempool);
|
assert(node.mempool);
|
||||||
LOCK2(cs_main, node.mempool->cs);
|
LOCK2(cs_main, node.mempool->cs);
|
||||||
CCoinsViewCache& chain_view = ::ChainstateActive().CoinsTip();
|
assert(std::addressof(::ChainstateActive()) == std::addressof(node.chainman->ActiveChainstate()));
|
||||||
|
CCoinsViewCache& chain_view = node.chainman->ActiveChainstate().CoinsTip();
|
||||||
CCoinsViewMemPool mempool_view(&chain_view, *node.mempool);
|
CCoinsViewMemPool mempool_view(&chain_view, *node.mempool);
|
||||||
for (auto& coin : coins) {
|
for (auto& coin : coins) {
|
||||||
if (!mempool_view.GetCoin(coin.first, coin.second)) {
|
if (!mempool_view.GetCoin(coin.first, coin.second)) {
|
||||||
|
@ -83,7 +83,7 @@ static void ApplyStats(CCoinsStats& stats, T& hash_obj, const uint256& hash, con
|
|||||||
|
|
||||||
//! Calculate statistics about the unspent transaction output set
|
//! Calculate statistics about the unspent transaction output set
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static bool GetUTXOStats(CCoinsView* view, CCoinsStats& stats, T hash_obj, const std::function<void()>& interruption_point)
|
static bool GetUTXOStats(CCoinsView* view, BlockManager& blockman, CCoinsStats& stats, T hash_obj, const std::function<void()>& interruption_point)
|
||||||
{
|
{
|
||||||
stats = CCoinsStats();
|
stats = CCoinsStats();
|
||||||
std::unique_ptr<CCoinsViewCursor> pcursor(view->Cursor());
|
std::unique_ptr<CCoinsViewCursor> pcursor(view->Cursor());
|
||||||
@ -92,7 +92,8 @@ static bool GetUTXOStats(CCoinsView* view, CCoinsStats& stats, T hash_obj, const
|
|||||||
stats.hashBlock = pcursor->GetBestBlock();
|
stats.hashBlock = pcursor->GetBestBlock();
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
stats.nHeight = g_chainman.m_blockman.LookupBlockIndex(stats.hashBlock)->nHeight;
|
assert(std::addressof(g_chainman.m_blockman) == std::addressof(blockman));
|
||||||
|
stats.nHeight = blockman.LookupBlockIndex(stats.hashBlock)->nHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrepareHash(hash_obj, stats);
|
PrepareHash(hash_obj, stats);
|
||||||
@ -126,19 +127,19 @@ static bool GetUTXOStats(CCoinsView* view, CCoinsStats& stats, T hash_obj, const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetUTXOStats(CCoinsView* view, CCoinsStats& stats, CoinStatsHashType hash_type, const std::function<void()>& interruption_point)
|
bool GetUTXOStats(CCoinsView* view, BlockManager& blockman, CCoinsStats& stats, CoinStatsHashType hash_type, const std::function<void()>& interruption_point)
|
||||||
{
|
{
|
||||||
switch (hash_type) {
|
switch (hash_type) {
|
||||||
case(CoinStatsHashType::HASH_SERIALIZED): {
|
case(CoinStatsHashType::HASH_SERIALIZED): {
|
||||||
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
|
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
|
||||||
return GetUTXOStats(view, stats, ss, interruption_point);
|
return GetUTXOStats(view, blockman, stats, ss, interruption_point);
|
||||||
}
|
}
|
||||||
case(CoinStatsHashType::MUHASH): {
|
case(CoinStatsHashType::MUHASH): {
|
||||||
MuHash3072 muhash;
|
MuHash3072 muhash;
|
||||||
return GetUTXOStats(view, stats, muhash, interruption_point);
|
return GetUTXOStats(view, blockman, stats, muhash, interruption_point);
|
||||||
}
|
}
|
||||||
case(CoinStatsHashType::NONE): {
|
case(CoinStatsHashType::NONE): {
|
||||||
return GetUTXOStats(view, stats, nullptr, interruption_point);
|
return GetUTXOStats(view, blockman, stats, nullptr, interruption_point);
|
||||||
}
|
}
|
||||||
} // no default case, so the compiler can warn about missing cases
|
} // no default case, so the compiler can warn about missing cases
|
||||||
assert(false);
|
assert(false);
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <amount.h>
|
#include <amount.h>
|
||||||
#include <uint256.h>
|
#include <uint256.h>
|
||||||
|
#include <validation.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@ -36,6 +37,6 @@ struct CCoinsStats
|
|||||||
};
|
};
|
||||||
|
|
||||||
//! Calculate statistics about the unspent transaction output set
|
//! Calculate statistics about the unspent transaction output set
|
||||||
bool GetUTXOStats(CCoinsView* view, CCoinsStats& stats, const CoinStatsHashType hash_type, const std::function<void()>& interruption_point = {});
|
bool GetUTXOStats(CCoinsView* view, BlockManager& blockman, CCoinsStats& stats, const CoinStatsHashType hash_type, const std::function<void()>& interruption_point = {});
|
||||||
|
|
||||||
#endif // BITCOIN_NODE_COINSTATS_H
|
#endif // BITCOIN_NODE_COINSTATS_H
|
||||||
|
@ -182,18 +182,21 @@ public:
|
|||||||
int getNumBlocks() override
|
int getNumBlocks() override
|
||||||
{
|
{
|
||||||
LOCK(::cs_main);
|
LOCK(::cs_main);
|
||||||
return ::ChainActive().Height();
|
assert(std::addressof(::ChainActive()) == std::addressof(m_context->chainman->ActiveChain()));
|
||||||
|
return m_context->chainman->ActiveChain().Height();
|
||||||
}
|
}
|
||||||
uint256 getBestBlockHash() override
|
uint256 getBestBlockHash() override
|
||||||
{
|
{
|
||||||
const CBlockIndex* tip = WITH_LOCK(::cs_main, return ::ChainActive().Tip());
|
assert(std::addressof(::ChainActive()) == std::addressof(m_context->chainman->ActiveChain()));
|
||||||
|
const CBlockIndex* tip = WITH_LOCK(::cs_main, return m_context->chainman->ActiveChain().Tip());
|
||||||
return tip ? tip->GetBlockHash() : Params().GenesisBlock().GetHash();
|
return tip ? tip->GetBlockHash() : Params().GenesisBlock().GetHash();
|
||||||
}
|
}
|
||||||
int64_t getLastBlockTime() override
|
int64_t getLastBlockTime() override
|
||||||
{
|
{
|
||||||
LOCK(::cs_main);
|
LOCK(::cs_main);
|
||||||
if (::ChainActive().Tip()) {
|
assert(std::addressof(::ChainActive()) == std::addressof(m_context->chainman->ActiveChain()));
|
||||||
return ::ChainActive().Tip()->GetBlockTime();
|
if (m_context->chainman->ActiveChain().Tip()) {
|
||||||
|
return m_context->chainman->ActiveChain().Tip()->GetBlockTime();
|
||||||
}
|
}
|
||||||
return Params().GenesisBlock().GetBlockTime(); // Genesis block's time of current network
|
return Params().GenesisBlock().GetBlockTime(); // Genesis block's time of current network
|
||||||
}
|
}
|
||||||
@ -202,11 +205,15 @@ public:
|
|||||||
const CBlockIndex* tip;
|
const CBlockIndex* tip;
|
||||||
{
|
{
|
||||||
LOCK(::cs_main);
|
LOCK(::cs_main);
|
||||||
tip = ::ChainActive().Tip();
|
assert(std::addressof(::ChainActive()) == std::addressof(m_context->chainman->ActiveChain()));
|
||||||
|
tip = m_context->chainman->ActiveChain().Tip();
|
||||||
}
|
}
|
||||||
return GuessVerificationProgress(Params().TxData(), tip);
|
return GuessVerificationProgress(Params().TxData(), tip);
|
||||||
}
|
}
|
||||||
bool isInitialBlockDownload() override { return ::ChainstateActive().IsInitialBlockDownload(); }
|
bool isInitialBlockDownload() override {
|
||||||
|
assert(std::addressof(::ChainstateActive()) == std::addressof(m_context->chainman->ActiveChainstate()));
|
||||||
|
return m_context->chainman->ActiveChainstate().IsInitialBlockDownload();
|
||||||
|
}
|
||||||
bool getReindex() override { return ::fReindex; }
|
bool getReindex() override { return ::fReindex; }
|
||||||
bool getImporting() override { return ::fImporting; }
|
bool getImporting() override { return ::fImporting; }
|
||||||
void setNetworkActive(bool active) override
|
void setNetworkActive(bool active) override
|
||||||
@ -231,7 +238,8 @@ public:
|
|||||||
bool getUnspentOutput(const COutPoint& output, Coin& coin) override
|
bool getUnspentOutput(const COutPoint& output, Coin& coin) override
|
||||||
{
|
{
|
||||||
LOCK(::cs_main);
|
LOCK(::cs_main);
|
||||||
return ::ChainstateActive().CoinsTip().GetCoin(output, coin);
|
assert(std::addressof(::ChainstateActive()) == std::addressof(m_context->chainman->ActiveChainstate()));
|
||||||
|
return m_context->chainman->ActiveChainstate().CoinsTip().GetCoin(output, coin);
|
||||||
}
|
}
|
||||||
WalletClient& walletClient() override
|
WalletClient& walletClient() override
|
||||||
{
|
{
|
||||||
@ -441,13 +449,15 @@ public:
|
|||||||
bool checkFinalTx(const CTransaction& tx) override
|
bool checkFinalTx(const CTransaction& tx) override
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
return CheckFinalTx(::ChainActive().Tip(), tx);
|
assert(std::addressof(::ChainActive()) == std::addressof(m_node.chainman->ActiveChain()));
|
||||||
|
return CheckFinalTx(m_node.chainman->ActiveChain().Tip(), tx);
|
||||||
}
|
}
|
||||||
Optional<int> findLocatorFork(const CBlockLocator& locator) override
|
Optional<int> findLocatorFork(const CBlockLocator& locator) override
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
||||||
if (CBlockIndex* fork = g_chainman.m_blockman.FindForkInGlobalIndex(active, locator)) {
|
assert(std::addressof(g_chainman) == std::addressof(*m_node.chainman));
|
||||||
|
if (CBlockIndex* fork = m_node.chainman->m_blockman.FindForkInGlobalIndex(active, locator)) {
|
||||||
return fork->nHeight;
|
return fork->nHeight;
|
||||||
}
|
}
|
||||||
return nullopt;
|
return nullopt;
|
||||||
@ -456,7 +466,8 @@ public:
|
|||||||
{
|
{
|
||||||
WAIT_LOCK(cs_main, lock);
|
WAIT_LOCK(cs_main, lock);
|
||||||
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
||||||
return FillBlock(g_chainman.m_blockman.LookupBlockIndex(hash), block, lock, active);
|
assert(std::addressof(g_chainman) == std::addressof(*m_node.chainman));
|
||||||
|
return FillBlock(m_node.chainman->m_blockman.LookupBlockIndex(hash), block, lock, active);
|
||||||
}
|
}
|
||||||
bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block) override
|
bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block) override
|
||||||
{
|
{
|
||||||
@ -468,7 +479,8 @@ public:
|
|||||||
{
|
{
|
||||||
WAIT_LOCK(cs_main, lock);
|
WAIT_LOCK(cs_main, lock);
|
||||||
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
||||||
if (const CBlockIndex* block = g_chainman.m_blockman.LookupBlockIndex(block_hash)) {
|
assert(std::addressof(g_chainman) == std::addressof(*m_node.chainman));
|
||||||
|
if (const CBlockIndex* block = m_node.chainman->m_blockman.LookupBlockIndex(block_hash)) {
|
||||||
if (const CBlockIndex* ancestor = block->GetAncestor(ancestor_height)) {
|
if (const CBlockIndex* ancestor = block->GetAncestor(ancestor_height)) {
|
||||||
return FillBlock(ancestor, ancestor_out, lock, active);
|
return FillBlock(ancestor, ancestor_out, lock, active);
|
||||||
}
|
}
|
||||||
@ -479,8 +491,10 @@ public:
|
|||||||
{
|
{
|
||||||
WAIT_LOCK(cs_main, lock);
|
WAIT_LOCK(cs_main, lock);
|
||||||
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
||||||
const CBlockIndex* block = g_chainman.m_blockman.LookupBlockIndex(block_hash);
|
assert(std::addressof(g_chainman) == std::addressof(*m_node.chainman));
|
||||||
const CBlockIndex* ancestor = g_chainman.m_blockman.LookupBlockIndex(ancestor_hash);
|
const CBlockIndex* block = m_node.chainman->m_blockman.LookupBlockIndex(block_hash);
|
||||||
|
assert(std::addressof(g_chainman) == std::addressof(*m_node.chainman));
|
||||||
|
const CBlockIndex* ancestor = m_node.chainman->m_blockman.LookupBlockIndex(ancestor_hash);
|
||||||
if (block && ancestor && block->GetAncestor(ancestor->nHeight) != ancestor) ancestor = nullptr;
|
if (block && ancestor && block->GetAncestor(ancestor->nHeight) != ancestor) ancestor = nullptr;
|
||||||
return FillBlock(ancestor, ancestor_out, lock, active);
|
return FillBlock(ancestor, ancestor_out, lock, active);
|
||||||
}
|
}
|
||||||
@ -488,8 +502,10 @@ public:
|
|||||||
{
|
{
|
||||||
WAIT_LOCK(cs_main, lock);
|
WAIT_LOCK(cs_main, lock);
|
||||||
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
||||||
const CBlockIndex* block1 = g_chainman.m_blockman.LookupBlockIndex(block_hash1);
|
assert(std::addressof(g_chainman) == std::addressof(*m_node.chainman));
|
||||||
const CBlockIndex* block2 = g_chainman.m_blockman.LookupBlockIndex(block_hash2);
|
const CBlockIndex* block1 = m_node.chainman->m_blockman.LookupBlockIndex(block_hash1);
|
||||||
|
assert(std::addressof(g_chainman) == std::addressof(*m_node.chainman));
|
||||||
|
const CBlockIndex* block2 = m_node.chainman->m_blockman.LookupBlockIndex(block_hash2);
|
||||||
const CBlockIndex* ancestor = block1 && block2 ? LastCommonAncestor(block1, block2) : nullptr;
|
const CBlockIndex* ancestor = block1 && block2 ? LastCommonAncestor(block1, block2) : nullptr;
|
||||||
// Using & instead of && below to avoid short circuiting and leaving
|
// Using & instead of && below to avoid short circuiting and leaving
|
||||||
// output uninitialized.
|
// output uninitialized.
|
||||||
@ -499,7 +515,8 @@ public:
|
|||||||
double guessVerificationProgress(const uint256& block_hash) override
|
double guessVerificationProgress(const uint256& block_hash) override
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
return GuessVerificationProgress(Params().TxData(), g_chainman.m_blockman.LookupBlockIndex(block_hash));
|
assert(std::addressof(g_chainman) == std::addressof(*m_node.chainman));
|
||||||
|
return GuessVerificationProgress(Params().TxData(), m_node.chainman->m_blockman.LookupBlockIndex(block_hash));
|
||||||
}
|
}
|
||||||
bool hasBlocks(const uint256& block_hash, int min_height, Optional<int> max_height) override
|
bool hasBlocks(const uint256& block_hash, int min_height, Optional<int> max_height) override
|
||||||
{
|
{
|
||||||
@ -511,7 +528,8 @@ public:
|
|||||||
// used to limit the range, and passing min_height that's too low or
|
// used to limit the range, and passing min_height that's too low or
|
||||||
// max_height that's too high will not crash or change the result.
|
// max_height that's too high will not crash or change the result.
|
||||||
LOCK(::cs_main);
|
LOCK(::cs_main);
|
||||||
if (CBlockIndex* block = g_chainman.m_blockman.LookupBlockIndex(block_hash)) {
|
assert(std::addressof(g_chainman) == std::addressof(*m_node.chainman));
|
||||||
|
if (CBlockIndex* block = m_node.chainman->m_blockman.LookupBlockIndex(block_hash)) {
|
||||||
if (max_height && block->nHeight >= *max_height) block = block->GetAncestor(*max_height);
|
if (max_height && block->nHeight >= *max_height) block = block->GetAncestor(*max_height);
|
||||||
for (; block->nStatus & BLOCK_HAVE_DATA; block = block->pprev) {
|
for (; block->nStatus & BLOCK_HAVE_DATA; block = block->pprev) {
|
||||||
// Check pprev to not segfault if min_height is too low
|
// Check pprev to not segfault if min_height is too low
|
||||||
@ -601,7 +619,10 @@ public:
|
|||||||
return ::fHavePruned;
|
return ::fHavePruned;
|
||||||
}
|
}
|
||||||
bool isReadyToBroadcast() override { return !::fImporting && !::fReindex && !isInitialBlockDownload(); }
|
bool isReadyToBroadcast() override { return !::fImporting && !::fReindex && !isInitialBlockDownload(); }
|
||||||
bool isInitialBlockDownload() override { return ::ChainstateActive().IsInitialBlockDownload(); }
|
bool isInitialBlockDownload() override {
|
||||||
|
assert(std::addressof(::ChainstateActive()) == std::addressof(m_node.chainman->ActiveChainstate()));
|
||||||
|
return m_node.chainman->ActiveChainstate().IsInitialBlockDownload();
|
||||||
|
}
|
||||||
bool shutdownRequested() override { return ShutdownRequested(); }
|
bool shutdownRequested() override { return ShutdownRequested(); }
|
||||||
int64_t getAdjustedTime() override { return GetAdjustedTime(); }
|
int64_t getAdjustedTime() override { return GetAdjustedTime(); }
|
||||||
void initMessage(const std::string& message) override { ::uiInterface.InitMessage(message); }
|
void initMessage(const std::string& message) override { ::uiInterface.InitMessage(message); }
|
||||||
|
@ -39,9 +39,10 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t
|
|||||||
|
|
||||||
{ // cs_main scope
|
{ // cs_main scope
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
assert(std::addressof(::ChainstateActive()) == std::addressof(node.chainman->ActiveChainstate()));
|
||||||
// If the transaction is already confirmed in the chain, don't do anything
|
// If the transaction is already confirmed in the chain, don't do anything
|
||||||
// and return early.
|
// and return early.
|
||||||
CCoinsViewCache &view = ::ChainstateActive().CoinsTip();
|
CCoinsViewCache &view = node.chainman->ActiveChainstate().CoinsTip();
|
||||||
for (size_t o = 0; o < tx->vout.size(); o++) {
|
for (size_t o = 0; o < tx->vout.size(); o++) {
|
||||||
const Coin& existingCoin = view.AccessCoin(COutPoint(hashTx, o));
|
const Coin& existingCoin = view.AccessCoin(COutPoint(hashTx, o));
|
||||||
// IsSpent doesn't mean the coin is spent, it means the output doesn't exist.
|
// IsSpent doesn't mean the coin is spent, it means the output doesn't exist.
|
||||||
@ -53,7 +54,7 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t
|
|||||||
if (max_tx_fee > 0) {
|
if (max_tx_fee > 0) {
|
||||||
// First, call ATMP with test_accept and check the fee. If ATMP
|
// First, call ATMP with test_accept and check the fee. If ATMP
|
||||||
// fails here, return error immediately.
|
// fails here, return error immediately.
|
||||||
const MempoolAcceptResult result = AcceptToMemoryPool(::ChainstateActive(), *node.mempool, tx, false /* bypass_limits */,
|
const MempoolAcceptResult result = AcceptToMemoryPool(node.chainman->ActiveChainstate(), *node.mempool, tx, false /* bypass_limits */,
|
||||||
true /* test_accept */);
|
true /* test_accept */);
|
||||||
if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
|
if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
|
||||||
return HandleATMPError(result.m_state, err_string);
|
return HandleATMPError(result.m_state, err_string);
|
||||||
@ -62,7 +63,7 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Try to submit the transaction to the mempool.
|
// Try to submit the transaction to the mempool.
|
||||||
const MempoolAcceptResult result = AcceptToMemoryPool(::ChainstateActive(), *node.mempool, tx, false /* bypass_limits */,
|
const MempoolAcceptResult result = AcceptToMemoryPool(node.chainman->ActiveChainstate(), *node.mempool, tx, false /* bypass_limits */,
|
||||||
false /* test_accept */);
|
false /* test_accept */);
|
||||||
if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
|
if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
|
||||||
return HandleATMPError(result.m_state, err_string);
|
return HandleATMPError(result.m_state, err_string);
|
||||||
|
@ -1073,9 +1073,9 @@ static RPCHelpMan gettxoutsetinfo()
|
|||||||
|
|
||||||
const CoinStatsHashType hash_type{request.params[0].isNull() ? CoinStatsHashType::HASH_SERIALIZED : ParseHashType(request.params[0].get_str())};
|
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());
|
CCoinsView* coins_view = WITH_LOCK(::cs_main, return &::ChainstateActive().CoinsDB());
|
||||||
NodeContext& node = EnsureNodeContext(request.context);
|
NodeContext& node = EnsureNodeContext(request.context);
|
||||||
if (GetUTXOStats(coins_view, stats, hash_type, node.rpc_interruption_point)) {
|
if (GetUTXOStats(coins_view, WITH_LOCK(::cs_main, return std::ref(g_chainman.m_blockman)), stats, hash_type, node.rpc_interruption_point)) {
|
||||||
ret.pushKV("height", (int64_t)stats.nHeight);
|
ret.pushKV("height", (int64_t)stats.nHeight);
|
||||||
ret.pushKV("bestblock", stats.hashBlock.GetHex());
|
ret.pushKV("bestblock", stats.hashBlock.GetHex());
|
||||||
ret.pushKV("transactions", (int64_t)stats.nTransactions);
|
ret.pushKV("transactions", (int64_t)stats.nTransactions);
|
||||||
@ -2444,7 +2444,7 @@ UniValue CreateUTXOSnapshot(NodeContext& node, CChainState& chainstate, CAutoFil
|
|||||||
|
|
||||||
chainstate.ForceFlushStateToDisk();
|
chainstate.ForceFlushStateToDisk();
|
||||||
|
|
||||||
if (!GetUTXOStats(&chainstate.CoinsDB(), stats, CoinStatsHashType::NONE, node.rpc_interruption_point)) {
|
if (!GetUTXOStats(&chainstate.CoinsDB(), chainstate.m_blockman, stats, CoinStatsHashType::NONE, node.rpc_interruption_point)) {
|
||||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set");
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ static UniValue generateBlocks(ChainstateManager& chainman, const CTxMemPool& me
|
|||||||
UniValue blockHashes(UniValue::VARR);
|
UniValue blockHashes(UniValue::VARR);
|
||||||
while (nHeight < nHeightEnd && !ShutdownRequested())
|
while (nHeight < nHeightEnd && !ShutdownRequested())
|
||||||
{
|
{
|
||||||
std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(mempool, Params()).CreateNewBlock(coinbase_script));
|
std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(mempool, Params()).CreateNewBlock(::ChainstateActive(), coinbase_script));
|
||||||
if (!pblocktemplate.get())
|
if (!pblocktemplate.get())
|
||||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
|
||||||
CBlock *pblock = &pblocktemplate->block;
|
CBlock *pblock = &pblocktemplate->block;
|
||||||
@ -358,7 +358,7 @@ static RPCHelpMan generateblock()
|
|||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
CTxMemPool empty_mempool;
|
CTxMemPool empty_mempool;
|
||||||
std::unique_ptr<CBlockTemplate> blocktemplate(BlockAssembler(empty_mempool, chainparams).CreateNewBlock(coinbase_script));
|
std::unique_ptr<CBlockTemplate> blocktemplate(BlockAssembler(empty_mempool, chainparams).CreateNewBlock(::ChainstateActive(), coinbase_script));
|
||||||
if (!blocktemplate) {
|
if (!blocktemplate) {
|
||||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
|
||||||
}
|
}
|
||||||
@ -369,7 +369,7 @@ static RPCHelpMan generateblock()
|
|||||||
|
|
||||||
// Add transactions
|
// Add transactions
|
||||||
block.vtx.insert(block.vtx.end(), txs.begin(), txs.end());
|
block.vtx.insert(block.vtx.end(), txs.begin(), txs.end());
|
||||||
RegenerateCommitments(block);
|
RegenerateCommitments(block, WITH_LOCK(::cs_main, return std::ref(g_chainman.m_blockman)));
|
||||||
|
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
@ -747,7 +747,7 @@ static RPCHelpMan getblocktemplate()
|
|||||||
|
|
||||||
// Create new block
|
// Create new block
|
||||||
CScript scriptDummy = CScript() << OP_TRUE;
|
CScript scriptDummy = CScript() << OP_TRUE;
|
||||||
pblocktemplate = BlockAssembler(mempool, Params()).CreateNewBlock(scriptDummy);
|
pblocktemplate = BlockAssembler(mempool, Params()).CreateNewBlock(::ChainstateActive(), scriptDummy);
|
||||||
if (!pblocktemplate)
|
if (!pblocktemplate)
|
||||||
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
|
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ CBlock BuildChainTestingSetup::CreateBlock(const CBlockIndex* prev,
|
|||||||
const CScript& scriptPubKey)
|
const CScript& scriptPubKey)
|
||||||
{
|
{
|
||||||
const CChainParams& chainparams = Params();
|
const CChainParams& chainparams = Params();
|
||||||
std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(*m_node.mempool, chainparams).CreateNewBlock(scriptPubKey);
|
std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(*m_node.mempool, chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey);
|
||||||
CBlock& block = pblocktemplate->block;
|
CBlock& block = pblocktemplate->block;
|
||||||
block.hashPrevBlock = prev->GetBlockHash();
|
block.hashPrevBlock = prev->GetBlockHash();
|
||||||
block.nTime = prev->nTime + 1;
|
block.nTime = prev->nTime + 1;
|
||||||
|
@ -264,7 +264,7 @@ FUZZ_TARGET_INIT(coins_view, initialize_coins_view)
|
|||||||
CCoinsStats stats;
|
CCoinsStats stats;
|
||||||
bool expected_code_path = false;
|
bool expected_code_path = false;
|
||||||
try {
|
try {
|
||||||
(void)GetUTXOStats(&coins_view_cache, stats, CoinStatsHashType::HASH_SERIALIZED);
|
(void)GetUTXOStats(&coins_view_cache, WITH_LOCK(::cs_main, return std::ref(g_chainman.m_blockman)), stats, CoinStatsHashType::HASH_SERIALIZED);
|
||||||
} catch (const std::logic_error&) {
|
} catch (const std::logic_error&) {
|
||||||
expected_code_path = true;
|
expected_code_path = true;
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ void MinerTestingSetup::TestPackageSelection(const CChainParams& chainparams, co
|
|||||||
uint256 hashHighFeeTx = tx.GetHash();
|
uint256 hashHighFeeTx = tx.GetHash();
|
||||||
m_node.mempool->addUnchecked(entry.Fee(50000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
|
m_node.mempool->addUnchecked(entry.Fee(50000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
|
||||||
|
|
||||||
std::unique_ptr<CBlockTemplate> pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
|
std::unique_ptr<CBlockTemplate> pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey);
|
||||||
BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 4U);
|
BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 4U);
|
||||||
BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashParentTx);
|
BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashParentTx);
|
||||||
BOOST_CHECK(pblocktemplate->block.vtx[2]->GetHash() == hashHighFeeTx);
|
BOOST_CHECK(pblocktemplate->block.vtx[2]->GetHash() == hashHighFeeTx);
|
||||||
@ -143,7 +143,7 @@ void MinerTestingSetup::TestPackageSelection(const CChainParams& chainparams, co
|
|||||||
tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse;
|
tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse;
|
||||||
uint256 hashLowFeeTx = tx.GetHash();
|
uint256 hashLowFeeTx = tx.GetHash();
|
||||||
m_node.mempool->addUnchecked(entry.Fee(feeToUse).FromTx(tx));
|
m_node.mempool->addUnchecked(entry.Fee(feeToUse).FromTx(tx));
|
||||||
pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
|
pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey);
|
||||||
// Verify that the free tx and the low fee tx didn't get selected
|
// Verify that the free tx and the low fee tx didn't get selected
|
||||||
for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
|
for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
|
||||||
BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeTx);
|
BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeTx);
|
||||||
@ -157,7 +157,7 @@ void MinerTestingSetup::TestPackageSelection(const CChainParams& chainparams, co
|
|||||||
tx.vout[0].nValue -= 2; // Now we should be just over the min relay fee
|
tx.vout[0].nValue -= 2; // Now we should be just over the min relay fee
|
||||||
hashLowFeeTx = tx.GetHash();
|
hashLowFeeTx = tx.GetHash();
|
||||||
m_node.mempool->addUnchecked(entry.Fee(feeToUse+2).FromTx(tx));
|
m_node.mempool->addUnchecked(entry.Fee(feeToUse+2).FromTx(tx));
|
||||||
pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
|
pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey);
|
||||||
BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 6U);
|
BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 6U);
|
||||||
BOOST_CHECK(pblocktemplate->block.vtx[4]->GetHash() == hashFreeTx);
|
BOOST_CHECK(pblocktemplate->block.vtx[4]->GetHash() == hashFreeTx);
|
||||||
BOOST_CHECK(pblocktemplate->block.vtx[5]->GetHash() == hashLowFeeTx);
|
BOOST_CHECK(pblocktemplate->block.vtx[5]->GetHash() == hashLowFeeTx);
|
||||||
@ -179,7 +179,7 @@ void MinerTestingSetup::TestPackageSelection(const CChainParams& chainparams, co
|
|||||||
tx.vout[0].nValue = 5000000000LL - 100000000 - feeToUse;
|
tx.vout[0].nValue = 5000000000LL - 100000000 - feeToUse;
|
||||||
uint256 hashLowFeeTx2 = tx.GetHash();
|
uint256 hashLowFeeTx2 = tx.GetHash();
|
||||||
m_node.mempool->addUnchecked(entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx));
|
m_node.mempool->addUnchecked(entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx));
|
||||||
pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
|
pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey);
|
||||||
|
|
||||||
// Verify that this tx isn't selected.
|
// Verify that this tx isn't selected.
|
||||||
for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
|
for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
|
||||||
@ -192,7 +192,7 @@ void MinerTestingSetup::TestPackageSelection(const CChainParams& chainparams, co
|
|||||||
tx.vin[0].prevout.n = 1;
|
tx.vin[0].prevout.n = 1;
|
||||||
tx.vout[0].nValue = 100000000 - 10000; // 10k satoshi fee
|
tx.vout[0].nValue = 100000000 - 10000; // 10k satoshi fee
|
||||||
m_node.mempool->addUnchecked(entry.Fee(10000).FromTx(tx));
|
m_node.mempool->addUnchecked(entry.Fee(10000).FromTx(tx));
|
||||||
pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
|
pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey);
|
||||||
BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 9U);
|
BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 9U);
|
||||||
BOOST_CHECK(pblocktemplate->block.vtx[8]->GetHash() == hashLowFeeTx2);
|
BOOST_CHECK(pblocktemplate->block.vtx[8]->GetHash() == hashLowFeeTx2);
|
||||||
}
|
}
|
||||||
@ -215,7 +215,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||||||
fCheckpointsEnabled = false;
|
fCheckpointsEnabled = false;
|
||||||
|
|
||||||
// Simple block creation, nothing special yet:
|
// Simple block creation, nothing special yet:
|
||||||
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey));
|
||||||
|
|
||||||
// We can't make transactions until we have inputs
|
// We can't make transactions until we have inputs
|
||||||
// Therefore, load 110 blocks :)
|
// Therefore, load 110 blocks :)
|
||||||
@ -252,7 +252,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||||||
LOCK(m_node.mempool->cs);
|
LOCK(m_node.mempool->cs);
|
||||||
|
|
||||||
// Just to make sure we can still make simple blocks
|
// Just to make sure we can still make simple blocks
|
||||||
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey));
|
||||||
|
|
||||||
const CAmount BLOCKSUBSIDY = 50*COIN;
|
const CAmount BLOCKSUBSIDY = 50*COIN;
|
||||||
const CAmount LOWFEE = CENT;
|
const CAmount LOWFEE = CENT;
|
||||||
@ -277,7 +277,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||||||
tx.vin[0].prevout.hash = hash;
|
tx.vin[0].prevout.hash = hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-blk-sigops"));
|
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey), std::runtime_error, HasReason("bad-blk-sigops"));
|
||||||
m_node.mempool->clear();
|
m_node.mempool->clear();
|
||||||
|
|
||||||
tx.vin[0].prevout.hash = txFirst[0]->GetHash();
|
tx.vin[0].prevout.hash = txFirst[0]->GetHash();
|
||||||
@ -291,7 +291,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||||||
m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOpsCost(80).FromTx(tx));
|
m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOpsCost(80).FromTx(tx));
|
||||||
tx.vin[0].prevout.hash = hash;
|
tx.vin[0].prevout.hash = hash;
|
||||||
}
|
}
|
||||||
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey));
|
||||||
m_node.mempool->clear();
|
m_node.mempool->clear();
|
||||||
|
|
||||||
// block size > limit
|
// block size > limit
|
||||||
@ -311,13 +311,13 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||||||
m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
|
m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
|
||||||
tx.vin[0].prevout.hash = hash;
|
tx.vin[0].prevout.hash = hash;
|
||||||
}
|
}
|
||||||
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey));
|
||||||
m_node.mempool->clear();
|
m_node.mempool->clear();
|
||||||
|
|
||||||
// orphan in *m_node.mempool, template creation fails
|
// orphan in *m_node.mempool, template creation fails
|
||||||
hash = tx.GetHash();
|
hash = tx.GetHash();
|
||||||
m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).FromTx(tx));
|
m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).FromTx(tx));
|
||||||
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
|
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
|
||||||
m_node.mempool->clear();
|
m_node.mempool->clear();
|
||||||
|
|
||||||
// child with higher feerate than parent
|
// child with higher feerate than parent
|
||||||
@ -334,7 +334,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||||||
tx.vout[0].nValue = tx.vout[0].nValue+BLOCKSUBSIDY-HIGHERFEE; //First txn output + fresh coinbase - new txn fee
|
tx.vout[0].nValue = tx.vout[0].nValue+BLOCKSUBSIDY-HIGHERFEE; //First txn output + fresh coinbase - new txn fee
|
||||||
hash = tx.GetHash();
|
hash = tx.GetHash();
|
||||||
m_node.mempool->addUnchecked(entry.Fee(HIGHERFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
|
m_node.mempool->addUnchecked(entry.Fee(HIGHERFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
|
||||||
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey));
|
||||||
m_node.mempool->clear();
|
m_node.mempool->clear();
|
||||||
|
|
||||||
// coinbase in *m_node.mempool, template creation fails
|
// coinbase in *m_node.mempool, template creation fails
|
||||||
@ -346,7 +346,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||||||
// give it a fee so it'll get mined
|
// give it a fee so it'll get mined
|
||||||
m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
|
m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
|
||||||
// Should throw bad-cb-multiple
|
// Should throw bad-cb-multiple
|
||||||
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-cb-multiple"));
|
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey), std::runtime_error, HasReason("bad-cb-multiple"));
|
||||||
m_node.mempool->clear();
|
m_node.mempool->clear();
|
||||||
|
|
||||||
// double spend txn pair in *m_node.mempool, template creation fails
|
// double spend txn pair in *m_node.mempool, template creation fails
|
||||||
@ -359,7 +359,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||||||
tx.vout[0].scriptPubKey = CScript() << OP_2;
|
tx.vout[0].scriptPubKey = CScript() << OP_2;
|
||||||
hash = tx.GetHash();
|
hash = tx.GetHash();
|
||||||
m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
|
m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
|
||||||
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
|
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
|
||||||
m_node.mempool->clear();
|
m_node.mempool->clear();
|
||||||
|
|
||||||
// subsidy changing
|
// subsidy changing
|
||||||
@ -375,7 +375,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||||||
next->BuildSkip();
|
next->BuildSkip();
|
||||||
::ChainActive().SetTip(next);
|
::ChainActive().SetTip(next);
|
||||||
}
|
}
|
||||||
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey));
|
||||||
// Extend to a 210000-long block chain.
|
// Extend to a 210000-long block chain.
|
||||||
while (::ChainActive().Tip()->nHeight < 210000) {
|
while (::ChainActive().Tip()->nHeight < 210000) {
|
||||||
CBlockIndex* prev = ::ChainActive().Tip();
|
CBlockIndex* prev = ::ChainActive().Tip();
|
||||||
@ -387,7 +387,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||||||
next->BuildSkip();
|
next->BuildSkip();
|
||||||
::ChainActive().SetTip(next);
|
::ChainActive().SetTip(next);
|
||||||
}
|
}
|
||||||
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey));
|
||||||
|
|
||||||
// invalid p2sh txn in *m_node.mempool, template creation fails
|
// invalid p2sh txn in *m_node.mempool, template creation fails
|
||||||
tx.vin[0].prevout.hash = txFirst[0]->GetHash();
|
tx.vin[0].prevout.hash = txFirst[0]->GetHash();
|
||||||
@ -404,7 +404,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||||||
hash = tx.GetHash();
|
hash = tx.GetHash();
|
||||||
m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
|
m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
|
||||||
// Should throw block-validation-failed
|
// Should throw block-validation-failed
|
||||||
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("block-validation-failed"));
|
BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey), std::runtime_error, HasReason("block-validation-failed"));
|
||||||
m_node.mempool->clear();
|
m_node.mempool->clear();
|
||||||
|
|
||||||
// Delete the dummy blocks again.
|
// Delete the dummy blocks again.
|
||||||
@ -492,7 +492,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||||||
tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | 1;
|
tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | 1;
|
||||||
BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
|
BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
|
||||||
|
|
||||||
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey));
|
||||||
|
|
||||||
// None of the of the absolute height/time locked tx should have made
|
// None of the of the absolute height/time locked tx should have made
|
||||||
// it into the template because we still check IsFinalTx in CreateNewBlock,
|
// it into the template because we still check IsFinalTx in CreateNewBlock,
|
||||||
@ -505,7 +505,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||||||
::ChainActive().Tip()->nHeight++;
|
::ChainActive().Tip()->nHeight++;
|
||||||
SetMockTime(::ChainActive().Tip()->GetMedianTimePast() + 1);
|
SetMockTime(::ChainActive().Tip()->GetMedianTimePast() + 1);
|
||||||
|
|
||||||
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
|
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey));
|
||||||
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5U);
|
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5U);
|
||||||
|
|
||||||
::ChainActive().Tip()->nHeight--;
|
::ChainActive().Tip()->nHeight--;
|
||||||
|
@ -42,7 +42,7 @@ std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coi
|
|||||||
{
|
{
|
||||||
auto block = std::make_shared<CBlock>(
|
auto block = std::make_shared<CBlock>(
|
||||||
BlockAssembler{*Assert(node.mempool), Params()}
|
BlockAssembler{*Assert(node.mempool), Params()}
|
||||||
.CreateNewBlock(coinbase_scriptPubKey)
|
.CreateNewBlock(::ChainstateActive(), coinbase_scriptPubKey)
|
||||||
->block);
|
->block);
|
||||||
|
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
@ -245,13 +245,13 @@ CBlock TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransa
|
|||||||
{
|
{
|
||||||
const CChainParams& chainparams = Params();
|
const CChainParams& chainparams = Params();
|
||||||
CTxMemPool empty_pool;
|
CTxMemPool empty_pool;
|
||||||
CBlock block = BlockAssembler(empty_pool, chainparams).CreateNewBlock(scriptPubKey)->block;
|
CBlock block = BlockAssembler(empty_pool, chainparams).CreateNewBlock(::ChainstateActive(), scriptPubKey)->block;
|
||||||
|
|
||||||
Assert(block.vtx.size() == 1);
|
Assert(block.vtx.size() == 1);
|
||||||
for (const CMutableTransaction& tx : txns) {
|
for (const CMutableTransaction& tx : txns) {
|
||||||
block.vtx.push_back(MakeTransactionRef(tx));
|
block.vtx.push_back(MakeTransactionRef(tx));
|
||||||
}
|
}
|
||||||
RegenerateCommitments(block);
|
RegenerateCommitments(block, WITH_LOCK(::cs_main, return std::ref(g_chainman.m_blockman)));
|
||||||
|
|
||||||
while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
|
while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ std::shared_ptr<CBlock> MinerTestingSetup::Block(const uint256& prev_hash)
|
|||||||
static int i = 0;
|
static int i = 0;
|
||||||
static uint64_t time = Params().GenesisBlock().nTime;
|
static uint64_t time = Params().GenesisBlock().nTime;
|
||||||
|
|
||||||
auto ptemplate = BlockAssembler(*m_node.mempool, Params()).CreateNewBlock(CScript{} << i++ << OP_TRUE);
|
auto ptemplate = BlockAssembler(*m_node.mempool, Params()).CreateNewBlock(::ChainstateActive(), CScript{} << i++ << OP_TRUE);
|
||||||
auto pblock = std::make_shared<CBlock>(ptemplate->block);
|
auto pblock = std::make_shared<CBlock>(ptemplate->block);
|
||||||
pblock->hashPrevBlock = prev_hash;
|
pblock->hashPrevBlock = prev_hash;
|
||||||
pblock->nTime = ++time;
|
pblock->nTime = ++time;
|
||||||
@ -325,7 +325,7 @@ BOOST_AUTO_TEST_CASE(witness_commitment_index)
|
|||||||
{
|
{
|
||||||
CScript pubKey;
|
CScript pubKey;
|
||||||
pubKey << 1 << OP_TRUE;
|
pubKey << 1 << OP_TRUE;
|
||||||
auto ptemplate = BlockAssembler(*m_node.mempool, Params()).CreateNewBlock(pubKey);
|
auto ptemplate = BlockAssembler(*m_node.mempool, Params()).CreateNewBlock(::ChainstateActive(), pubKey);
|
||||||
CBlock pblock = ptemplate->block;
|
CBlock pblock = ptemplate->block;
|
||||||
|
|
||||||
CTxOut witness;
|
CTxOut witness;
|
||||||
|
@ -5425,7 +5425,7 @@ bool ChainstateManager::PopulateAndValidateSnapshot(
|
|||||||
// about the snapshot_chainstate.
|
// about the snapshot_chainstate.
|
||||||
CCoinsViewDB* snapshot_coinsdb = WITH_LOCK(::cs_main, return &snapshot_chainstate.CoinsDB());
|
CCoinsViewDB* snapshot_coinsdb = WITH_LOCK(::cs_main, return &snapshot_chainstate.CoinsDB());
|
||||||
|
|
||||||
if (!GetUTXOStats(snapshot_coinsdb, stats, CoinStatsHashType::HASH_SERIALIZED, breakpoint_fnc)) {
|
if (!GetUTXOStats(snapshot_coinsdb, WITH_LOCK(::cs_main, return std::ref(m_blockman)), stats, CoinStatsHashType::HASH_SERIALIZED, breakpoint_fnc)) {
|
||||||
LogPrintf("[snapshot] failed to generate coins stats\n");
|
LogPrintf("[snapshot] failed to generate coins stats\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -148,8 +148,6 @@ extern const std::vector<std::string> CHECKLEVEL_DOC;
|
|||||||
FILE* OpenBlockFile(const FlatFilePos &pos, bool fReadOnly = false);
|
FILE* OpenBlockFile(const FlatFilePos &pos, bool fReadOnly = false);
|
||||||
/** Translation to a filesystem path */
|
/** Translation to a filesystem path */
|
||||||
fs::path GetBlockPosFilename(const FlatFilePos &pos);
|
fs::path GetBlockPosFilename(const FlatFilePos &pos);
|
||||||
/** Ensures we have a genesis block in the block tree, possibly writing one to disk. */
|
|
||||||
bool LoadGenesisBlock(const CChainParams& chainparams);
|
|
||||||
/** Unload database information */
|
/** Unload database information */
|
||||||
void UnloadBlockIndex(CTxMemPool* mempool, ChainstateManager& chainman);
|
void UnloadBlockIndex(CTxMemPool* mempool, ChainstateManager& chainman);
|
||||||
/** Run instances of script checking worker threads */
|
/** Run instances of script checking worker threads */
|
||||||
@ -725,6 +723,7 @@ public:
|
|||||||
/** Replay blocks that aren't fully applied to the database. */
|
/** Replay blocks that aren't fully applied to the database. */
|
||||||
bool ReplayBlocks(const CChainParams& params);
|
bool ReplayBlocks(const CChainParams& params);
|
||||||
bool RewindBlockIndex(const CChainParams& params) LOCKS_EXCLUDED(cs_main);
|
bool RewindBlockIndex(const CChainParams& params) LOCKS_EXCLUDED(cs_main);
|
||||||
|
/** Ensures we have a genesis block in the block tree, possibly writing one to disk. */
|
||||||
bool LoadGenesisBlock(const CChainParams& chainparams);
|
bool LoadGenesisBlock(const CChainParams& chainparams);
|
||||||
|
|
||||||
void PruneBlockIndexCandidates();
|
void PruneBlockIndexCandidates();
|
||||||
|
Loading…
Reference in New Issue
Block a user