Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
// Copyright (c) 2009-2010 Satoshi Nakamoto | // Copyright (c) 2009-2010 Satoshi Nakamoto | ||||
// Copyright (c) 2009-2018 The Bitcoin Core developers | // Copyright (c) 2009-2018 The Bitcoin Core developers | ||||
// Copyright (c) 2017-2020 The Bitcoin developers | // Copyright (c) 2017-2020 The Bitcoin developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <validation.h> | #include <validation.h> | ||||
#include <arith_uint256.h> | #include <arith_uint256.h> | ||||
#include <avalanche/avalanche.h> | #include <avalanche/avalanche.h> | ||||
#include <avalanche/postconsensus.h> | |||||
#include <avalanche/processor.h> | #include <avalanche/processor.h> | ||||
#include <blockvalidity.h> | #include <blockvalidity.h> | ||||
#include <chainparams.h> | #include <chainparams.h> | ||||
#include <checkpoints.h> | #include <checkpoints.h> | ||||
#include <checkqueue.h> | #include <checkqueue.h> | ||||
#include <config.h> | #include <config.h> | ||||
#include <consensus/activation.h> | #include <consensus/activation.h> | ||||
#include <consensus/amount.h> | #include <consensus/amount.h> | ||||
▲ Show 20 Lines • Show All 4,226 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 | ||||
* @param[in,out] fNewBlock True if block was first received via this call. | * block. | ||||
* @param[in,out] fNewBlock True if block was first received via | |||||
* this call. | |||||
* @param[in] fPostConsensusActive A boolean to indicate if Avalanche | |||||
* post-consensus voting is currently | |||||
* active. | |||||
* @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 fPostConsensusActive) { | |||||
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(); | ||||
m_blockman.m_dirty_blockindex.insert(pindex); | m_blockman.m_dirty_blockindex.insert(pindex); | ||||
} | } | ||||
} | } | ||||
// Apply Avalanche post-consensus policies if voting is active | |||||
if (fPostConsensusActive && avalanche::isEarlyBlockPenaltyEnabled(gArgs) && | |||||
pindex->pprev) { | |||||
const CBlockIndex *parent = pindex->pprev; | |||||
const int64_t timeDiff = | |||||
pindex->nTimeReceived >= parent->nTimeReceived | |||||
? pindex->nTimeReceived - parent->nTimeReceived | |||||
: 0; | |||||
const int64_t penaltyWindow = | |||||
avalanche::getEarlyBlockPenaltyWindow(gArgs, m_params); | |||||
if (timeDiff < penaltyWindow) { | |||||
const int64_t penaltyFactor = | |||||
avalanche::getEarlyBlockPenaltyFactor(gArgs, m_params); | |||||
const CBlockHeader header = pindex->GetBlockHeader(); | |||||
LogPrint(BCLog::AVALANCHE, | |||||
"Early block hash: %s, parentTime: %d, receivedTime: %d, " | |||||
"timeDiff: %d\n", | |||||
header.GetHash().ToString(), parent->nTimeReceived, | |||||
pindex->nTimeReceived, timeDiff); | |||||
arith_uint256 target; | |||||
bool negative; | |||||
bool overflow; | |||||
const uint32_t powRequired = | |||||
GetNextWorkRequired(parent, &header, m_params); | |||||
target.SetCompact(powRequired, &negative, &overflow); | |||||
const arith_uint256 oldTarget = target; | |||||
target /= penaltyFactor; | |||||
const uint32_t newPowLimit = target.GetCompact(negative); | |||||
LogPrint(BCLog::AVALANCHE, | |||||
"Early block targets: oldTarget: %s, oldPowLimit: 0x%.8x, " | |||||
"newTarget: %s, newPowLimit: 0x%.8x\n", | |||||
oldTarget.ToString(), powRequired, target.ToString(), | |||||
newPowLimit); | |||||
if (!CheckProofOfWork(header.GetHash(), newPowLimit, | |||||
consensusParams)) { | |||||
// Mark this block as parked | |||||
pindex->nStatus = pindex->nStatus.withParked(); | |||||
m_blockman.m_dirty_blockindex.insert(pindex); | |||||
LogPrint(BCLog::AVALANCHE, | |||||
"Early block rejected due to PoW penalty: %s\n", | |||||
header.GetHash().ToString()); | |||||
} else { | |||||
LogPrint(BCLog::AVALANCHE, "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 postConsensusActive = | |||||
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, force_processing, nullptr, new_block); | config, block, state, force_processing, nullptr, new_block, | ||||
postConsensusActive); | |||||
} | } | ||||
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 1,667 Lines • Show Last 20 Lines |