1 // Aleth: Ethereum C++ client, tools and libraries.
2 // Copyright 2014-2019 Aleth Authors.
3 // Licensed under the GNU General Public License, Version 3.
4 
5 
6 #pragma once
7 
8 #include "ChainOperationParams.h"
9 #include "Common.h"
10 #include "Exceptions.h"
11 #include <libdevcore/Common.h>
12 #include <libdevcore/Guards.h>
13 #include <libdevcore/Log.h>
14 #include <libdevcore/RLP.h>
15 #include <libdevcore/SHA3.h>
16 #include <algorithm>
17 
18 namespace dev
19 {
20 namespace eth
21 {
22 
23 enum IncludeSeal
24 {
25     WithoutSeal = 0,
26     WithSeal = 1,
27     OnlySeal = 2
28 };
29 
30 enum Strictness
31 {
32     CheckEverything,
33     QuickNonce,
34     IgnoreSeal,
35     CheckNothingNew
36 };
37 
38 // TODO: for implementing soon.
39 /*enum Check
40 {
41     CheckBasic,
42     CheckExtended,
43     CheckBlock,
44     CheckParent,
45     CheckSeal,
46     CheckSealQuickly,
47     CheckAll = CheckBasic | CheckExtended | CheckBlock | CheckParent | CheckSeal,
48 };
49 using Checks = FlagSet<Check>;*/
50 
51 enum BlockDataType
52 {
53     HeaderData,
54     BlockData
55 };
56 
57 DEV_SIMPLE_EXCEPTION(NoHashRecorded);
58 DEV_SIMPLE_EXCEPTION(GenesisBlockCannotBeCalculated);
59 
60 /** @brief Encapsulation of a block header.
61  * Class to contain all of a block header's data. It is able to parse a block header and populate
62  * from some given RLP block serialisation with the static fromHeader(), through the method
63  * populate(). This will not conduct any verification above basic formating. In this case extra
64  * verification can be performed through verify().
65  *
66  * The object may also be populated from an entire block through the explicit
67  * constructor BlockHeader(bytesConstRef) and manually with the populate() method. These will
68  * conduct verification of the header against the other information in the block.
69  *
70  * The object may be populated with a template given a parent BlockHeader object with the
71  * populateFromParent() method. The genesis block info may be retrieved with genesis() and the
72  * corresponding RLP block created with createGenesisBlock().
73  *
74  * To determine the header hash without the nonce (for sealing), the method hash(WithoutNonce) is
75  * provided.
76  *
77  * The default constructor creates an empty object, which can be tested against with the boolean
78  * conversion operator.
79  */
80 class BlockHeader
81 {
82     friend class BlockChain;
83 public:
84     static const unsigned BasicFields = 13;
85 
86     BlockHeader();
87     explicit BlockHeader(bytesConstRef _data, BlockDataType _bdt = BlockData, h256 const& _hashWith = h256());
88     explicit BlockHeader(bytes const& _data, BlockDataType _bdt = BlockData, h256 const& _hashWith = h256()): BlockHeader(&_data, _bdt, _hashWith) {}
89     BlockHeader(BlockHeader const& _other);
90     BlockHeader& operator=(BlockHeader const& _other);
91 
headerHashFromBlock(bytes const & _block)92     static h256 headerHashFromBlock(bytes const& _block) { return headerHashFromBlock(&_block); }
93     static h256 headerHashFromBlock(bytesConstRef _block);
94     static RLP extractHeader(bytesConstRef _block);
95 
96     explicit operator bool() const { return m_timestamp >= 0; }
97 
98     bool operator==(BlockHeader const& _cmp) const
99     {
100         return m_parentHash == _cmp.parentHash() &&
101             m_sha3Uncles == _cmp.sha3Uncles() &&
102             m_author == _cmp.author() &&
103             m_stateRoot == _cmp.stateRoot() &&
104             m_transactionsRoot == _cmp.transactionsRoot() &&
105             m_receiptsRoot == _cmp.receiptsRoot() &&
106             m_logBloom == _cmp.logBloom() &&
107             m_difficulty == _cmp.difficulty() &&
108             m_number == _cmp.number() &&
109             m_gasLimit == _cmp.gasLimit() &&
110             m_gasUsed == _cmp.gasUsed() &&
111             m_timestamp == _cmp.timestamp() &&
112             m_extraData == _cmp.extraData();
113     }
114     bool operator!=(BlockHeader const& _cmp) const { return !operator==(_cmp); }
115 
116     void clear();
noteDirty()117     void noteDirty() const { Guard l(m_hashLock); m_hashWithout = m_hash = h256(); }
118     void populateFromParent(BlockHeader const& parent);
119 
120     // TODO: pull out into abstract class Verifier.
121     void verify(Strictness _s = CheckEverything, BlockHeader const& _parent = BlockHeader(), bytesConstRef _block = bytesConstRef()) const;
verify(Strictness _s,bytesConstRef _block)122     void verify(Strictness _s, bytesConstRef _block) const { verify(_s, BlockHeader(), _block); }
123 
124     h256 hash(IncludeSeal _i = WithSeal) const;
125     void streamRLP(RLPStream& _s, IncludeSeal _i = WithSeal) const;
126 
setParentHash(h256 const & _v)127     void setParentHash(h256 const& _v) { m_parentHash = _v; noteDirty(); }
setSha3Uncles(h256 const & _v)128     void setSha3Uncles(h256 const& _v) { m_sha3Uncles = _v; noteDirty(); }
setTimestamp(int64_t _v)129     void setTimestamp(int64_t _v) { m_timestamp = _v; noteDirty(); }
setAuthor(Address const & _v)130     void setAuthor(Address const& _v) { m_author = _v; noteDirty(); }
setRoots(h256 const & _t,h256 const & _r,h256 const & _u,h256 const & _s)131     void setRoots(h256 const& _t, h256 const& _r, h256 const& _u, h256 const& _s) { m_transactionsRoot = _t; m_receiptsRoot = _r; m_stateRoot = _s; m_sha3Uncles = _u; noteDirty(); }
setGasUsed(u256 const & _v)132     void setGasUsed(u256 const& _v) { m_gasUsed = _v; noteDirty(); }
setNumber(int64_t _v)133     void setNumber(int64_t _v) { m_number = _v; noteDirty(); }
setGasLimit(u256 const & _v)134     void setGasLimit(u256 const& _v) { m_gasLimit = _v; noteDirty(); }
setExtraData(bytes const & _v)135     void setExtraData(bytes const& _v) { m_extraData = _v; noteDirty(); }
setLogBloom(LogBloom const & _v)136     void setLogBloom(LogBloom const& _v) { m_logBloom = _v; noteDirty(); }
setDifficulty(u256 const & _v)137     void setDifficulty(u256 const& _v) { m_difficulty = _v; noteDirty(); }
setSeal(unsigned _offset,T const & _value)138     template <class T> void setSeal(unsigned _offset, T const& _value) { Guard l(m_sealLock); if (m_seal.size() <= _offset) m_seal.resize(_offset + 1); m_seal[_offset] = rlp(_value); noteDirty(); }
setSeal(T const & _value)139     template <class T> void setSeal(T const& _value) { setSeal(0, _value); }
140 
parentHash()141     h256 const& parentHash() const { return m_parentHash; }
sha3Uncles()142     h256 const& sha3Uncles() const { return m_sha3Uncles; }
hasUncles()143     bool hasUncles() const { return m_sha3Uncles != EmptyListSHA3; }
timestamp()144     int64_t timestamp() const { return m_timestamp; }
author()145     Address const& author() const { return m_author; }
stateRoot()146     h256 const& stateRoot() const { return m_stateRoot; }
transactionsRoot()147     h256 const& transactionsRoot() const { return m_transactionsRoot; }
receiptsRoot()148     h256 const& receiptsRoot() const { return m_receiptsRoot; }
gasUsed()149     u256 const& gasUsed() const { return m_gasUsed; }
number()150     int64_t number() const { return m_number; }
gasLimit()151     u256 const& gasLimit() const { return m_gasLimit; }
extraData()152     bytes const& extraData() const { return m_extraData; }
logBloom()153     LogBloom const& logBloom() const { return m_logBloom; }
difficulty()154     u256 const& difficulty() const { return m_difficulty; }
155     template <class T> T seal(unsigned _offset = 0) const { T ret; Guard l(m_sealLock); if (_offset < m_seal.size()) ret = RLP(m_seal[_offset]).convert<T>(RLP::VeryStrict); return ret; }
156 
157 private:
158     void populate(RLP const& _header);
159     void streamRLPFields(RLPStream& _s) const;
seal()160     std::vector<bytes> seal() const
161     {
162         Guard l(m_sealLock);
163         return m_seal;
164     }
hashRawRead()165     h256 hashRawRead() const
166     {
167         Guard l(m_hashLock);
168         return m_hash;
169     }
hashWithoutRawRead()170     h256 hashWithoutRawRead() const
171     {
172         Guard l(m_hashLock);
173         return m_hashWithout;
174     }
175 
176     h256 m_parentHash;
177     h256 m_sha3Uncles;
178     h256 m_stateRoot;
179     h256 m_transactionsRoot;
180     h256 m_receiptsRoot;
181     LogBloom m_logBloom;
182     int64_t m_number = 0;
183     u256 m_gasLimit;
184     u256 m_gasUsed;
185     bytes m_extraData;
186     int64_t m_timestamp = -1;
187 
188     Address m_author;
189     u256 m_difficulty;
190 
191     std::vector<bytes> m_seal;		///< Additional (RLP-encoded) header fields.
192     mutable Mutex m_sealLock;
193 
194     mutable h256 m_hash;			///< (Memoised) SHA3 hash of the block header with seal.
195     mutable h256 m_hashWithout;		///< (Memoised) SHA3 hash of the block header without seal.
196     mutable Mutex m_hashLock;		///< A lock for both m_hash and m_hashWithout.
197 
198     mutable Logger m_logger{createLogger(VerbosityDebug, "blockhdr")};
199 };
200 
201 inline std::ostream& operator<<(std::ostream& _out, BlockHeader const& _bi)
202 {
203     _out << _bi.hash(WithoutSeal) << " " << _bi.parentHash() << " " << _bi.sha3Uncles() << " " << _bi.author() << " " << _bi.stateRoot() << " " << _bi.transactionsRoot() << " " <<
204             _bi.receiptsRoot() << " " << _bi.logBloom() << " " << _bi.difficulty() << " " << _bi.number() << " " << _bi.gasLimit() << " " <<
205             _bi.gasUsed() << " " << _bi.timestamp();
206     return _out;
207 }
208 
209 }
210 }
211