class CInv;
class CRequestTracker;
class CNode;
+class CBlockIndexTrustComparator;
static const unsigned int MAX_BLOCK_SIZE = 1000000;
static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2;
extern CScript COINBASE_FLAGS;
extern CCriticalSection cs_main;
extern std::map<uint256, CBlockIndex*> mapBlockIndex;
+extern std::set<CBlockIndex*, CBlockIndexTrustComparator> setBlockIndexValid;
extern std::set<std::pair<COutPoint, unsigned int> > setStakeSeen;
extern CBlockIndex* pindexGenesisBlock;
extern unsigned int nStakeMinAge;
bool IsInitialBlockDownload();
std::string GetWarnings(std::string strFor);
bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, bool fAllowSlow);
+bool SetBestChain(CBlockIndex* pindexNew);
+bool ConnectBestBlock();
uint256 WantedByOrphan(const CBlock* pblockOrphan);
const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake);
void StakeMiner(CWallet *pwallet);
// Read a block from disk
bool ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions=true);
- // Make this block (with given index) the new tip of the active block chain
- bool SetBestChain(CBlockIndex* pindexNew);
-
// Add this block to the block index, and if necessary, switch the active block chain to this
bool AddToBlockIndex(const CDiskBlockPos &pos);
extern CBlockFileInfo infoLastBlockFile;
extern int nLastBlockFile;
+enum BlockStatus {
+ BLOCK_VALID_UNKNOWN = 0,
+ BLOCK_VALID_HEADER = 1, // parsed, version ok, hash satisfies claimed PoW, 1 <= vtx count <= max, timestamp not in future
+ BLOCK_VALID_TREE = 2, // parent found, difficulty matches, timestamp >= median previous, checkpoint
+ BLOCK_VALID_TRANSACTIONS = 3, // only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid, no duplicate txids, sigops, size, merkle root
+ BLOCK_VALID_CHAIN = 4, // outputs do not overspend inputs, no double spends, coinbase output ok, immature coinbase spends, BIP30
+ BLOCK_VALID_SCRIPTS = 5, // scripts/signatures ok
+ BLOCK_VALID_MASK = 7,
+
+ BLOCK_HAVE_DATA = 8, // full block available in blk*.dat
+ BLOCK_HAVE_UNDO = 16, // undo data available in rev*.dat
+ BLOCK_HAVE_MASK = 24,
+
+ BLOCK_FAILED_VALID = 32, // stage after last reached validness failed
+ BLOCK_FAILED_CHILD = 64, // descends from failed block
+ BLOCK_FAILED_MASK = 96
+};
+
/** The block chain is a tree shaped structure starting with the
* genesis block at the root, with each block potentially having multiple
* candidates to be the next block. pprev and pnext link a path through the
class CBlockIndex
{
public:
+ // pointer to the hash of the block, if any. memory is owned by this CBlockIndex
const uint256* phashBlock;
+
+ // pointer to the index of the predecessor of this block
CBlockIndex* pprev;
+
+ // (memory only) pointer to the index of the *active* successor of this block
CBlockIndex* pnext;
+
+ // height of the entry in the chain. The genesis block has height 0
int nHeight;
- CDiskBlockPos pos;
+
+ // Which # file this block is stored in (blk?????.dat)
+ int nFile;
+
+ // Byte offset within blk?????.dat where this block's data is stored
+ unsigned int nDataPos;
+
+ // Byte offset within rev?????.dat where this block's undo data is stored
unsigned int nUndoPos;
- uint256 nChainTrust; // trust score of block chain
+ // (memory only) Trust score of block chain up to and including this block
+ uint256 nChainTrust;
+
+ // Number of transactions in this block.
+ unsigned int nTx;
+
+ // (memory only) Number of transactions in the chain up to and including this block
+ unsigned int nChainTx;
+
+ // Verification status of this block. See enum BlockStatus for detailed info
+ unsigned int nStatus;
+
+ // Coins amount created by this block
int64 nMint;
+
+ // Total coins created in this block chain up to and including this block
int64 nMoneySupply;
+ // Block flags
unsigned int nFlags;
enum
{
- BLOCK_PROOF_OF_STAKE = (1 << 0), // is proof-of-stake block
- BLOCK_STAKE_ENTROPY = (1 << 1), // entropy bit for stake modifier
- BLOCK_STAKE_MODIFIER = (1 << 2), // regenerated stake modifier
+ // is proof-of-stake block
+ BLOCK_PROOF_OF_STAKE = (1 << 0),
+ // entropy bit for stake modifier
+ BLOCK_STAKE_ENTROPY = (1 << 1),
+ // regenerated stake modifier
+ BLOCK_STAKE_MODIFIER = (1 << 2),
};
- uint64 nStakeModifier; // hash modifier for proof-of-stake
- unsigned int nStakeModifierChecksum; // checksum of index; in-memeory only
+ // Hash modifier for proof-of-stake kernel
+ uint64 nStakeModifier;
- // proof-of-stake specific fields
+ // Checksum of index in-memory only
+ unsigned int nStakeModifierChecksum;
+
+ // Predecessor of coinstake transaction
COutPoint prevoutStake;
+
+ // Timestamp of coinstake transaction
unsigned int nStakeTime;
+
+ // Kernel hash
uint256 hashProofOfStake;
- // block header
+ // Block header
int nVersion;
uint256 hashMerkleRoot;
unsigned int nTime;
unsigned int nBits;
unsigned int nNonce;
-
CBlockIndex()
{
phashBlock = NULL;
pprev = NULL;
pnext = NULL;
nHeight = 0;
- pos.SetNull();
+ nFile = 0;
+ nDataPos = 0;
nUndoPos = 0;
nChainTrust = 0;
+ nTx = 0;
+ nChainTx = 0;
+ nStatus = 0;
nMint = 0;
nMoneySupply = 0;
nFlags = 0;
pprev = NULL;
pnext = NULL;
nHeight = 0;
- pos.SetNull();
+ nFile = 0;
+ nDataPos = 0;
nUndoPos = 0;
nChainTrust = 0;
+ nTx = 0;
+ nChainTx = 0;
+ nStatus = 0;
nMint = 0;
nMoneySupply = 0;
nFlags = 0;
}
CDiskBlockPos GetBlockPos() const {
- return pos;
+ CDiskBlockPos ret;
+ if (nStatus & BLOCK_HAVE_DATA) {
+ ret.nFile = nFile;
+ ret.nPos = nDataPos;
+ } else
+ ret.SetNull();
+ return ret;
}
CDiskBlockPos GetUndoPos() const {
- CDiskBlockPos ret = pos;
- if (nUndoPos == 0)
+ CDiskBlockPos ret;
+ if (nStatus & BLOCK_HAVE_UNDO) {
+ ret.nFile = nFile;
+ ret.nPos = nUndoPos;
+ } else
ret.SetNull();
- else
- ret.nPos = nUndoPos - 1;
return ret;
}
}
};
+struct CBlockIndexTrustComparator
+{
+ bool operator()(CBlockIndex *pa, CBlockIndex *pb) {
+ if (pa->nChainTrust > pb->nChainTrust) return false;
+ if (pa->nChainTrust < pb->nChainTrust) return true;
+
+ return false; // identical blocks
+ }
+};
+
/** Used to marshal pointers into hashes for db storage. */
class CDiskBlockIndex : public CBlockIndex
{
IMPLEMENT_SERIALIZE
(
if (!(nType & SER_GETHASH))
- READWRITE(nVersion);
-
- READWRITE(nHeight);
- READWRITE(pos);
- READWRITE(nUndoPos);
+ READWRITE(VARINT(nVersion));
+
+ READWRITE(VARINT(nHeight));
+ READWRITE(VARINT(nStatus));
+ READWRITE(VARINT(nTx));
+ if (nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO))
+ READWRITE(VARINT(nFile));
+ if (nStatus & BLOCK_HAVE_DATA)
+ READWRITE(VARINT(nDataPos));
+ if (nStatus & BLOCK_HAVE_UNDO)
+ READWRITE(VARINT(nUndoPos));
READWRITE(nMint);
READWRITE(nMoneySupply);
READWRITE(nFlags);