Skip to content

Commit 90fab7b

Browse files
authored
Merge pull request #278 from JaredTate/develop
Fix Memory Access Bug & Improve GetAlgo Handling for Legacy & Testnet Blocks
2 parents c5d9a01 + e578b20 commit 90fab7b

2 files changed

Lines changed: 123 additions & 78 deletions

File tree

src/chain.cpp

Lines changed: 93 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,46 @@
88
#include <chainparams.h>
99
#include <validation.h>
1010

11+
// Include whatever header actually declares LogPrintf in your codebase.
12+
// In DigiByte, it might be "logging.h" or "util/system.h". Adjust as needed:
13+
#include <logging.h> // or #include <util/system.h> or #include "util.h"
14+
15+
/**
16+
* CBlockIndex default constructor
17+
*/
18+
CBlockIndex::CBlockIndex()
19+
{
20+
for (unsigned i = 0; i < NUM_ALGOS_IMPL; i++) {
21+
lastAlgoBlocks[i] = nullptr;
22+
}
23+
}
24+
1125
/**
12-
* CChain implementation
26+
* CBlockIndex constructor that copies from a block header.
27+
* We can safely call LogPrintf here because we are in a .cpp file that includes logging.
1328
*/
29+
CBlockIndex::CBlockIndex(const CBlockHeader& block)
30+
: nVersion(block.nVersion),
31+
hashMerkleRoot(block.hashMerkleRoot),
32+
nTime(block.nTime),
33+
nBits(block.nBits),
34+
nNonce(block.nNonce)
35+
{
36+
// Initialize lastAlgoBlocks to null.
37+
for (unsigned i = 0; i < NUM_ALGOS_IMPL; i++) {
38+
lastAlgoBlocks[i] = nullptr;
39+
}
40+
41+
// Determine raw algo index from version bits:
42+
int rawAlgo = block.GetAlgo(); // This returns ALGO_UNKNOWN if it doesn't match recognized bits
43+
if (rawAlgo >= 0 && rawAlgo < NUM_ALGOS_IMPL) {
44+
lastAlgoBlocks[rawAlgo] = this;
45+
} else {
46+
// We can log this occurrence:
47+
LogPrintf("CBlockIndex ctor: ALGO_UNKNOWN in block version=0x%08x\n", block.nVersion);
48+
}
49+
}
50+
1451
void CChain::SetTip(CBlockIndex *pindex) {
1552
if (pindex == nullptr) {
1653
vChain.clear();
@@ -65,23 +102,55 @@ const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
65102
CBlockIndex* CChain::FindEarliestAtLeast(int64_t nTime, int height) const
66103
{
67104
std::pair<int64_t, int> blockparams = std::make_pair(nTime, height);
68-
std::vector<CBlockIndex*>::const_iterator lower = std::lower_bound(vChain.begin(), vChain.end(), blockparams,
69-
[](CBlockIndex* pBlock, const std::pair<int64_t, int>& blockparams) -> bool { return pBlock->GetBlockTimeMax() < blockparams.first || pBlock->nHeight < blockparams.second; });
105+
auto lower = std::lower_bound(
106+
vChain.begin(), vChain.end(), blockparams,
107+
[](CBlockIndex* pBlock, const std::pair<int64_t, int>& bp) {
108+
return pBlock->GetBlockTimeMax() < bp.first || pBlock->nHeight < bp.second;
109+
}
110+
);
70111
return (lower == vChain.end() ? nullptr : *lower);
71112
}
72113

73-
/** Turn the lowest '1' bit in the binary representation of a number into a '0'. */
114+
/**
115+
* Return recognized mining algo for this block, forcibly mapping blocks
116+
* below height 145,000 to ALGO_SCRYPT. If none recognized, logs a warning.
117+
*/
118+
int CBlockIndex::GetAlgo() const
119+
{
120+
// If we’re on mainnet, for historical reasons we force blocks below 145k to scrypt:
121+
if (!Params().NetworkIDString().compare("main")) {
122+
if (nHeight < 145000) {
123+
return ALGO_SCRYPT;
124+
}
125+
}
126+
127+
// Otherwise, parse from version bits (same as before):
128+
switch (nVersion & BLOCK_VERSION_ALGO) {
129+
case BLOCK_VERSION_SCRYPT: return ALGO_SCRYPT;
130+
case BLOCK_VERSION_SHA256D: return ALGO_SHA256D;
131+
case BLOCK_VERSION_GROESTL: return ALGO_GROESTL;
132+
case BLOCK_VERSION_SKEIN: return ALGO_SKEIN;
133+
case BLOCK_VERSION_QUBIT: return ALGO_QUBIT;
134+
case BLOCK_VERSION_ODO: return ALGO_ODO;
135+
}
136+
137+
// If still not recognized:
138+
LogPrintf("Warning: block at height=%d has unrecognized nVersion=0x%08x\n", nHeight, nVersion);
139+
return ALGO_UNKNOWN;
140+
}
141+
142+
143+
/** Turn the lowest '1' bit in the binary representation of a number into '0'. */
74144
int static inline InvertLowestOne(int n) { return n & (n - 1); }
75145

76146
/** Compute what height to jump back to with the CBlockIndex::pskip pointer. */
77147
int static inline GetSkipHeight(int height) {
78148
if (height < 2)
79149
return 0;
80150

81-
// Determine which height to jump back to. Any number strictly lower than height is acceptable,
82-
// but the following expression seems to perform well in simulations (max 110 steps to go back
83-
// up to 2**18 blocks).
84-
return (height & 1) ? InvertLowestOne(InvertLowestOne(height - 1)) + 1 : InvertLowestOne(height);
151+
return (height & 1)
152+
? InvertLowestOne(InvertLowestOne(height - 1)) + 1
153+
: InvertLowestOne(height);
85154
}
86155

87156
const CBlockIndex* CBlockIndex::GetAncestor(int height) const
@@ -124,18 +193,16 @@ void CBlockIndex::BuildSkip()
124193

125194
int GetAlgoWorkFactor(int nHeight, int algo)
126195
{
127-
if (nHeight < Params().GetConsensus().multiAlgoDiffChangeTarget)
128-
{
196+
if (nHeight < Params().GetConsensus().multiAlgoDiffChangeTarget) {
129197
return 1;
130198
}
131199

132200
switch (algo)
133201
{
134202
case ALGO_SHA256D:
135-
return 1;
136-
// work factor = absolute work ratio * optimisation factor
203+
return 1;
137204
case ALGO_SCRYPT:
138-
return 1024 * 4;
205+
return 1024 * 4; // etc...
139206
case ALGO_GROESTL:
140207
return 64 * 8;
141208
case ALGO_SKEIN:
@@ -155,33 +222,26 @@ arith_uint256 GetBlockProofBase(const CBlockIndex& block)
155222
bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow);
156223
if (fNegative || fOverflow || bnTarget == 0)
157224
return 0;
158-
// We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256
159-
// as it's too large for a arith_uint256. However, as 2**256 is at least as large
160-
// as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1,
161-
// or ~bnTarget / (nTarget+1) + 1.
225+
226+
// 2**256 / (bnTarget+1)
162227
return (~bnTarget / (bnTarget + 1)) + 1;
163228
}
164229

165-
// DGB 6.14.1 GetBlock Proof
166230
arith_uint256 GetBlockProof(const CBlockIndex& block)
167231
{
168232
CBlockHeader header = block.GetBlockHeader();
169233
int nHeight = block.nHeight;
170234
const Consensus::Params& params = Params().GetConsensus();
171235

172-
if (nHeight < params.workComputationChangeTarget)
173-
{
236+
if (nHeight < params.workComputationChangeTarget) {
174237
arith_uint256 bnBlockWork = GetBlockProofBase(block);
175238
uint32_t nAlgoWork = GetAlgoWorkFactor(nHeight, header.GetAlgo());
176239
return bnBlockWork * nAlgoWork;
177-
}
178-
else
179-
{
180-
// Compute the geometric mean of the block targets for each individual algorithm.
240+
} else {
241+
// Compute the geometric mean across all active algos
181242
arith_uint256 bnAvgTarget(1);
182243

183-
for (int i = 0; i < NUM_ALGOS_IMPL; i++)
184-
{
244+
for (int i = 0; i < NUM_ALGOS_IMPL; i++) {
185245
if (!IsAlgoActive(block.pprev, params, i))
186246
continue;
187247
unsigned int nBits = GetNextWorkRequired(block.pprev, &header, params, i);
@@ -196,11 +256,9 @@ arith_uint256 GetBlockProof(const CBlockIndex& block)
196256
// that all intermediate values fit in 256-bit integers.
197257
bnAvgTarget *= bnTarget.ApproxNthRoot(NUM_ALGOS);
198258
}
199-
// see comment in GetProofBase
200259
arith_uint256 bnRes = (~bnAvgTarget / (bnAvgTarget + 1)) + 1;
201-
// Scale to roughly match the old work calculation
260+
// scale
202261
bnRes <<= 7;
203-
204262
return bnRes;
205263
}
206264
}
@@ -211,14 +269,11 @@ arith_uint256 GetBlockProof(const CBlockIndex& block, int algo)
211269
int nHeight = block.nHeight;
212270
const Consensus::Params& params = Params().GetConsensus();
213271

214-
if (nHeight < params.workComputationChangeTarget)
215-
{
272+
if (nHeight < params.workComputationChangeTarget) {
216273
arith_uint256 bnBlockWork = GetBlockProofBase(block);
217274
uint32_t nAlgoWork = GetAlgoWorkFactor(nHeight, header.GetAlgo());
218275
return bnBlockWork * nAlgoWork;
219-
}
220-
else
221-
{
276+
} else {
222277
if (!IsAlgoActive(block.pprev, params, algo))
223278
return 0;
224279
unsigned int nBits = GetNextWorkRequired(block.pprev, &header, params, algo);
@@ -228,12 +283,12 @@ arith_uint256 GetBlockProof(const CBlockIndex& block, int algo)
228283
bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
229284
if (fNegative || fOverflow || bnTarget == 0)
230285
return 0;
231-
232286
return (~bnTarget / (bnTarget + 1)) + 1;
233287
}
234288
}
235289

236-
int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params& params)
290+
int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from,
291+
const CBlockIndex& tip, const Consensus::Params& params)
237292
{
238293
arith_uint256 r;
239294
int sign = 1;
@@ -250,9 +305,8 @@ int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& fr
250305
return sign * r.GetLow64();
251306
}
252307

253-
/** Find the last common ancestor two blocks have.
254-
* Both pa and pb must be non-nullptr. */
255-
const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex* pb) {
308+
const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex* pb)
309+
{
256310
if (pa->nHeight > pb->nHeight) {
257311
pa = pa->GetAncestor(pb->nHeight);
258312
} else if (pb->nHeight > pa->nHeight) {

src/chain.h

Lines changed: 30 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -61,34 +61,34 @@ class CBlockFileInfo
6161
READWRITE(VARINT(obj.nTimeLast));
6262
}
6363

64-
void SetNull() {
64+
void SetNull() {
6565
nBlocks = 0;
6666
nSize = 0;
6767
nUndoSize = 0;
6868
nHeightFirst = 0;
6969
nHeightLast = 0;
7070
nTimeFirst = 0;
7171
nTimeLast = 0;
72-
}
72+
}
7373

74-
CBlockFileInfo() {
74+
CBlockFileInfo() {
7575
SetNull();
76-
}
77-
78-
std::string ToString() const;
79-
80-
/** update statistics (does not update nSize) */
81-
void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) {
82-
if (nBlocks==0 || nHeightFirst > nHeightIn)
83-
nHeightFirst = nHeightIn;
84-
if (nBlocks==0 || nTimeFirst > nTimeIn)
85-
nTimeFirst = nTimeIn;
86-
nBlocks++;
87-
if (nHeightIn > nHeightLast)
88-
nHeightLast = nHeightIn;
89-
if (nTimeIn > nTimeLast)
90-
nTimeLast = nTimeIn;
91-
}
76+
}
77+
78+
std::string ToString() const;
79+
80+
/** update statistics (does not update nSize) */
81+
void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) {
82+
if (nBlocks==0 || nHeightFirst > nHeightIn)
83+
nHeightFirst = nHeightIn;
84+
if (nBlocks==0 || nTimeFirst > nTimeIn)
85+
nTimeFirst = nTimeIn;
86+
nBlocks++;
87+
if (nHeightIn > nHeightLast)
88+
nHeightLast = nHeightIn;
89+
if (nTimeIn > nTimeLast)
90+
nTimeLast = nTimeIn;
91+
}
9292
};
9393

9494
enum BlockStatus: uint32_t {
@@ -202,21 +202,16 @@ class CBlockIndex
202202
unsigned int nTimeMax{0};
203203
CBlockIndex *lastAlgoBlocks[NUM_ALGOS_IMPL];
204204

205-
CBlockIndex()
206-
{
207-
}
205+
/**
206+
* Default constructor (no header):
207+
*/
208+
CBlockIndex();
208209

209-
explicit CBlockIndex(const CBlockHeader& block)
210-
: nVersion{block.nVersion},
211-
hashMerkleRoot{block.hashMerkleRoot},
212-
nTime{block.nTime},
213-
nBits{block.nBits},
214-
nNonce{block.nNonce}
215-
{
216-
for (unsigned i = 0; i < NUM_ALGOS_IMPL; i++)
217-
lastAlgoBlocks[i] = nullptr;
218-
lastAlgoBlocks[GetAlgo()] = this;
219-
}
210+
/**
211+
* Full constructor that copies fields from a block header.
212+
* (Definition is moved to chain.cpp so we can log from there)
213+
*/
214+
explicit CBlockIndex(const CBlockHeader& block);
220215

221216
FlatFilePos GetBlockPos() const {
222217
FlatFilePos ret;
@@ -260,19 +255,15 @@ class CBlockIndex
260255
return GetPoWAlgoHash(block);
261256
}
262257

263-
int GetAlgo() const
264-
{
265-
CBlockHeader block = GetBlockHeader();
266-
return block.GetAlgo();
267-
}
268-
269258
/**
270259
* Check whether this block's and all previous blocks' transactions have been
271260
* downloaded (and stored to disk) at some point.
272261
*
273262
* Does not imply the transactions are consensus-valid (ConnectTip might fail)
274263
* Does not imply the transactions are still stored on disk. (IsBlockPruned might return true)
275264
*/
265+
int GetAlgo() const;
266+
276267
bool HaveTxsDownloaded() const { return nChainTx != 0; }
277268

278269
int64_t GetBlockTime() const

0 commit comments

Comments
 (0)