cleanup: dedup addrman Select_ table walk and pow-limit-by-algo selection
Two behavior-preserving refactors flagged by the Phase-6 hygiene scoping: * addrman: CAddrMan::Select_ contained two ~40-line copies of the same bucket-table random walk, differing only in the table (vvTried/vvNew), its bucket count, and a log label. Extract the shared loop into SelectFromTable_(vvTable, nBucketCount, tableName); Select_ now just dispatches to it. Verbatim move — clean compile proves self-containment. * pow: the "Equihash uses powLimit, everything else uses powAlternate" selection was copy-pasted as an if/else into GetNextWorkRequired, CalculateNextWorkRequired, and lwmaCalculateNextWorkRequired. Extract into PowLimitForAlgo(params). The CheckProofOfWork site (line ~892) is left as-is: it has an extra `height <= 1` genesis special-case and is NOT the same selection. On DragonX (RandomX) this always returns powAlternate, exactly as before. Validated: full build of dragonxd/cli/tx, isolated self-mine to height 336, verifychain 4 0 -> true (exercises PowLimitForAlgo on every block). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -473,25 +473,6 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
|
||||
if (size() == 0)
|
||||
return CAddrInfo();
|
||||
|
||||
// Track number of attempts to find a table entry, before giving up to avoid infinite loop
|
||||
const int kMaxRetries = 200000; // magic number so unit tests can pass
|
||||
const int kRetriesBetweenSleep = 1000;
|
||||
const int kRetrySleepInterval = 100; // milliseconds
|
||||
|
||||
// Peer-selection tuning factors (networking heuristics, not consensus).
|
||||
// On each rejected candidate the running chance factor is scaled up by this
|
||||
// amount so the loop is guaranteed to eventually accept a peer.
|
||||
const double kChanceFactorGrowth = 1.2;
|
||||
// Candidates on unreachable networks are deprioritized to this fraction of
|
||||
// their base chance.
|
||||
const double kUnreachableDeprioritize = 0.25;
|
||||
// Candidates that were just tried are deprioritized to this fraction of
|
||||
// their base chance.
|
||||
const double kJustTriedDeprioritize = 0.10;
|
||||
// Fixed-point scale for the acceptance probability test: draw a random int in
|
||||
// [0, kChanceScale) and accept if it falls below (factors * chance) * kChanceScale.
|
||||
const int kChanceScale = 1 << 30;
|
||||
|
||||
if (newOnly && nNew == 0)
|
||||
return CAddrInfo();
|
||||
|
||||
@@ -499,6 +480,32 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
|
||||
if (!newOnly &&
|
||||
(nTried > 0 && (nNew == 0 || RandomInt(2) == 0))) {
|
||||
// use a tried node
|
||||
return SelectFromTable_(vvTried, ADDRMAN_TRIED_BUCKET_COUNT, "tried");
|
||||
} else {
|
||||
// use a new node
|
||||
return SelectFromTable_(vvNew, ADDRMAN_NEW_BUCKET_COUNT, "new");
|
||||
}
|
||||
|
||||
return CAddrInfo();
|
||||
}
|
||||
|
||||
// Random-walk one addrman bucket table (tried or new) and return an accepted peer,
|
||||
// applying the reachable/just-tried deprioritization and the growing chance factor.
|
||||
// Extracted verbatim from Select_'s two previously copy-pasted branches; the only
|
||||
// differences were the table (vvTried/vvNew), its bucket count, and the log label.
|
||||
CAddrInfo CAddrMan::SelectFromTable_(int (*vvTable)[ADDRMAN_BUCKET_SIZE], int nBucketCount, const char *tableName)
|
||||
{
|
||||
// Track number of attempts to find a table entry, before giving up to avoid infinite loop
|
||||
const int kMaxRetries = 200000; // magic number so unit tests can pass
|
||||
const int kRetriesBetweenSleep = 1000;
|
||||
const int kRetrySleepInterval = 100; // milliseconds
|
||||
|
||||
// Peer-selection tuning factors (networking heuristics, not consensus).
|
||||
const double kChanceFactorGrowth = 1.2;
|
||||
const double kUnreachableDeprioritize = 0.25;
|
||||
const double kJustTriedDeprioritize = 0.10;
|
||||
const int kChanceScale = 1 << 30;
|
||||
|
||||
double fChanceFactor = 1.0;
|
||||
double fReachableFactor = 1.0;
|
||||
double fJustTried = 1.0;
|
||||
@@ -507,20 +514,20 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
|
||||
return CAddrInfo();
|
||||
|
||||
int i = 0;
|
||||
int nKBucket = RandomInt(ADDRMAN_TRIED_BUCKET_COUNT);
|
||||
int nKBucket = RandomInt(nBucketCount);
|
||||
int nKBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE);
|
||||
while (vvTried[nKBucket][nKBucketPos] == -1) {
|
||||
nKBucket = (nKBucket + insecure_rand()) % ADDRMAN_TRIED_BUCKET_COUNT;
|
||||
while (vvTable[nKBucket][nKBucketPos] == -1) {
|
||||
nKBucket = (nKBucket + insecure_rand()) % nBucketCount;
|
||||
nKBucketPos = (nKBucketPos + insecure_rand()) % ADDRMAN_BUCKET_SIZE;
|
||||
if (i++ > kMaxRetries)
|
||||
return CAddrInfo();
|
||||
if (i % kRetriesBetweenSleep == 0 && !nKey.IsNull())
|
||||
MilliSleep(kRetrySleepInterval);
|
||||
}
|
||||
int nId = vvTried[nKBucket][nKBucketPos];
|
||||
int nId = vvTable[nKBucket][nKBucketPos];
|
||||
// assert(mapInfo.count(nId) == 1);
|
||||
if(mapInfo.count(nId) != 1) {
|
||||
fprintf(stderr,"%s: Could not find tried node with nId=%d=vvTried[%d][%d], mapInfo.count(%d)=%lu\n", __func__, nId, nKBucket, nKBucketPos, nId, mapInfo.count(nId) );
|
||||
fprintf(stderr,"%s: Could not find %s node with nId=%d=vvTable[%d][%d], mapInfo.count(%d)=%lu\n", __func__, tableName, nId, nKBucket, nKBucketPos, nId, mapInfo.count(nId) );
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -537,49 +544,6 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
|
||||
return info;
|
||||
fChanceFactor *= kChanceFactorGrowth;
|
||||
}
|
||||
} else {
|
||||
// use a new node
|
||||
double fChanceFactor = 1.0;
|
||||
double fReachableFactor = 1.0;
|
||||
double fJustTried = 1.0;
|
||||
while (1) {
|
||||
if (ShutdownRequested()) //break loop on shutdown request
|
||||
return CAddrInfo();
|
||||
|
||||
int i = 0;
|
||||
int nUBucket = RandomInt(ADDRMAN_NEW_BUCKET_COUNT);
|
||||
int nUBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE);
|
||||
while (vvNew[nUBucket][nUBucketPos] == -1) {
|
||||
nUBucket = (nUBucket + insecure_rand()) % ADDRMAN_NEW_BUCKET_COUNT;
|
||||
nUBucketPos = (nUBucketPos + insecure_rand()) % ADDRMAN_BUCKET_SIZE;
|
||||
if (i++ > kMaxRetries)
|
||||
return CAddrInfo();
|
||||
if (i % kRetriesBetweenSleep == 0 && !nKey.IsNull())
|
||||
MilliSleep(kRetrySleepInterval);
|
||||
}
|
||||
int nId = vvNew[nUBucket][nUBucketPos];
|
||||
|
||||
if(mapInfo.count(nId) != 1) {
|
||||
fprintf(stderr,"%s: Could not find new node with nId=%d=vvNew[%d][%d], mapInfo.count(%d)=%lu\n", __func__, nId, nUBucket, nUBucketPos, nId, mapInfo.count(nId) );
|
||||
continue;
|
||||
}
|
||||
// assert(mapInfo.count(nId) == 1);
|
||||
CAddrInfo& info = mapInfo[nId];
|
||||
if (info.IsReachableNetwork()) {
|
||||
//deprioritize unreachable networks
|
||||
fReachableFactor = kUnreachableDeprioritize;
|
||||
}
|
||||
if (info.IsJustTried()) {
|
||||
//deprioritize entries just tried
|
||||
fJustTried = kJustTriedDeprioritize;
|
||||
}
|
||||
if (RandomInt(kChanceScale) < fChanceFactor * fReachableFactor * fJustTried * info.GetChance() * kChanceScale)
|
||||
return info;
|
||||
fChanceFactor *= kChanceFactorGrowth;
|
||||
}
|
||||
}
|
||||
|
||||
return CAddrInfo();
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ADDRMAN
|
||||
|
||||
@@ -300,6 +300,10 @@ protected:
|
||||
//! Select an address to connect to, if newOnly is set to true, only the new table is selected from.
|
||||
CAddrInfo Select_(bool newOnly);
|
||||
|
||||
//! Random-walk one bucket table (tried or new) and return an accepted peer.
|
||||
//! Shared implementation for Select_'s two (previously copy-pasted) branches.
|
||||
CAddrInfo SelectFromTable_(int (*vvTable)[ADDRMAN_BUCKET_SIZE], int nBucketCount, const char *tableName);
|
||||
|
||||
//! Wraps GetRandInt to allow tests to override RandomInt and make it deterministic.
|
||||
virtual int RandomInt(int nMax);
|
||||
|
||||
|
||||
23
src/pow.cpp
23
src/pow.cpp
@@ -97,6 +97,14 @@ bnTarget = RT_CST_RST (bnTarget, ts, cw, numerator, denominator, W, T, past);
|
||||
#define T ASSETCHAINS_BLOCKTIME
|
||||
#define K ((int64_t)1000000)
|
||||
|
||||
// The proof-of-work limit for the active algorithm: Equihash chains use params.powLimit,
|
||||
// everything else (DragonX = RandomX) uses params.powAlternate. Shared by the retarget
|
||||
// functions below, where this selection was previously copy-pasted as an if/else.
|
||||
static arith_uint256 PowLimitForAlgo(const Consensus::Params& params)
|
||||
{
|
||||
return UintToArith256(ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH ? params.powLimit : params.powAlternate);
|
||||
}
|
||||
|
||||
arith_uint256 RT_CST_RST_outer(int32_t height,uint32_t nTime,arith_uint256 bnTarget,uint32_t *ts,arith_uint256 *ct,int32_t numerator,int32_t denominator,int32_t W,int32_t past)
|
||||
{
|
||||
int64_t outerK; int32_t cmpval; arith_uint256 mintarget = bnTarget / arith_uint256(2);
|
||||
@@ -211,10 +219,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
|
||||
}
|
||||
|
||||
arith_uint256 bnLimit;
|
||||
if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH)
|
||||
bnLimit = UintToArith256(params.powLimit);
|
||||
else
|
||||
bnLimit = UintToArith256(params.powAlternate);
|
||||
bnLimit = PowLimitForAlgo(params);
|
||||
unsigned int nProofOfWorkLimit = bnLimit.GetCompact();
|
||||
// Genesis block
|
||||
if (pindexLast == NULL )
|
||||
@@ -461,10 +466,7 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg,
|
||||
}
|
||||
// Retarget
|
||||
arith_uint256 bnLimit;
|
||||
if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH)
|
||||
bnLimit = UintToArith256(params.powLimit);
|
||||
else
|
||||
bnLimit = UintToArith256(params.powAlternate);
|
||||
bnLimit = PowLimitForAlgo(params);
|
||||
|
||||
const arith_uint256 bnPowLimit = bnLimit; //UintToArith256(params.powLimit);
|
||||
arith_uint256 bnNew {bnAvg};
|
||||
@@ -498,10 +500,7 @@ unsigned int lwmaGetNextWorkRequired(const CBlockIndex* pindexLast, const CBlock
|
||||
unsigned int lwmaCalculateNextWorkRequired(const CBlockIndex* pindexLast, const Consensus::Params& params)
|
||||
{
|
||||
arith_uint256 nextTarget {0}, sumTarget {0}, bnTmp, bnLimit;
|
||||
if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH)
|
||||
bnLimit = UintToArith256(params.powLimit);
|
||||
else
|
||||
bnLimit = UintToArith256(params.powAlternate);
|
||||
bnLimit = PowLimitForAlgo(params);
|
||||
|
||||
unsigned int nProofOfWorkLimit = bnLimit.GetCompact();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user