]> Git Repo - VerusCoin.git/blobdiff - src/chain.h
Build fix
[VerusCoin.git] / src / chain.h
index 9532fb15ccc177df12443610e4145078b60d1a80..961afe6c40e776b89f43c9caeda5eb7b24941419 100644 (file)
@@ -1,7 +1,7 @@
 // Copyright (c) 2009-2010 Satoshi Nakamoto
 // Copyright (c) 2009-2014 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+// file COPYING or https://www.opensource.org/licenses/mit-license.php .
 
 #ifndef BITCOIN_CHAIN_H
 #define BITCOIN_CHAIN_H
@@ -13,14 +13,67 @@ class CChainPower;
 #include "pow.h"
 #include "tinyformat.h"
 #include "uint256.h"
+#include "mmr.h"
 
 #include <vector>
 
-#include <boost/foreach.hpp>
-
 static const int SPROUT_VALUE_VERSION = 1001400;
 static const int SAPLING_VALUE_VERSION = 1010100;
 
+class CBlockFileInfo
+{
+public:
+    unsigned int nBlocks;      //!< number of blocks stored in file
+    unsigned int nSize;        //!< number of used bytes of block file
+    unsigned int nUndoSize;    //!< number of used bytes in the undo file
+    unsigned int nHeightFirst; //!< lowest height of block in file
+    unsigned int nHeightLast;  //!< highest height of block in file
+    uint64_t nTimeFirst;       //!< earliest time of block in file
+    uint64_t nTimeLast;        //!< latest time of block in file
+
+    ADD_SERIALIZE_METHODS;
+
+    template <typename Stream, typename Operation>
+    inline void SerializationOp(Stream& s, Operation ser_action) {
+        READWRITE(VARINT(nBlocks));
+        READWRITE(VARINT(nSize));
+        READWRITE(VARINT(nUndoSize));
+        READWRITE(VARINT(nHeightFirst));
+        READWRITE(VARINT(nHeightLast));
+        READWRITE(VARINT(nTimeFirst));
+        READWRITE(VARINT(nTimeLast));
+    }
+
+     void SetNull() {
+         nBlocks = 0;
+         nSize = 0;
+         nUndoSize = 0;
+         nHeightFirst = 0;
+         nHeightLast = 0;
+         nTimeFirst = 0;
+         nTimeLast = 0;
+     }
+
+     CBlockFileInfo() {
+         SetNull();
+     }
+
+     std::string ToString() const;
+
+     /** update statistics (does not update nSize) */
+     void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) {
+         if (nBlocks==0 || nHeightFirst > nHeightIn)
+             nHeightFirst = nHeightIn;
+         if (nBlocks==0 || nTimeFirst > nTimeIn)
+             nTimeFirst = nTimeIn;
+         nBlocks++;
+         if (nHeightIn > nHeightLast)
+             nHeightLast = nHeightIn;
+         if (nTimeIn > nTimeLast)
+             nTimeLast = nTimeIn;
+     }
+};
+
 struct CDiskBlockPos
 {
     int nFile;
@@ -198,6 +251,9 @@ class CChainPower
         {
             return !(p1 < p2);
         }
+
+        uint256 CompactChainPower() const;
+        static CChainPower ExpandCompactPower(uint256 compactPower, uint32_t height = 0);
 };
 
 /** The block chain is a tree shaped structure starting with the
@@ -217,8 +273,13 @@ public:
     //! pointer to the index of some further predecessor of this block
     CBlockIndex* pskip;
 
-    //! height of the entry in the chain. The genesis block has height 0
-    int64_t newcoins,zfunds; int8_t segid; // jl777 fields
+    int64_t newcoins;
+    int64_t zfunds;
+    int64_t immature;       // how much in this block is immature
+    uint32_t maturity;      // when do the immature funds in this block mature?
+
+    int8_t segid; // jl777 fields
+
     //! Which # file this block is stored in (blk?????.dat)
     int nFile;
 
@@ -288,6 +349,8 @@ public:
     {
         phashBlock = NULL;
         newcoins = zfunds = 0;
+        maturity = 0;
+        immature = 0;
         segid = -2;
         pprev = NULL;
         pskip = NULL;
@@ -334,7 +397,7 @@ public:
         nSolution      = block.nSolution;
     }
 
-    int32_t SetHeight(int32_t height)
+    void SetHeight(int32_t height)
     {
         this->chainPower.nHeight = height;
     }
@@ -450,6 +513,58 @@ public:
     {
         return GetBlockHeader().IsVerusPOSBlock();
     }
+
+    bool GetRawVerusPOSHash(uint256 &ret) const;
+    uint256 GetVerusEntropyHashComponent() const;
+
+    uint256 BlockMMRRoot() const
+    {
+        if (nVersion == CBlockHeader::VERUS_V2)
+        {
+            CPBaaSSolutionDescriptor descr = CConstVerusSolutionVector::GetDescriptor((nSolution));
+            if (descr.version >= CActivationHeight::ACTIVATE_PBAAS)
+            {
+                return descr.hashBlockMMRRoot;
+            }
+        }
+        return hashMerkleRoot;
+    }
+
+    uint256 PrevMMRRoot()
+    {
+        if (nVersion == CBlockHeader::VERUS_V2)
+        {
+            CPBaaSSolutionDescriptor descr = CConstVerusSolutionVector::GetDescriptor(nSolution);
+            if (descr.version >= CActivationHeight::ACTIVATE_PBAAS)
+            {
+                return descr.hashPrevMMRRoot;
+            }
+        }
+        return uint256();
+    }
+
+    // return a node from this block index as is, including hash of merkle root and block hash as well as compact chain power, to put into an MMR
+    ChainMMRNode GetBlockMMRNode() const
+    {
+        uint256 blockHash = GetBlockHash();
+
+        uint256 preHash = ChainMMRNode::HashObj(BlockMMRRoot(), blockHash);
+        uint256 power = ArithToUint256(GetCompactPower(nNonce, nBits, nVersion));
+
+        return ChainMMRNode(ChainMMRNode::HashObj(preHash, power), power);
+    }
+
+    CMMRNodeBranch MMRProofBridge()
+    {
+        // we need to add the block hash on the right, no change to index, as bit is zero
+        return CMMRNodeBranch(CMMRNodeBranch::BRANCH_MMRBLAKE_NODE, 2, 0, std::vector<uint256>({GetBlockHash()}));
+    }
+
+    CMMRNodeBranch BlockProofBridge()
+    {
+        // we need to add the merkle root on the left
+        return CMMRNodeBranch(CMMRNodeBranch::BRANCH_MMRBLAKE_NODE, 2, 1, std::vector<uint256>({BlockMMRRoot()}));
+    }
 };
 
 /** Used to marshal pointers into hashes for db storage. */
@@ -471,6 +586,9 @@ public:
     template <typename Stream, typename Operation>
     inline void SerializationOp(Stream& s, Operation ser_action) {
         int nVersion = s.GetVersion();
+#ifdef VERUSHASHDEBUG
+        if (!ser_action.ForRead()) printf("Serializing block index %s, stream version: %x\n", ToString().c_str(), nVersion);
+#endif
         if (!(s.GetType() & SER_GETHASH))
             READWRITE(VARINT(nVersion));
 
@@ -521,6 +639,9 @@ public:
         if ((s.GetType() & SER_DISK) && (nVersion >= SAPLING_VALUE_VERSION)) {
             READWRITE(nSaplingValue);
         }
+
+        // If you have just added new serialized fields above, remember to add
+        // them to CBlockTreeDB::LoadBlockIndexGuts() in txdb.cpp :)
     }
 
     uint256 GetBlockHash() const
@@ -537,25 +658,45 @@ public:
         return block.GetHash();
     }
 
-
     std::string ToString() const
     {
-        std::string str = "CDiskBlockIndex(";
-        str += CBlockIndex::ToString();
-        str += strprintf("\n                hashBlock=%s, hashPrev=%s)",
-            GetBlockHash().ToString(),
-            hashPrev.ToString());
+        std::string str = "CDiskBlockIndex:\n";
+
+        CBlockHeader block;
+        block.nVersion        = nVersion;
+        block.hashPrevBlock   = hashPrev;
+        block.hashMerkleRoot  = hashMerkleRoot;
+        block.hashFinalSaplingRoot    = hashFinalSaplingRoot;
+        block.nTime           = nTime;
+        block.nBits           = nBits;
+        block.nNonce          = nNonce;
+        block.nSolution       = nSolution;
+        CPBaaSPreHeader preBlock(block);
+
+        str += strprintf("block.nVersion=%x\npprev=%p\nnHeight=%d\nhashBlock=%s\nblock.hashPrevBlock=%s\nblock.hashMerkleRoot=%s\nblock.nBits=%d\nblock.nNonce=%s\nblock.nSolution=%s\npreBlock.hashPrevMMRRoot=%s\npreBlock.hashBlockMMRRoot=%s\n",
+            this->nVersion, pprev, this->chainPower.nHeight, GetBlockHash().ToString(), hashPrev.ToString(), hashMerkleRoot.ToString(), nBits, nNonce.ToString(), HexBytes(nSolution.data(), nSolution.size()), preBlock.hashPrevMMRRoot.ToString(), preBlock.hashBlockMMRRoot.ToString());
+
         return str;
     }
 };
 
-/** An in-memory indexed chain of blocks. */
+class CChain;
+typedef CMerkleMountainRange<ChainMMRNode, CChunkedLayer<ChainMMRNode, 9>, COverlayNodeLayer<ChainMMRNode, CChain>> ChainMerkleMountainRange;
+typedef CMerkleMountainView<ChainMMRNode, CChunkedLayer<ChainMMRNode, 9>, COverlayNodeLayer<ChainMMRNode, CChain>> ChainMerkleMountainView;
+
+/** An in-memory indexed chain of blocks. 
+ * With Verus and PBaaS chains, this also provides a complete Merkle Mountain Range (MMR) for the chain at all times,
+ * enabling proof of any transaction that can be exported and trusted on any chain that has a trusted oracle or other lite proof of this chain.
+*/
 class CChain {
 private:
     std::vector<CBlockIndex*> vChain;
+    ChainMerkleMountainRange mmr;
     CBlockIndex *lastTip;
 
 public:
+    CChain() : vChain(), mmr(COverlayNodeLayer<ChainMMRNode, CChain>(*this)) {}
+
     /** Returns the index entry for the genesis block of this chain, or NULL if none. */
     CBlockIndex *Genesis() const {
         return vChain.size() > 0 ? vChain[0] : NULL;
@@ -578,6 +719,28 @@ public:
         return vChain[nHeight];
     }
 
+    uint256 GetVerusEntropyHash(int forHeight, int *pPOSheight=nullptr, int *pPOWheight=nullptr, int *pALTheight=nullptr) const;
+
+    /** Get the Merkle Mountain Range for this chain. */
+    const ChainMerkleMountainRange &GetMMR()
+    {
+        return mmr;
+    }
+
+    /** Get a Merkle Mountain Range view for this chain. */
+    ChainMerkleMountainView GetMMV()
+    {
+        return ChainMerkleMountainView(mmr, mmr.size());
+    }    
+
+    ChainMMRNode GetMMRNode(int index) const
+    {
+        return vChain[index]->GetBlockMMRNode();
+    }
+
+    bool GetBlockProof(ChainMerkleMountainView &view, CMMRProof &retProof, int index) const;
+    bool GetMerkleProof(ChainMerkleMountainView &view, CMMRProof &retProof, int index) const;
+
     /** Compare two chains efficiently. */
     friend bool operator==(const CChain &a, const CChain &b) {
         return a.vChain.size() == b.vChain.size() &&
@@ -586,7 +749,7 @@ public:
 
     /** Efficiently check whether a block is present in this chain. */
     bool Contains(const CBlockIndex *pindex) const {
-        return (*this)[pindex->GetHeight()] == pindex;
+        return !pindex ? false : (*this)[pindex->GetHeight()] == pindex;
     }
 
     /** Find the successor of a block in this chain, or NULL if the given index is not found or is the tip. */
@@ -602,6 +765,11 @@ public:
         return vChain.size() - 1;
     }
 
+    uint64_t size()
+    {
+        return vChain.size();
+    }
+
     /** Set/initialize a chain with a given tip. */
     void SetTip(CBlockIndex *pindex);
 
This page took 0.029677 seconds and 4 git commands to generate.