Ethereum  PoC-8
The C++ Implementation of Ethereum
BlockHeader.cpp
Go to the documentation of this file.
1 /*
2  This file is part of cpp-ethereum.
3 
4  cpp-ethereum is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  cpp-ethereum is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16 */
22 #include <libdevcore/Common.h>
23 #include <libdevcore/Log.h>
24 #include <libdevcore/RLP.h>
25 #include <libdevcore/TrieDB.h>
27 #include <libdevcore/TrieHash.h>
28 #include <libethcore/Common.h>
29 #include "Exceptions.h"
30 #include "BlockHeader.h"
31 using namespace std;
32 using namespace dev;
33 using namespace dev::eth;
34 
35 BlockHeader::BlockHeader()
36 {
37 }
38 
39 BlockHeader::BlockHeader(bytesConstRef _block, BlockDataType _bdt, h256 const& _hashWith)
40 {
41  RLP header = _bdt == BlockData ? extractHeader(_block) : RLP(_block);
42  m_hash = _hashWith ? _hashWith : sha3(header.data());
43  populate(header);
44 }
45 
46 BlockHeader::BlockHeader(BlockHeader const& _other) :
47  m_parentHash(_other.parentHash()),
48  m_sha3Uncles(_other.sha3Uncles()),
49  m_stateRoot(_other.stateRoot()),
50  m_transactionsRoot(_other.transactionsRoot()),
51  m_receiptsRoot(_other.receiptsRoot()),
52  m_logBloom(_other.logBloom()),
53  m_number(_other.number()),
54  m_gasLimit(_other.gasLimit()),
55  m_gasUsed(_other.gasUsed()),
56  m_extraData(_other.extraData()),
57  m_timestamp(_other.timestamp()),
58  m_author(_other.author()),
59  m_difficulty(_other.difficulty()),
60  m_seal(_other.seal()),
61  m_hash(_other.hashRawRead()),
62  m_hashWithout(_other.hashWithoutRawRead())
63 {
64  assert(*this == _other);
65 }
66 
68 {
69  if (this == &_other)
70  return *this;
71  m_parentHash = _other.parentHash();
72  m_sha3Uncles = _other.sha3Uncles();
73  m_stateRoot = _other.stateRoot();
74  m_transactionsRoot = _other.transactionsRoot();
75  m_receiptsRoot = _other.receiptsRoot();
76  m_logBloom = _other.logBloom();
77  m_number = _other.number();
78  m_gasLimit = _other.gasLimit();
79  m_gasUsed = _other.gasUsed();
80  m_extraData = _other.extraData();
81  m_timestamp = _other.timestamp();
82  m_author = _other.author();
83  m_difficulty = _other.difficulty();
84  std::vector<bytes> seal = _other.seal();
85  {
86  Guard l(m_sealLock);
87  m_seal = std::move(seal);
88  }
89  h256 hash = _other.hashRawRead();
90  h256 hashWithout = _other.hashWithoutRawRead();
91  {
92  Guard l(m_hashLock);
93  m_hash = std::move(hash);
94  m_hashWithout = std::move(hashWithout);
95  }
96  assert(*this == _other);
97  return *this;
98 }
99 
101 {
102  m_parentHash = h256();
103  m_sha3Uncles = EmptyListSHA3;
104  m_author = Address();
105  m_stateRoot = EmptyTrie;
106  m_transactionsRoot = EmptyTrie;
107  m_receiptsRoot = EmptyTrie;
108  m_logBloom = LogBloom();
109  m_difficulty = 0;
110  m_number = 0;
111  m_gasLimit = 0;
112  m_gasUsed = 0;
113  m_timestamp = -1;
114  m_extraData.clear();
115  m_seal.clear();
116  noteDirty();
117 }
118 
120 {
121  h256 dummy;
122  Guard l(m_hashLock);
123  h256& memo = _i == WithSeal ? m_hash : _i == WithoutSeal ? m_hashWithout : dummy;
124  if (!memo)
125  {
126  RLPStream s;
127  streamRLP(s, _i);
128  memo = sha3(s.out());
129  }
130  return memo;
131 }
132 
133 void BlockHeader::streamRLPFields(RLPStream& _s) const
134 {
135  _s << m_parentHash << m_sha3Uncles << m_author << m_stateRoot << m_transactionsRoot << m_receiptsRoot << m_logBloom
136  << m_difficulty << m_number << m_gasLimit << m_gasUsed << m_timestamp << m_extraData;
137 }
138 
140 {
141  if (_i != OnlySeal)
142  {
143  _s.appendList(BlockHeader::BasicFields + (_i == WithoutSeal ? 0 : m_seal.size()));
144  BlockHeader::streamRLPFields(_s);
145  }
146  if (_i != WithoutSeal)
147  for (unsigned i = 0; i < m_seal.size(); ++i)
148  _s.appendRaw(m_seal[i]);
149 }
150 
152 {
153  return sha3(RLP(_block)[0].data());
154 }
155 
157 {
158  RLP root(_block);
159  if (!root.isList())
160  BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("Block must be a list") << BadFieldError(0, _block.toString()));
161  RLP header = root[0];
162  if (!header.isList())
163  BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("Block header must be a list") << BadFieldError(0, header.data().toString()));
164  if (!root[1].isList())
165  BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("Block transactions must be a list") << BadFieldError(1, root[1].data().toString()));
166  if (!root[2].isList())
167  BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("Block uncles must be a list") << BadFieldError(2, root[2].data().toString()));
168  return header;
169 }
170 
171 void BlockHeader::populate(RLP const& _header)
172 {
173  int field = 0;
174  try
175  {
176  m_parentHash = _header[field = 0].toHash<h256>(RLP::VeryStrict);
177  m_sha3Uncles = _header[field = 1].toHash<h256>(RLP::VeryStrict);
178  m_author = _header[field = 2].toHash<Address>(RLP::VeryStrict);
179  m_stateRoot = _header[field = 3].toHash<h256>(RLP::VeryStrict);
180  m_transactionsRoot = _header[field = 4].toHash<h256>(RLP::VeryStrict);
181  m_receiptsRoot = _header[field = 5].toHash<h256>(RLP::VeryStrict);
182  m_logBloom = _header[field = 6].toHash<LogBloom>(RLP::VeryStrict);
183  m_difficulty = _header[field = 7].toInt<u256>();
184  m_number = _header[field = 8].toPositiveInt64();
185  m_gasLimit = _header[field = 9].toInt<u256>();
186  m_gasUsed = _header[field = 10].toInt<u256>();
187  m_timestamp = _header[field = 11].toPositiveInt64();
188  m_extraData = _header[field = 12].toBytes();
189  m_seal.clear();
190  for (unsigned i = 13; i < _header.itemCount(); ++i)
191  m_seal.push_back(_header[i].data().toBytes());
192  }
193  catch (Exception const& _e)
194  {
195  _e << errinfo_name("invalid block header format") << BadFieldError(field, toHex(_header[field].data().toBytes()));
196  throw;
197  }
198 }
199 
201 {
202  m_stateRoot = _parent.stateRoot();
203  m_number = _parent.m_number + 1;
204  m_parentHash = _parent.m_hash;
205  m_gasLimit = _parent.m_gasLimit;
206  m_difficulty = _parent.m_difficulty;
207  m_gasUsed = 0;
208 }
209 
210 void BlockHeader::verify(Strictness _s, BlockHeader const& _parent, bytesConstRef _block) const
211 {
212  if (m_number > ~(unsigned)0)
213  BOOST_THROW_EXCEPTION(InvalidNumber());
214 
215  if (_s != CheckNothingNew && m_gasUsed > m_gasLimit)
216  BOOST_THROW_EXCEPTION(TooMuchGasUsed() << RequirementError(bigint(m_gasLimit), bigint(m_gasUsed)));
217 
218  if (_parent)
219  {
220  if (m_parentHash && _parent.hash() != m_parentHash)
221  BOOST_THROW_EXCEPTION(InvalidParentHash());
222 
223  if (m_timestamp <= _parent.m_timestamp)
224  BOOST_THROW_EXCEPTION(InvalidTimestamp());
225 
226  if (m_number != _parent.m_number + 1)
227  BOOST_THROW_EXCEPTION(InvalidNumber());
228  }
229 
230  if (_block)
231  {
232  RLP root(_block);
233 
234  auto txList = root[1];
235  auto expectedRoot = trieRootOver(txList.itemCount(), [&](unsigned i){ return rlp(i); }, [&](unsigned i){ return txList[i].data().toBytes(); });
236 
237  LOG(m_logger) << "Expected trie root: " << toString(expectedRoot);
238  if (m_transactionsRoot != expectedRoot)
239  {
240  StateCacheDB tm;
241  GenericTrieDB<StateCacheDB> transactionsTrie(&tm);
242  transactionsTrie.init();
243 
244  vector<bytesConstRef> txs;
245 
246  for (unsigned i = 0; i < txList.itemCount(); ++i)
247  {
248  RLPStream k;
249  k << i;
250 
251  transactionsTrie.insert(&k.out(), txList[i].data());
252 
253  txs.push_back(txList[i].data());
254  cdebug << toHex(k.out()) << toHex(txList[i].data());
255  }
256  cdebug << "trieRootOver" << expectedRoot;
257  cdebug << "orderedTrieRoot" << orderedTrieRoot(txs);
258  cdebug << "TrieDB" << transactionsTrie.root();
259  cdebug << "Contents:";
260  for (auto const& t: txs)
261  cdebug << toHex(t);
262 
263  BOOST_THROW_EXCEPTION(InvalidTransactionsRoot() << Hash256RequirementError(expectedRoot, m_transactionsRoot));
264  }
265  LOG(m_logger) << "Expected uncle hash: " << toString(sha3(root[2].data()));
266  if (m_sha3Uncles != sha3(root[2].data()))
267  BOOST_THROW_EXCEPTION(InvalidUnclesHash() << Hash256RequirementError(sha3(root[2].data()), m_sha3Uncles));
268  }
269 }
_T toInt(int _flags=Strict) const
Converts to int of type given; if isData(), decodes as big-endian bytestream.
Definition: RLP.h:257
Definition: Address.cpp:20
bytes toBytes(int _flags=LaissezFaire) const
Converts to bytearray.
Definition: RLP.h:177
boost::tuple< errinfo_required_h256, errinfo_got_h256 > Hash256RequirementError
Definition: Exceptions.h:91
h256 const & receiptsRoot() const
Definition: BlockHeader.h:164
boost::error_info< struct tag_field, std::string > errinfo_name
Definition: Exceptions.h:33
u256 const & difficulty() const
Definition: BlockHeader.h:170
bytes rlp(_T _t)
Export a single item in RLP format, returning a byte array.
Definition: RLP.h:453
Merkle Patricia Tree "Trie": a modifed base-16 Radix tree. This version uses a database backend...
Definition: TrieDB.h:56
void populateFromParent(BlockHeader const &parent)
Encapsulation of a block header. Class to contain all of a block header&#39;s data. It is able to parse a...
Definition: BlockHeader.h:96
BlockHeader & operator=(BlockHeader const &_other)
Definition: BlockHeader.cpp:67
h160 Address
Definition: Address.h:30
static RLP extractHeader(bytesConstRef _block)
h256 const EmptyTrie
Definition: TrieCommon.cpp:28
Definition: FixedHash.h:390
Address const & author() const
Definition: BlockHeader.h:161
std::string toString(std::chrono::time_point< T > const &_e, std::string const &_format="%F %T")
Definition: CommonIO.h:86
int64_t number() const
Definition: BlockHeader.h:166
T seal(unsigned _offset=0) const
Definition: BlockHeader.h:171
bool sha3(bytesConstRef _input, bytesRef o_output) noexcept
Definition: SHA3.cpp:28
#define cdebug
boost::multiprecision::number< boost::multiprecision::cpp_int_backend<> > bigint
Definition: Common.h:118
int64_t timestamp() const
Definition: BlockHeader.h:160
Base class for all exceptions.
Definition: Exceptions.h:38
std::lock_guard< std::mutex > Guard
Definition: Guards.h:41
h256 const & parentHash() const
Definition: BlockHeader.h:157
static h256 headerHashFromBlock(bytes const &_block)
Definition: BlockHeader.h:108
bytesConstRef data() const
The bare data of the RLP.
Definition: RLP.h:80
h256 const & transactionsRoot() const
Definition: BlockHeader.h:163
h256 hash(IncludeSeal _i=WithSeal) const
static const unsigned BasicFields
Definition: BlockHeader.h:100
int64_t toPositiveInt64(int _flags=Strict) const
Definition: RLP.h:280
RLPStream & appendList(size_t _items)
Appends a list.
Definition: RLP.cpp:268
FixedHash< 32 > h256
Definition: FixedHash.h:354
h256 const EmptyListSHA3
Definition: SHA3.cpp:26
void streamRLP(RLPStream &_s, IncludeSeal _i=WithSeal) const
bytes const & out() const
Read the byte stream.
Definition: RLP.h:419
LogBloom const & logBloom() const
Definition: BlockHeader.h:169
h256 const & sha3Uncles() const
Definition: BlockHeader.h:158
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void > > u256
Definition: Common.h:121
boost::tuple< errinfo_field, errinfo_data > BadFieldError
Definition: Exceptions.h:43
#define LOG
Definition: Log.h:63
void noteDirty() const
Definition: BlockHeader.h:133
boost::error_info< struct tag_comment, std::string > errinfo_comment
Definition: Assertions.h:69
h256 trieRootOver(unsigned _itemCount, T const &_getKey, U const &_getValue)
Definition: TrieHash.h:36
size_t itemCount() const
Definition: RLP.h:101
std::string toString() const
Definition: vector_ref.h:44
u256 const & gasLimit() const
Definition: BlockHeader.h:167
h2048 LogBloom
The log bloom&#39;s size (2048-bit).
Definition: Common.h:69
void verify(Strictness _s=CheckEverything, BlockHeader const &_parent=BlockHeader(), bytesConstRef _block=bytesConstRef()) const
h256 orderedTrieRoot(std::vector< bytes > const &_data)
Definition: TrieHash.cpp:112
std::string toHex(Iterator _it, Iterator _end, std::string const &_prefix)
Definition: CommonData.h:46
bytes const & extraData() const
Definition: BlockHeader.h:168
void insert(bytes const &_key, bytes const &_value)
Definition: TrieDB.h:97
boost::tuple< errinfo_required, errinfo_got > RequirementError
Definition: Exceptions.h:86
Class for writing to an RLP bytestream.
Definition: RLP.h:369
_N toHash(int _flags=Strict) const
Definition: RLP.h:288
RLPStream & appendRaw(bytesConstRef _rlp, size_t _itemCount=1)
Appends raw (pre-serialised) RLP data. Use with caution.
Definition: RLP.cpp:222
Definition: RLP.h:47
h256 const & root() const
Definition: TrieDB.h:88
h256 const & stateRoot() const
Definition: BlockHeader.h:162
bool isList() const
List value.
Definition: RLP.h:95
u256 const & gasUsed() const
Definition: BlockHeader.h:165