Changeset View
Changeset View
Standalone View
Standalone View
src/chain.h
Show First 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | public: | ||||
} | } | ||||
CBlockFileInfo() { SetNull(); } | CBlockFileInfo() { SetNull(); } | ||||
std::string ToString() const; | std::string ToString() const; | ||||
/** update statistics (does not update nSize) */ | /** update statistics (does not update nSize) */ | ||||
void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) { | void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) { | ||||
if (nBlocks == 0 || nHeightFirst > nHeightIn) nHeightFirst = nHeightIn; | if (nBlocks == 0 || nHeightFirst > nHeightIn) { | ||||
if (nBlocks == 0 || nTimeFirst > nTimeIn) nTimeFirst = nTimeIn; | nHeightFirst = nHeightIn; | ||||
} | |||||
if (nBlocks == 0 || nTimeFirst > nTimeIn) { | |||||
nTimeFirst = nTimeIn; | |||||
} | |||||
nBlocks++; | nBlocks++; | ||||
if (nHeightIn > nHeightLast) nHeightLast = nHeightIn; | if (nHeightIn > nHeightLast) { | ||||
if (nTimeIn > nTimeLast) nTimeLast = nTimeIn; | nHeightLast = nHeightIn; | ||||
} | |||||
if (nTimeIn > nTimeLast) { | |||||
nTimeLast = nTimeIn; | |||||
} | |||||
} | } | ||||
}; | }; | ||||
struct CDiskBlockPos { | struct CDiskBlockPos { | ||||
int nFile; | int nFile; | ||||
unsigned int nPos; | unsigned int nPos; | ||||
ADD_SERIALIZE_METHODS; | ADD_SERIALIZE_METHODS; | ||||
▲ Show 20 Lines • Show All 190 Lines • ▼ Show 20 Lines | CDiskBlockPos GetUndoPos() const { | ||||
ret.nPos = nUndoPos; | ret.nPos = nUndoPos; | ||||
} | } | ||||
return ret; | return ret; | ||||
} | } | ||||
CBlockHeader GetBlockHeader() const { | CBlockHeader GetBlockHeader() const { | ||||
CBlockHeader block; | CBlockHeader block; | ||||
block.nVersion = nVersion; | block.nVersion = nVersion; | ||||
if (pprev) block.hashPrevBlock = pprev->GetBlockHash(); | if (pprev) { | ||||
block.hashPrevBlock = pprev->GetBlockHash(); | |||||
} | |||||
block.hashMerkleRoot = hashMerkleRoot; | block.hashMerkleRoot = hashMerkleRoot; | ||||
block.nTime = nTime; | block.nTime = nTime; | ||||
block.nBits = nBits; | block.nBits = nBits; | ||||
block.nNonce = nNonce; | block.nNonce = nNonce; | ||||
return block; | return block; | ||||
} | } | ||||
uint256 GetBlockHash() const { return *phashBlock; } | uint256 GetBlockHash() const { return *phashBlock; } | ||||
int64_t GetBlockTime() const { return (int64_t)nTime; } | int64_t GetBlockTime() const { return (int64_t)nTime; } | ||||
int64_t GetBlockTimeMax() const { return (int64_t)nTimeMax; } | int64_t GetBlockTimeMax() const { return (int64_t)nTimeMax; } | ||||
enum { nMedianTimeSpan = 11 }; | enum { nMedianTimeSpan = 11 }; | ||||
int64_t GetMedianTimePast() const { | int64_t GetMedianTimePast() const { | ||||
int64_t pmedian[nMedianTimeSpan]; | int64_t pmedian[nMedianTimeSpan]; | ||||
int64_t *pbegin = &pmedian[nMedianTimeSpan]; | int64_t *pbegin = &pmedian[nMedianTimeSpan]; | ||||
int64_t *pend = &pmedian[nMedianTimeSpan]; | int64_t *pend = &pmedian[nMedianTimeSpan]; | ||||
const CBlockIndex *pindex = this; | const CBlockIndex *pindex = this; | ||||
for (int i = 0; i < nMedianTimeSpan && pindex; | for (int i = 0; i < nMedianTimeSpan && pindex; | ||||
i++, pindex = pindex->pprev) | i++, pindex = pindex->pprev) { | ||||
*(--pbegin) = pindex->GetBlockTime(); | *(--pbegin) = pindex->GetBlockTime(); | ||||
} | |||||
std::sort(pbegin, pend); | std::sort(pbegin, pend); | ||||
return pbegin[(pend - pbegin) / 2]; | return pbegin[(pend - pbegin) / 2]; | ||||
} | } | ||||
std::string ToString() const { | std::string ToString() const { | ||||
return strprintf( | return strprintf( | ||||
"CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)", pprev, | "CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)", pprev, | ||||
nHeight, hashMerkleRoot.ToString(), GetBlockHash().ToString()); | nHeight, hashMerkleRoot.ToString(), GetBlockHash().ToString()); | ||||
} | } | ||||
//! Check whether this block index entry is valid up to the passed validity | //! Check whether this block index entry is valid up to the passed validity | ||||
//! level. | //! level. | ||||
bool IsValid(enum BlockStatus nUpTo = BLOCK_VALID_TRANSACTIONS) const { | bool IsValid(enum BlockStatus nUpTo = BLOCK_VALID_TRANSACTIONS) const { | ||||
// Only validity flags allowed. | // Only validity flags allowed. | ||||
assert(!(nUpTo & ~BLOCK_VALID_MASK)); | assert(!(nUpTo & ~BLOCK_VALID_MASK)); | ||||
if (nStatus & BLOCK_FAILED_MASK) return false; | if (nStatus & BLOCK_FAILED_MASK) { | ||||
return false; | |||||
} | |||||
return ((nStatus & BLOCK_VALID_MASK) >= nUpTo); | return ((nStatus & BLOCK_VALID_MASK) >= nUpTo); | ||||
} | } | ||||
//! Raise the validity level of this block index entry. | //! Raise the validity level of this block index entry. | ||||
//! Returns true if the validity was changed. | //! Returns true if the validity was changed. | ||||
bool RaiseValidity(enum BlockStatus nUpTo) { | bool RaiseValidity(enum BlockStatus nUpTo) { | ||||
// Only validity flags allowed. | // Only validity flags allowed. | ||||
assert(!(nUpTo & ~BLOCK_VALID_MASK)); | assert(!(nUpTo & ~BLOCK_VALID_MASK)); | ||||
if (nStatus & BLOCK_FAILED_MASK) return false; | if (nStatus & BLOCK_FAILED_MASK) { | ||||
return false; | |||||
} | |||||
if ((nStatus & BLOCK_VALID_MASK) < nUpTo) { | if ((nStatus & BLOCK_VALID_MASK) < nUpTo) { | ||||
nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo; | nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo; | ||||
return true; | return true; | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
//! Build the skiplist pointer for this entry. | //! Build the skiplist pointer for this entry. | ||||
Show All 24 Lines | explicit CDiskBlockIndex(const CBlockIndex *pindex) : CBlockIndex(*pindex) { | ||||
hashPrev = (pprev ? pprev->GetBlockHash() : uint256()); | hashPrev = (pprev ? pprev->GetBlockHash() : uint256()); | ||||
} | } | ||||
ADD_SERIALIZE_METHODS; | ADD_SERIALIZE_METHODS; | ||||
template <typename Stream, typename Operation> | template <typename Stream, typename Operation> | ||||
inline void SerializationOp(Stream &s, Operation ser_action) { | inline void SerializationOp(Stream &s, Operation ser_action) { | ||||
int nVersion = s.GetVersion(); | int nVersion = s.GetVersion(); | ||||
if (!(s.GetType() & SER_GETHASH)) READWRITE(VARINT(nVersion)); | if (!(s.GetType() & SER_GETHASH)) { | ||||
READWRITE(VARINT(nVersion)); | |||||
} | |||||
READWRITE(VARINT(nHeight)); | READWRITE(VARINT(nHeight)); | ||||
READWRITE(VARINT(nStatus)); | READWRITE(VARINT(nStatus)); | ||||
READWRITE(VARINT(nTx)); | READWRITE(VARINT(nTx)); | ||||
if (nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) | if (nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) { | ||||
READWRITE(VARINT(nFile)); | READWRITE(VARINT(nFile)); | ||||
if (nStatus & BLOCK_HAVE_DATA) READWRITE(VARINT(nDataPos)); | } | ||||
if (nStatus & BLOCK_HAVE_UNDO) READWRITE(VARINT(nUndoPos)); | if (nStatus & BLOCK_HAVE_DATA) { | ||||
READWRITE(VARINT(nDataPos)); | |||||
} | |||||
if (nStatus & BLOCK_HAVE_UNDO) { | |||||
READWRITE(VARINT(nUndoPos)); | |||||
} | |||||
// block header | // block header | ||||
READWRITE(this->nVersion); | READWRITE(this->nVersion); | ||||
READWRITE(hashPrev); | READWRITE(hashPrev); | ||||
READWRITE(hashMerkleRoot); | READWRITE(hashMerkleRoot); | ||||
READWRITE(nTime); | READWRITE(nTime); | ||||
READWRITE(nBits); | READWRITE(nBits); | ||||
READWRITE(nNonce); | READWRITE(nNonce); | ||||
Show All 40 Lines | CBlockIndex *Tip() const { | ||||
return vChain.size() > 0 ? vChain[vChain.size() - 1] : nullptr; | return vChain.size() > 0 ? vChain[vChain.size() - 1] : nullptr; | ||||
} | } | ||||
/** | /** | ||||
* Returns the index entry at a particular height in this chain, or nullptr | * Returns the index entry at a particular height in this chain, or nullptr | ||||
* if no such height exists. | * if no such height exists. | ||||
*/ | */ | ||||
CBlockIndex *operator[](int nHeight) const { | CBlockIndex *operator[](int nHeight) const { | ||||
if (nHeight < 0 || nHeight >= (int)vChain.size()) return nullptr; | if (nHeight < 0 || nHeight >= (int)vChain.size()) { | ||||
return nullptr; | |||||
} | |||||
return vChain[nHeight]; | return vChain[nHeight]; | ||||
} | } | ||||
/** Compare two chains efficiently. */ | /** Compare two chains efficiently. */ | ||||
friend bool operator==(const CChain &a, const CChain &b) { | friend bool operator==(const CChain &a, const CChain &b) { | ||||
return a.vChain.size() == b.vChain.size() && | return a.vChain.size() == b.vChain.size() && | ||||
a.vChain[a.vChain.size() - 1] == b.vChain[b.vChain.size() - 1]; | a.vChain[a.vChain.size() - 1] == b.vChain[b.vChain.size() - 1]; | ||||
} | } | ||||
/** Efficiently check whether a block is present in this chain. */ | /** Efficiently check whether a block is present in this chain. */ | ||||
bool Contains(const CBlockIndex *pindex) const { | bool Contains(const CBlockIndex *pindex) const { | ||||
return (*this)[pindex->nHeight] == pindex; | return (*this)[pindex->nHeight] == pindex; | ||||
} | } | ||||
/** | /** | ||||
* Find the successor of a block in this chain, or nullptr if the given | * Find the successor of a block in this chain, or nullptr if the given | ||||
* index is not found or is the tip. | * index is not found or is the tip. | ||||
*/ | */ | ||||
CBlockIndex *Next(const CBlockIndex *pindex) const { | CBlockIndex *Next(const CBlockIndex *pindex) const { | ||||
if (Contains(pindex)) | if (!Contains(pindex)) { | ||||
return (*this)[pindex->nHeight + 1]; | |||||
else | |||||
return nullptr; | return nullptr; | ||||
} | } | ||||
return (*this)[pindex->nHeight + 1]; | |||||
} | |||||
/** | /** | ||||
* Return the maximal height in the chain. Is equal to chain.Tip() ? | * Return the maximal height in the chain. Is equal to chain.Tip() ? | ||||
* chain.Tip()->nHeight : -1. | * chain.Tip()->nHeight : -1. | ||||
*/ | */ | ||||
int Height() const { return vChain.size() - 1; } | int Height() const { return vChain.size() - 1; } | ||||
/** Set/initialize a chain with a given tip. */ | /** Set/initialize a chain with a given tip. */ | ||||
void SetTip(CBlockIndex *pindex); | void SetTip(CBlockIndex *pindex); | ||||
Show All 19 Lines |