Use equivalent PoW for non-main-chain requests
This commit is contained in:
parent
b6ea3bcede
commit
f7303f9793
4 changed files with 49 additions and 4 deletions
|
@ -3459,7 +3459,6 @@ bool static AlreadyHave(const CInv& inv)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void static ProcessGetData(CNode* pfrom)
|
void static ProcessGetData(CNode* pfrom)
|
||||||
{
|
{
|
||||||
std::deque<CInv>::iterator it = pfrom->vRecvGetData.begin();
|
std::deque<CInv>::iterator it = pfrom->vRecvGetData.begin();
|
||||||
|
@ -3487,11 +3486,13 @@ void static ProcessGetData(CNode* pfrom)
|
||||||
if (chainActive.Contains(mi->second)) {
|
if (chainActive.Contains(mi->second)) {
|
||||||
send = true;
|
send = true;
|
||||||
} else {
|
} else {
|
||||||
|
static const int nOneMonth = 30 * 24 * 60 * 60;
|
||||||
// To prevent fingerprinting attacks, only send blocks outside of the active
|
// To prevent fingerprinting attacks, only send blocks outside of the active
|
||||||
// chain if they are valid, and no more than a month older than the best header
|
// chain if they are valid, and no more than a month older (both in time, and in
|
||||||
// chain we know about.
|
// best equivalent proof of work) than the best header chain we know about.
|
||||||
send = mi->second->IsValid(BLOCK_VALID_SCRIPTS) && (pindexBestHeader != NULL) &&
|
send = mi->second->IsValid(BLOCK_VALID_SCRIPTS) && (pindexBestHeader != NULL) &&
|
||||||
(mi->second->GetBlockTime() > pindexBestHeader->GetBlockTime() - 30 * 24 * 60 * 60);
|
(pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() < nOneMonth) &&
|
||||||
|
(GetBlockProofEquivalentTime(*pindexBestHeader, *mi->second, *pindexBestHeader, Params().GetConsensus()) < nOneMonth);
|
||||||
if (!send) {
|
if (!send) {
|
||||||
LogPrintf("%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom->GetId());
|
LogPrintf("%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom->GetId());
|
||||||
}
|
}
|
||||||
|
|
17
src/pow.cpp
17
src/pow.cpp
|
@ -114,3 +114,20 @@ arith_uint256 GetBlockProof(const CBlockIndex& block)
|
||||||
// or ~bnTarget / (nTarget+1) + 1.
|
// or ~bnTarget / (nTarget+1) + 1.
|
||||||
return (~bnTarget / (bnTarget + 1)) + 1;
|
return (~bnTarget / (bnTarget + 1)) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params& params)
|
||||||
|
{
|
||||||
|
arith_uint256 r;
|
||||||
|
int sign = 1;
|
||||||
|
if (to.nChainWork > from.nChainWork) {
|
||||||
|
r = to.nChainWork - from.nChainWork;
|
||||||
|
} else {
|
||||||
|
r = from.nChainWork - to.nChainWork;
|
||||||
|
sign = -1;
|
||||||
|
}
|
||||||
|
r = r * arith_uint256(params.nPowTargetSpacing) / GetBlockProof(tip);
|
||||||
|
if (r.bits() > 63) {
|
||||||
|
return sign * std::numeric_limits<int64_t>::max();
|
||||||
|
}
|
||||||
|
return sign * r.GetLow64();
|
||||||
|
}
|
||||||
|
|
|
@ -22,4 +22,7 @@ unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nF
|
||||||
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&);
|
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&);
|
||||||
arith_uint256 GetBlockProof(const CBlockIndex& block);
|
arith_uint256 GetBlockProof(const CBlockIndex& block);
|
||||||
|
|
||||||
|
/** Return the time it would take to redo the work difference between from and to, assuming the current hashrate corresponds to the difficulty at tip, in seconds. */
|
||||||
|
int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params&);
|
||||||
|
|
||||||
#endif // BITCOIN_POW_H
|
#endif // BITCOIN_POW_H
|
||||||
|
|
|
@ -69,4 +69,28 @@ BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual)
|
||||||
BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), 0x1d00e1fd);
|
BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), 0x1d00e1fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test)
|
||||||
|
{
|
||||||
|
SelectParams(CBaseChainParams::MAIN);
|
||||||
|
const Consensus::Params& params = Params().GetConsensus();
|
||||||
|
|
||||||
|
std::vector<CBlockIndex> blocks(10000);
|
||||||
|
for (int i = 0; i < 10000; i++) {
|
||||||
|
blocks[i].pprev = i ? &blocks[i - 1] : NULL;
|
||||||
|
blocks[i].nHeight = i;
|
||||||
|
blocks[i].nTime = 1269211443 + i * params.nPowTargetSpacing;
|
||||||
|
blocks[i].nBits = 0x207fffff; /* target 0x7fffff000... */
|
||||||
|
blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + GetBlockProof(blocks[i - 1]) : arith_uint256(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < 1000; j++) {
|
||||||
|
CBlockIndex *p1 = &blocks[GetRand(10000)];
|
||||||
|
CBlockIndex *p2 = &blocks[GetRand(10000)];
|
||||||
|
CBlockIndex *p3 = &blocks[GetRand(10000)];
|
||||||
|
|
||||||
|
int64_t tdiff = GetBlockProofEquivalentTime(*p1, *p2, *p3, params);
|
||||||
|
BOOST_CHECK_EQUAL(tdiff, p1->GetBlockTime() - p2->GetBlockTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
Loading…
Reference in a new issue