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