Skip to content

Commit

Permalink
Merge pull request zcash#5918
Browse files Browse the repository at this point in the history
f7303f9 Use equivalent PoW for non-main-chain requests (Pieter Wuille)
  • Loading branch information
sipa committed Apr 28, 2015
2 parents 9e06be2 + f7303f9 commit 7bf5d5e
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 4 deletions.
9 changes: 5 additions & 4 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3675,7 +3675,6 @@ bool static AlreadyHave(const CInv& inv)
return true;
}


void static ProcessGetData(CNode* pfrom)
{
std::deque<CInv>::iterator it = pfrom->vRecvGetData.begin();
Expand Down Expand Up @@ -3703,11 +3702,13 @@ void static ProcessGetData(CNode* pfrom)
if (chainActive.Contains(mi->second)) {
send = true;
} else {
static const int nOneMonth = 30 * 24 * 60 * 60;
// 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 we know about.
// chain if they are valid, and no more than a month older (both in time, and in
// best equivalent proof of work) than the best header chain we know about.
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) {
LogPrintf("%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom->GetId());
}
Expand Down
17 changes: 17 additions & 0 deletions src/pow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,20 @@ arith_uint256 GetBlockProof(const CBlockIndex& block)
// or ~bnTarget / (nTarget+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();
}
3 changes: 3 additions & 0 deletions src/pow.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,7 @@ unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nF
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&);
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
24 changes: 24 additions & 0 deletions src/test/pow_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,28 @@ BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual)
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()

0 comments on commit 7bf5d5e

Please sign in to comment.