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)
|
if (size() == 0)
|
||||||
return CAddrInfo();
|
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)
|
if (newOnly && nNew == 0)
|
||||||
return CAddrInfo();
|
return CAddrInfo();
|
||||||
|
|
||||||
@@ -499,6 +480,32 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
|
|||||||
if (!newOnly &&
|
if (!newOnly &&
|
||||||
(nTried > 0 && (nNew == 0 || RandomInt(2) == 0))) {
|
(nTried > 0 && (nNew == 0 || RandomInt(2) == 0))) {
|
||||||
// use a tried node
|
// 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 fChanceFactor = 1.0;
|
||||||
double fReachableFactor = 1.0;
|
double fReachableFactor = 1.0;
|
||||||
double fJustTried = 1.0;
|
double fJustTried = 1.0;
|
||||||
@@ -507,20 +514,20 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
|
|||||||
return CAddrInfo();
|
return CAddrInfo();
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int nKBucket = RandomInt(ADDRMAN_TRIED_BUCKET_COUNT);
|
int nKBucket = RandomInt(nBucketCount);
|
||||||
int nKBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE);
|
int nKBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE);
|
||||||
while (vvTried[nKBucket][nKBucketPos] == -1) {
|
while (vvTable[nKBucket][nKBucketPos] == -1) {
|
||||||
nKBucket = (nKBucket + insecure_rand()) % ADDRMAN_TRIED_BUCKET_COUNT;
|
nKBucket = (nKBucket + insecure_rand()) % nBucketCount;
|
||||||
nKBucketPos = (nKBucketPos + insecure_rand()) % ADDRMAN_BUCKET_SIZE;
|
nKBucketPos = (nKBucketPos + insecure_rand()) % ADDRMAN_BUCKET_SIZE;
|
||||||
if (i++ > kMaxRetries)
|
if (i++ > kMaxRetries)
|
||||||
return CAddrInfo();
|
return CAddrInfo();
|
||||||
if (i % kRetriesBetweenSleep == 0 && !nKey.IsNull())
|
if (i % kRetriesBetweenSleep == 0 && !nKey.IsNull())
|
||||||
MilliSleep(kRetrySleepInterval);
|
MilliSleep(kRetrySleepInterval);
|
||||||
}
|
}
|
||||||
int nId = vvTried[nKBucket][nKBucketPos];
|
int nId = vvTable[nKBucket][nKBucketPos];
|
||||||
// assert(mapInfo.count(nId) == 1);
|
// assert(mapInfo.count(nId) == 1);
|
||||||
if(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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,49 +544,6 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
|
|||||||
return info;
|
return info;
|
||||||
fChanceFactor *= kChanceFactorGrowth;
|
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
|
#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.
|
//! Select an address to connect to, if newOnly is set to true, only the new table is selected from.
|
||||||
CAddrInfo Select_(bool newOnly);
|
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.
|
//! Wraps GetRandInt to allow tests to override RandomInt and make it deterministic.
|
||||||
virtual int RandomInt(int nMax);
|
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 T ASSETCHAINS_BLOCKTIME
|
||||||
#define K ((int64_t)1000000)
|
#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)
|
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);
|
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;
|
arith_uint256 bnLimit;
|
||||||
if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH)
|
bnLimit = PowLimitForAlgo(params);
|
||||||
bnLimit = UintToArith256(params.powLimit);
|
|
||||||
else
|
|
||||||
bnLimit = UintToArith256(params.powAlternate);
|
|
||||||
unsigned int nProofOfWorkLimit = bnLimit.GetCompact();
|
unsigned int nProofOfWorkLimit = bnLimit.GetCompact();
|
||||||
// Genesis block
|
// Genesis block
|
||||||
if (pindexLast == NULL )
|
if (pindexLast == NULL )
|
||||||
@@ -461,10 +466,7 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg,
|
|||||||
}
|
}
|
||||||
// Retarget
|
// Retarget
|
||||||
arith_uint256 bnLimit;
|
arith_uint256 bnLimit;
|
||||||
if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH)
|
bnLimit = PowLimitForAlgo(params);
|
||||||
bnLimit = UintToArith256(params.powLimit);
|
|
||||||
else
|
|
||||||
bnLimit = UintToArith256(params.powAlternate);
|
|
||||||
|
|
||||||
const arith_uint256 bnPowLimit = bnLimit; //UintToArith256(params.powLimit);
|
const arith_uint256 bnPowLimit = bnLimit; //UintToArith256(params.powLimit);
|
||||||
arith_uint256 bnNew {bnAvg};
|
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)
|
unsigned int lwmaCalculateNextWorkRequired(const CBlockIndex* pindexLast, const Consensus::Params& params)
|
||||||
{
|
{
|
||||||
arith_uint256 nextTarget {0}, sumTarget {0}, bnTmp, bnLimit;
|
arith_uint256 nextTarget {0}, sumTarget {0}, bnTmp, bnLimit;
|
||||||
if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH)
|
bnLimit = PowLimitForAlgo(params);
|
||||||
bnLimit = UintToArith256(params.powLimit);
|
|
||||||
else
|
|
||||||
bnLimit = UintToArith256(params.powAlternate);
|
|
||||||
|
|
||||||
unsigned int nProofOfWorkLimit = bnLimit.GetCompact();
|
unsigned int nProofOfWorkLimit = bnLimit.GetCompact();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user