Skip to content

Commit f7303f9

Browse files
committed
Use equivalent PoW for non-main-chain requests
1 parent b6ea3bc commit f7303f9

File tree

4 files changed

+49
-4
lines changed

4 files changed

+49
-4
lines changed

src/main.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3459,7 +3459,6 @@ bool static AlreadyHave(const CInv& inv)
34593459
return true;
34603460
}
34613461

3462-
34633462
void static ProcessGetData(CNode* pfrom)
34643463
{
34653464
std::deque<CInv>::iterator it = pfrom->vRecvGetData.begin();
@@ -3487,11 +3486,13 @@ void static ProcessGetData(CNode* pfrom)
34873486
if (chainActive.Contains(mi->second)) {
34883487
send = true;
34893488
} else {
3489+
static const int nOneMonth = 30 * 24 * 60 * 60;
34903490
// To prevent fingerprinting attacks, only send blocks outside of the active
3491-
// chain if they are valid, and no more than a month older than the best header
3492-
// chain we know about.
3491+
// chain if they are valid, and no more than a month older (both in time, and in
3492+
// best equivalent proof of work) than the best header chain we know about.
34933493
send = mi->second->IsValid(BLOCK_VALID_SCRIPTS) && (pindexBestHeader != NULL) &&
3494-
(mi->second->GetBlockTime() > pindexBestHeader->GetBlockTime() - 30 * 24 * 60 * 60);
3494+
(pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() < nOneMonth) &&
3495+
(GetBlockProofEquivalentTime(*pindexBestHeader, *mi->second, *pindexBestHeader, Params().GetConsensus()) < nOneMonth);
34953496
if (!send) {
34963497
LogPrintf("%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom->GetId());
34973498
}

src/pow.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,20 @@ arith_uint256 GetBlockProof(const CBlockIndex& block)
114114
// or ~bnTarget / (nTarget+1) + 1.
115115
return (~bnTarget / (bnTarget + 1)) + 1;
116116
}
117+
118+
int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params& params)
119+
{
120+
arith_uint256 r;
121+
int sign = 1;
122+
if (to.nChainWork > from.nChainWork) {
123+
r = to.nChainWork - from.nChainWork;
124+
} else {
125+
r = from.nChainWork - to.nChainWork;
126+
sign = -1;
127+
}
128+
r = r * arith_uint256(params.nPowTargetSpacing) / GetBlockProof(tip);
129+
if (r.bits() > 63) {
130+
return sign * std::numeric_limits<int64_t>::max();
131+
}
132+
return sign * r.GetLow64();
133+
}

src/pow.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,7 @@ unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nF
2222
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&);
2323
arith_uint256 GetBlockProof(const CBlockIndex& block);
2424

25+
/** 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. */
26+
int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params&);
27+
2528
#endif // BITCOIN_POW_H

src/test/pow_tests.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,28 @@ BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual)
6969
BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), 0x1d00e1fd);
7070
}
7171

72+
BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test)
73+
{
74+
SelectParams(CBaseChainParams::MAIN);
75+
const Consensus::Params& params = Params().GetConsensus();
76+
77+
std::vector<CBlockIndex> blocks(10000);
78+
for (int i = 0; i < 10000; i++) {
79+
blocks[i].pprev = i ? &blocks[i - 1] : NULL;
80+
blocks[i].nHeight = i;
81+
blocks[i].nTime = 1269211443 + i * params.nPowTargetSpacing;
82+
blocks[i].nBits = 0x207fffff; /* target 0x7fffff000... */
83+
blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + GetBlockProof(blocks[i - 1]) : arith_uint256(0);
84+
}
85+
86+
for (int j = 0; j < 1000; j++) {
87+
CBlockIndex *p1 = &blocks[GetRand(10000)];
88+
CBlockIndex *p2 = &blocks[GetRand(10000)];
89+
CBlockIndex *p3 = &blocks[GetRand(10000)];
90+
91+
int64_t tdiff = GetBlockProofEquivalentTime(*p1, *p2, *p3, params);
92+
BOOST_CHECK_EQUAL(tdiff, p1->GetBlockTime() - p2->GetBlockTime());
93+
}
94+
}
95+
7296
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)