Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 4,092 Lines • ▼ Show 20 Lines | if (NotifyHeaderTip(ActiveChainstate())) { | ||||
} | } | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
/** | /** | ||||
* Store a block on disk. | * Store a block on disk. | ||||
* | * | ||||
* @param[in] config The global config. | * @param[in] config The global config. | ||||
* @param[in,out] pblock The block we want to accept. | * @param[in,out] pblock The block we want to accept. | ||||
* @param[in] fRequested A boolean to indicate if this block was requested | * @param[in] fRequested A boolean to indicate if this block was | ||||
* from our peers. | * requested from our peers. | ||||
* @param[in] dbp If non-null, the disk position of the block. | * @param[in] dbp If non-null, the disk position of the block. | ||||
* @param[in,out] fNewBlock True if block was first received via this call. | * @param[in,out] fNewBlock True if block was first received via this call. | ||||
* @param[in] fPostConsensus A boolean to indicate if Avalanche | |||||
* post-consensus rules should be applied. | |||||
* @return True if the block is accepted as a valid block and written to disk. | * @return True if the block is accepted as a valid block and written to disk. | ||||
*/ | */ | ||||
bool CChainState::AcceptBlock(const Config &config, | bool CChainState::AcceptBlock(const Config &config, | ||||
const std::shared_ptr<const CBlock> &pblock, | const std::shared_ptr<const CBlock> &pblock, | ||||
BlockValidationState &state, bool fRequested, | BlockValidationState &state, bool fRequested, | ||||
const FlatFilePos *dbp, bool *fNewBlock) { | const FlatFilePos *dbp, bool *fNewBlock, | ||||
bool fPostConsensus) { | |||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
const CBlock &block = *pblock; | const CBlock &block = *pblock; | ||||
if (fNewBlock) { | if (fNewBlock) { | ||||
*fNewBlock = false; | *fNewBlock = false; | ||||
} | } | ||||
CBlockIndex *pindex = nullptr; | CBlockIndex *pindex = nullptr; | ||||
▲ Show 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | if (gArgs.GetBoolArg("-parkdeepreorg", true)) { | ||||
if (pindexFork && pindexFork->nHeight + 1 < m_chain.Height()) { | if (pindexFork && pindexFork->nHeight + 1 < m_chain.Height()) { | ||||
LogPrintf("Park block %s as it would cause a deep reorg.\n", | LogPrintf("Park block %s as it would cause a deep reorg.\n", | ||||
pindex->GetBlockHash().ToString()); | pindex->GetBlockHash().ToString()); | ||||
pindex->nStatus = pindex->nStatus.withParked(); | pindex->nStatus = pindex->nStatus.withParked(); | ||||
setDirtyBlockIndex.insert(pindex); | setDirtyBlockIndex.insert(pindex); | ||||
} | } | ||||
} | } | ||||
// Avalanche post-consensus rules | |||||
if (fPostConsensus && pindex->pprev && !IsBlockAvalancheFinalized(pindex)) { | |||||
const CBlockIndex *parent = pindex->pprev; | |||||
const int64_t timeDiff = | |||||
pindex->nTimeReceived >= parent->nTimeReceived | |||||
? pindex->nTimeReceived - parent->nTimeReceived | |||||
: 0; | |||||
if (timeDiff < consensusParams.earlyBlockPowTargetPenaltyWindow) { | |||||
const CBlockHeader header = pindex->GetBlockHeader(); | |||||
LogPrintf("Early block hash: %s, parentTime: %d, receivedTime: %d, " | |||||
"timeDiff: %d\n", | |||||
header.GetHash().ToString(), parent->nTimeReceived, | |||||
pindex->nTimeReceived, timeDiff); | |||||
arith_uint256 target; | |||||
arith_uint256 oldTarget; | |||||
bool negative; | |||||
bool overflow; | |||||
uint32_t powRequired = | |||||
GetNextWorkRequired(parent, &header, m_params); | |||||
target.SetCompact(powRequired, &negative, &overflow); | |||||
oldTarget = target; | |||||
target *= consensusParams.earlyBlockPowTargetPenaltyWindow; | |||||
target /= (1 - consensusParams.earlyBlockPowTargetPenaltyFactor) * | |||||
timeDiff + | |||||
consensusParams.earlyBlockPowTargetPenaltyFactor * | |||||
consensusParams.earlyBlockPowTargetPenaltyWindow; | |||||
const uint32_t newPowLimit = target.GetCompact(negative); | |||||
LogPrintf("Early block:\n" | |||||
"oldTarget: %s, oldPowLimit: 0x%.8x\n" | |||||
"newTarget: %s, newPowLimit: 0x%.8x\n", | |||||
oldTarget.ToString(), powRequired, target.ToString(), | |||||
newPowLimit); | |||||
if (!CheckProofOfWork(header.GetHash(), newPowLimit, | |||||
consensusParams)) { | |||||
// Mark this block as parked | |||||
/*BlockValidationState state; | |||||
UpdateFlagsForBlock(nullptr, pindex, | |||||
[](const BlockStatus status) { | |||||
return status.withParked(); | |||||
});*/ | |||||
pindex->nStatus = pindex->nStatus.withParked(); | |||||
setDirtyBlockIndex.insert(pindex); | |||||
LogPrintf("Early block rejected due to PoW " | |||||
"penalty: %s\n", | |||||
header.GetHash().ToString()); | |||||
} else { | |||||
LogPrintf("Early block accepted: %s\n", | |||||
header.GetHash().ToString()); | |||||
} | |||||
} | |||||
} | |||||
// Header is valid/has work and the merkle tree is good. | // Header is valid/has work and the merkle tree is good. | ||||
// Relay now, but if it does not build on our best tip, let the | // Relay now, but if it does not build on our best tip, let the | ||||
// SendMessages loop relay it. | // SendMessages loop relay it. | ||||
if (!IsInitialBlockDownload() && m_chain.Tip() == pindex->pprev) { | if (!IsInitialBlockDownload() && m_chain.Tip() == pindex->pprev) { | ||||
GetMainSignals().NewPoWValidBlock(pindex, pblock); | GetMainSignals().NewPoWValidBlock(pindex, pblock); | ||||
} | } | ||||
// Write block to history file | // Write block to history file | ||||
Show All 21 Lines | bool CChainState::AcceptBlock(const Config &config, | ||||
return true; | return true; | ||||
} | } | ||||
bool ChainstateManager::ProcessNewBlock( | bool ChainstateManager::ProcessNewBlock( | ||||
const Config &config, const std::shared_ptr<const CBlock> &block, | const Config &config, const std::shared_ptr<const CBlock> &block, | ||||
bool force_processing, bool *new_block) { | bool force_processing, bool *new_block) { | ||||
AssertLockNotHeld(cs_main); | AssertLockNotHeld(cs_main); | ||||
bool applyPostConsensus = g_avalanche && g_avalanche->isQuorumEstablished(); | |||||
{ | { | ||||
if (new_block) { | if (new_block) { | ||||
*new_block = false; | *new_block = false; | ||||
} | } | ||||
BlockValidationState state; | BlockValidationState state; | ||||
// CheckBlock() does not support multi-threaded block validation | // CheckBlock() does not support multi-threaded block validation | ||||
// because CBlock::fChecked can cause data race. | // because CBlock::fChecked can cause data race. | ||||
// Therefore, the following critical section must include the | // Therefore, the following critical section must include the | ||||
// CheckBlock() call as well. | // CheckBlock() call as well. | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
// Ensure that CheckBlock() passes before calling AcceptBlock, as | // Ensure that CheckBlock() passes before calling AcceptBlock, as | ||||
// belt-and-suspenders. | // belt-and-suspenders. | ||||
bool ret = | bool ret = | ||||
CheckBlock(*block, state, config.GetChainParams().GetConsensus(), | CheckBlock(*block, state, config.GetChainParams().GetConsensus(), | ||||
BlockValidationOptions(config)); | BlockValidationOptions(config)); | ||||
if (ret) { | if (ret) { | ||||
// Store to disk | // Store to disk | ||||
ret = ActiveChainstate().AcceptBlock( | ret = ActiveChainstate().AcceptBlock(config, block, state, | ||||
config, block, state, force_processing, nullptr, new_block); | force_processing, nullptr, | ||||
new_block, applyPostConsensus); | |||||
} | } | ||||
if (!ret) { | if (!ret) { | ||||
GetMainSignals().BlockChecked(*block, state); | GetMainSignals().BlockChecked(*block, state); | ||||
return error("%s: AcceptBlock FAILED (%s)", __func__, | return error("%s: AcceptBlock FAILED (%s)", __func__, | ||||
state.ToString()); | state.ToString()); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 2,022 Lines • Show Last 20 Lines |