block.h raw

   1  // Copyright (c) 2009-2010 Satoshi Nakamoto
   2  // Copyright (c) 2009-2022 The Limenka developers
   3  // Distributed under the MIT software license, see the accompanying
   4  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   5  
   6  #ifndef LIMENKA_PRIMITIVES_BLOCK_H
   7  #define LIMENKA_PRIMITIVES_BLOCK_H
   8  
   9  #include <consensus/amount.h>
  10  #include <primitives/transaction.h>
  11  #include <serialize.h>
  12  #include <uint256.h>
  13  #include <util/time.h>
  14  
  15  /** Nodes collect new transactions into a block, hash them into a hash tree,
  16   * and scan through nonce values to make the block's hash satisfy proof-of-work
  17   * requirements.  When they solve the proof-of-work, they broadcast the block
  18   * to everyone and the block is added to the block chain.  The first transaction
  19   * in the block is a special one that creates a new coin owned by the creator
  20   * of the block.
  21   */
  22  class CBlockHeader
  23  {
  24  public:
  25      // header
  26      int32_t nVersion;
  27      uint256 hashPrevBlock;
  28      uint256 hashMerkleRoot;
  29      uint32_t nTime;
  30      uint32_t nBits;
  31      uint32_t nNonce;
  32  
  33      CBlockHeader()
  34      {
  35          SetNull();
  36      }
  37  
  38      SERIALIZE_METHODS(CBlockHeader, obj) { READWRITE(obj.nVersion, obj.hashPrevBlock, obj.hashMerkleRoot, obj.nTime, obj.nBits, obj.nNonce); }
  39  
  40      void SetNull()
  41      {
  42          nVersion = 0;
  43          hashPrevBlock.SetNull();
  44          hashMerkleRoot.SetNull();
  45          nTime = 0;
  46          nBits = 0;
  47          nNonce = 0;
  48      }
  49  
  50      bool IsNull() const
  51      {
  52          return (nBits == 0);
  53      }
  54  
  55      uint256 GetHash() const;
  56  
  57      NodeSeconds Time() const
  58      {
  59          return NodeSeconds{std::chrono::seconds{nTime}};
  60      }
  61  
  62      int64_t GetBlockTime() const
  63      {
  64          return (int64_t)nTime;
  65      }
  66  };
  67  
  68  /** Fork block subsidy: time-proportional, uncapped.
  69   *  R(e) = R_full * e / 600 where R_full is the halved base subsidy
  70   *  (halving counted in aggregate fork seconds).  At e = 600 the block
  71   *  pays exactly the parent-chain subsidy; early blocks pay
  72   *  proportionally less, late blocks proportionally more (catch-up).
  73   *  The telescoping sum of e over all blocks equals elapsed time, so
  74   *  total issuance is exactly parity regardless of cadence.
  75   *  e: measured interval (nTime - prev nTime, seconds)
  76   *  nAggregateSeconds: total fork seconds emitted so far
  77   *  nSubsidyHalvingInterval: blocks-per-halving (210000)
  78   */
  79  inline CAmount GetForkBlockSubsidy(int64_t e, int64_t nAggregateSeconds, int nSubsidyHalvingInterval)
  80  {
  81      int64_t halvings = nAggregateSeconds / (600 * nSubsidyHalvingInterval);
  82      CAmount nSubsidy = 50 * COIN;
  83      if (halvings >= 63) return 0; // shift past the word width would be UB
  84      nSubsidy >>= halvings;
  85      if (nSubsidy == 0) return 0;
  86      return (nSubsidy * e) / 600;
  87  }
  88  
  89  /** Fork block payload weight limit: time-proportional, uncapped.
  90   *  payload = S_max * e / 600 (header+coinbase subtracted by the
  91   *  caller).  A late block can clear the backlog accumulated during a
  92   *  stall. */
  93  inline int64_t GetForkPayloadWeightLimit(int64_t e, int64_t nMaxPayloadWeight)
  94  {
  95      return (nMaxPayloadWeight * e) / 600;
  96  }
  97  
  98  
  99  class CBlock : public CBlockHeader
 100  {
 101  public:
 102      // network and disk
 103      std::vector<CTransactionRef> vtx;
 104  
 105      // Memory-only flags for caching expensive checks
 106      mutable bool fChecked;                            // CheckBlock()
 107      mutable bool m_checked_witness_commitment{false}; // CheckWitnessCommitment()
 108      mutable bool m_checked_merkle_root{false};        // CheckMerkleRoot()
 109  
 110      CBlock()
 111      {
 112          SetNull();
 113      }
 114  
 115      CBlock(const CBlockHeader &header)
 116      {
 117          SetNull();
 118          *(static_cast<CBlockHeader*>(this)) = header;
 119      }
 120  
 121      SERIALIZE_METHODS(CBlock, obj)
 122      {
 123          READWRITE(AsBase<CBlockHeader>(obj), obj.vtx);
 124      }
 125  
 126      void SetNull()
 127      {
 128          CBlockHeader::SetNull();
 129          vtx.clear();
 130          fChecked = false;
 131          m_checked_witness_commitment = false;
 132          m_checked_merkle_root = false;
 133      }
 134  
 135      CBlockHeader GetBlockHeader() const
 136      {
 137          CBlockHeader block;
 138          block.nVersion       = nVersion;
 139          block.hashPrevBlock  = hashPrevBlock;
 140          block.hashMerkleRoot = hashMerkleRoot;
 141          block.nTime          = nTime;
 142          block.nBits          = nBits;
 143          block.nNonce         = nNonce;
 144          return block;
 145      }
 146  
 147      std::string ToString() const;
 148  };
 149  
 150  /** Describes a place in the block chain to another node such that if the
 151   * other node doesn't have the same branch, it can find a recent common trunk.
 152   * The further back it is, the further before the fork it may be.
 153   */
 154  struct CBlockLocator
 155  {
 156      /** Historically CBlockLocator's version field has been written to network
 157       * streams as the negotiated protocol version and to disk streams as the
 158       * client version, but the value has never been used.
 159       *
 160       * Hard-code to the highest protocol version ever written to a network stream.
 161       * SerParams can be used if the field requires any meaning in the future,
 162       **/
 163      static constexpr int DUMMY_VERSION = 70016;
 164  
 165      std::vector<uint256> vHave;
 166  
 167      CBlockLocator() = default;
 168  
 169      explicit CBlockLocator(std::vector<uint256>&& have) : vHave(std::move(have)) {}
 170  
 171      SERIALIZE_METHODS(CBlockLocator, obj)
 172      {
 173          int nVersion = DUMMY_VERSION;
 174          READWRITE(nVersion);
 175          READWRITE(obj.vHave);
 176      }
 177  
 178      void SetNull()
 179      {
 180          vHave.clear();
 181      }
 182  
 183      bool IsNull() const
 184      {
 185          return vHave.empty();
 186      }
 187  };
 188  
 189  #endif // LIMENKA_PRIMITIVES_BLOCK_H
 190