Prepare database format for multi-stage block processing
[novacoin.git] / src / main.h
index 038eb36..195d62e 100644 (file)
@@ -25,6 +25,7 @@ class CAddress;
 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;
@@ -72,6 +73,7 @@ extern libzerocoin::Params* ZCParams;
 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;
@@ -135,6 +137,8 @@ int GetNumBlocksOfPeers();
 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);
@@ -1385,9 +1389,6 @@ public:
     // 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);
 
@@ -1472,6 +1473,24 @@ extern CCriticalSection cs_LastBlockFile;
 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
@@ -1482,50 +1501,92 @@ extern int nLastBlockFile;
 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;
@@ -1548,9 +1609,13 @@ public:
         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;
@@ -1577,15 +1642,22 @@ public:
     }
 
     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;
     }
 
@@ -1719,6 +1791,16 @@ public:
     }
 };
 
+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
 {
@@ -1739,11 +1821,17 @@ public:
     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);