Fabcoin Core  0.16.2
P2P Digital Currency
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>
26 #include <libdevcore/TrieHash.h>
27 #include <libethcore/Common.h>
28 #include "Exceptions.h"
29 #include "BlockHeader.h"
30 using namespace std;
31 using namespace dev;
32 using namespace dev::eth;
33 
34 BlockHeader::BlockHeader()
35 {
36 }
37 
38 BlockHeader::BlockHeader(bytesConstRef _block, BlockDataType _bdt, h256 const& _hashWith)
39 {
40  RLP header = _bdt == BlockData ? extractHeader(_block) : RLP(_block);
41  m_hash = _hashWith ? _hashWith : sha3(header.data());
42  populate(header);
43 }
44 
45 void BlockHeader::clear()
46 {
47  m_parentHash = h256();
48  m_sha3Uncles = EmptyListSHA3;
49  m_author = Address();
50  m_stateRoot = EmptyTrie;
51  m_transactionsRoot = EmptyTrie;
52  m_receiptsRoot = EmptyTrie;
53  m_logBloom = LogBloom();
54  m_difficulty = 0;
55  m_number = 0;
56  m_gasLimit = 0;
57  m_gasUsed = 0;
58  m_timestamp = Invalid256;
59  m_extraData.clear();
60  m_seal.clear();
61  noteDirty();
62 }
63 
64 h256 BlockHeader::hash(IncludeSeal _i) const
65 {
66  h256 dummy;
67  h256& memo = _i == WithSeal ? m_hash : _i == WithoutSeal ? m_hashWithout : dummy;
68  if (!memo)
69  {
70  RLPStream s;
71  streamRLP(s, _i);
72  memo = sha3(s.out());
73  }
74  return memo;
75 }
76 
77 void BlockHeader::streamRLPFields(RLPStream& _s) const
78 {
79  _s << m_parentHash << m_sha3Uncles << m_author << m_stateRoot << m_transactionsRoot << m_receiptsRoot << m_logBloom
80  << m_difficulty << m_number << m_gasLimit << m_gasUsed << m_timestamp << m_extraData;
81 }
82 
83 void BlockHeader::streamRLP(RLPStream& _s, IncludeSeal _i) const
84 {
85  if (_i != OnlySeal)
86  {
87  _s.appendList(BlockHeader::BasicFields + (_i == WithoutSeal ? 0 : m_seal.size()));
88  BlockHeader::streamRLPFields(_s);
89  }
90  if (_i != WithoutSeal)
91  for (unsigned i = 0; i < m_seal.size(); ++i)
92  _s.appendRaw(m_seal[i]);
93 }
94 
95 h256 BlockHeader::headerHashFromBlock(bytesConstRef _block)
96 {
97  return sha3(RLP(_block)[0].data());
98 }
99 
100 RLP BlockHeader::extractHeader(bytesConstRef _block)
101 {
102  RLP root(_block);
103  if (!root.isList())
104  BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("Block must be a list") << BadFieldError(0, _block.toString()));
105  RLP header = root[0];
106  if (!header.isList())
107  BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("Block header must be a list") << BadFieldError(0, header.data().toString()));
108  if (!root[1].isList())
109  BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("Block transactions must be a list") << BadFieldError(1, root[1].data().toString()));
110  if (!root[2].isList())
111  BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("Block uncles must be a list") << BadFieldError(2, root[2].data().toString()));
112  return header;
113 }
114 
115 void BlockHeader::populate(RLP const& _header)
116 {
117  int field = 0;
118  try
119  {
120  m_parentHash = _header[field = 0].toHash<h256>(RLP::VeryStrict);
121  m_sha3Uncles = _header[field = 1].toHash<h256>(RLP::VeryStrict);
122  m_author = _header[field = 2].toHash<Address>(RLP::VeryStrict);
123  m_stateRoot = _header[field = 3].toHash<h256>(RLP::VeryStrict);
124  m_transactionsRoot = _header[field = 4].toHash<h256>(RLP::VeryStrict);
125  m_receiptsRoot = _header[field = 5].toHash<h256>(RLP::VeryStrict);
126  m_logBloom = _header[field = 6].toHash<LogBloom>(RLP::VeryStrict);
127  m_difficulty = _header[field = 7].toInt<u256>();
128  m_number = _header[field = 8].toInt<u256>();
129  m_gasLimit = _header[field = 9].toInt<u256>();
130  m_gasUsed = _header[field = 10].toInt<u256>();
131  m_timestamp = _header[field = 11].toInt<u256>();
132  m_extraData = _header[field = 12].toBytes();
133  m_seal.clear();
134  for (unsigned i = 13; i < _header.itemCount(); ++i)
135  m_seal.push_back(_header[i].data().toBytes());
136  }
137  catch (Exception const& _e)
138  {
139  _e << errinfo_name("invalid block header format") << BadFieldError(field, toHex(_header[field].data().toBytes()));
140  throw;
141  }
142 }
143 
144 struct BlockInfoDiagnosticsChannel: public LogChannel { static const char* name() { return EthBlue "▧" EthWhite " ◌"; } static const int verbosity = 9; };
145 
146 void BlockHeader::populateFromParent(BlockHeader const& _parent)
147 {
148  m_stateRoot = _parent.stateRoot();
149  m_number = _parent.m_number + 1;
150  m_parentHash = _parent.m_hash;
151  m_gasLimit = _parent.m_gasLimit;
152  m_difficulty = 1;
153  m_gasUsed = 0;
154 }
155 
156 void BlockHeader::verify(Strictness _s, BlockHeader const& _parent, bytesConstRef _block) const
157 {
158  if (m_number > ~(unsigned)0)
159  BOOST_THROW_EXCEPTION(InvalidNumber());
160 
161  if (_s != CheckNothingNew && m_gasUsed > m_gasLimit)
162  BOOST_THROW_EXCEPTION(TooMuchGasUsed() << RequirementError(bigint(m_gasLimit), bigint(m_gasUsed)));
163 
164  if (_parent)
165  {
166  if (m_parentHash && _parent.hash() != m_parentHash)
167  BOOST_THROW_EXCEPTION(InvalidParentHash());
168 
169  if (m_timestamp <= _parent.m_timestamp)
170  BOOST_THROW_EXCEPTION(InvalidTimestamp());
171 
172  if (m_number != _parent.m_number + 1)
173  BOOST_THROW_EXCEPTION(InvalidNumber());
174  }
175 
176  if (_block)
177  {
178  RLP root(_block);
179 
180  auto txList = root[1];
181  auto expectedRoot = trieRootOver(txList.itemCount(), [&](unsigned i){ return rlp(i); }, [&](unsigned i){ return txList[i].data().toBytes(); });
182 
183  clog(BlockInfoDiagnosticsChannel) << "Expected trie root:" << toString(expectedRoot);
184  if (m_transactionsRoot != expectedRoot)
185  {
186  MemoryDB tm;
187  GenericTrieDB<MemoryDB> transactionsTrie(&tm);
188  transactionsTrie.init();
189 
190  vector<bytesConstRef> txs;
191 
192  for (unsigned i = 0; i < txList.itemCount(); ++i)
193  {
194  RLPStream k;
195  k << i;
196 
197  transactionsTrie.insert(&k.out(), txList[i].data());
198 
199  txs.push_back(txList[i].data());
200  cdebug << toHex(k.out()) << toHex(txList[i].data());
201  }
202  cdebug << "trieRootOver" << expectedRoot;
203  cdebug << "orderedTrieRoot" << orderedTrieRoot(txs);
204  cdebug << "TrieDB" << transactionsTrie.root();
205  cdebug << "Contents:";
206  for (auto const& t: txs)
207  cdebug << toHex(t);
208 
209  BOOST_THROW_EXCEPTION(InvalidTransactionsRoot() << Hash256RequirementError(expectedRoot, m_transactionsRoot));
210  }
211  clog(BlockInfoDiagnosticsChannel) << "Expected uncle hash:" << toString(sha3(root[2].data()));
212  if (m_sha3Uncles != sha3(root[2].data()))
213  BOOST_THROW_EXCEPTION(InvalidUnclesHash() << Hash256RequirementError(sha3(root[2].data()), m_sha3Uncles));
214  }
215 }
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
Definition: Arith256.cpp:15
h256 m_hash
(Memoised) SHA3 hash of the block header with seal.
Definition: BlockHeader.h:190
std::string toHex(T const &_data, int _w=2, HexPrefix _prefix=HexPrefix::DontAdd)
Definition: CommonData.h:54
boost::tuple< errinfo_required_h256, errinfo_got_h256 > Hash256RequirementError
Definition: Exceptions.h:84
h256 EmptyListSHA3
Definition: SHA3.cpp:36
boost::error_info< struct tag_field, std::string > errinfo_name
Definition: Exceptions.h:33
bool isList() const
List value.
Definition: RLP.h:112
bytes rlp(_T _t)
Export a single item in RLP format, returning a byte array.
Definition: RLP.h:467
h256 const & stateRoot() const
Definition: BlockHeader.h:158
h256 hash(IncludeSeal _i=WithSeal) const
Definition: BlockHeader.cpp:64
bytesConstRef data() const
The bare data of the RLP.
Definition: RLP.h:97
Merkle Patricia Tree "Trie": a modifed base-16 Radix tree.
Definition: TrieDB.h:64
size_t itemCount() const
Definition: RLP.h:118
Encapsulation of a block header.
Definition: BlockHeader.h:95
boost::multiprecision::number< boost::multiprecision::cpp_int_backend<>> bigint
Definition: Common.h:121
bytes const & out() const
Read the byte stream.
Definition: RLP.h:433
bool verify(Public const &_k, Signature const &_s, h256 const &_hash)
Verify signature.
Definition: Common.cpp:255
h160 Address
An Ethereum address: 20 bytes.
Definition: Common.h:62
h256 const EmptyTrie
Definition: OverlayDB.cpp:33
std::hash for asio::adress
Definition: Common.h:323
std::string toString(string32 const &_s)
Make normal string from fixed-length string.
Definition: CommonData.cpp:141
#define cdebug
Definition: Log.h:302
_N toHash(int _flags=Strict) const
Definition: RLP.h:298
Base class for all exceptions.
Definition: Exceptions.h:39
const char * name
Definition: rest.cpp:36
h256 const & root() const
Definition: TrieDB.h:99
#define EthWhite
Definition: Terminal.h:119
std::vector< unsigned char > toBytes() const
Definition: vector_ref.h:45
const u256 Invalid256
Definition: Common.cpp:38
RLPStream & appendList(size_t _items)
Appends a list.
Definition: RLP.cpp:276
ANONYMOUS_NAMESPACE_BEGIN const CryptoPP::GF2_32 field
Definition: ida.cpp:14
FixedHash< 32 > h256
Definition: FixedHash.h:340
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void >> u256
Definition: Common.h:125
boost::tuple< errinfo_field, errinfo_data > BadFieldError
Definition: Exceptions.h:42
boost::error_info< struct tag_comment, std::string > errinfo_comment
Definition: Assertions.h:78
bool sha3(bytesConstRef _input, bytesRef o_output)
Calculate SHA3-256 hash of the given input and load it into the given output.
Definition: SHA3.cpp:214
h256 trieRootOver(unsigned _itemCount, T const &_getKey, U const &_getValue)
Definition: TrieHash.h:35
#define clog(X)
Definition: Log.h:295
The default logging channels.
Definition: Log.h:130
h2048 LogBloom
The log bloom&#39;s size (2048-bit).
Definition: Common.h:58
h256 orderedTrieRoot(std::vector< bytes > const &_data)
Definition: TrieHash.cpp:179
#define EthBlue
Definition: Terminal.h:127
void insert(bytes const &_key, bytes const &_value)
Definition: TrieDB.h:103
boost::tuple< errinfo_required, errinfo_got > RequirementError
Definition: Exceptions.h:80
_T toInt(int _flags=Strict) const
Converts to int of type given; if isString(), decodes as big-endian bytestream.
Definition: RLP.h:275
Class for writing to an RLP bytestream.
Definition: RLP.h:383
RLPStream & appendRaw(bytesConstRef _rlp, size_t _itemCount=1)
Appends raw (pre-serialised) RLP data. Use with caution.
Definition: RLP.cpp:230
uint8_t const * data
Definition: sha3.h:19
Class for interpreting Recursive Linear-Prefix Data.
Definition: RLP.h:64
std::string toString() const
Definition: vector_ref.h:46
bytes toBytes(int _flags=LaissezFaire) const
Converts to bytearray.
Definition: RLP.h:195