/* This file is part of cpp-ethereum. cpp-ethereum is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. cpp-ethereum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ /** @file BlockInfo.h * @author Gav Wood * @date 2014 */ #pragma once #include #include #include "Common.h" namespace dev { namespace eth { enum IncludeNonce { WithoutNonce = 0, WithNonce = 1 }; enum Strictness { CheckEverything, IgnoreNonce, CheckNothing }; /** @brief Encapsulation of a block header. * Class to contain all of a block header's data. It is able to parse a block header and populate * from some given RLP block serialisation with the static fromHeader(), through the method * populateFromHeader(). This will conduct a minimal level of verification. In this case extra * verification can be performed through verifyInternals() and verifyParent(). * * The object may also be populated from an entire block through the explicit * constructor BlockInfo(bytesConstRef) and manually with the populate() method. These will * conduct verification of the header against the other information in the block. * * The object may be populated with a template given a parent BlockInfo object with the * populateFromParent() method. The genesis block info may be retrieved with genesis() and the * corresponding RLP block created with createGenesisBlock(). * * The difficulty and gas-limit derivations may be calculated with the calculateDifficulty() * and calculateGasLimit() and the object serialised to RLP with streamRLP. To determine the * header hash without the nonce (for mining), the method headerHash(WithoutNonce) is provided. * * The default constructor creates an empty object, which can be tested against with the boolean * conversion operator. */ struct BlockInfo { public: // TODO: make them all private! h256 parentHash; h256 sha3Uncles; Address coinbaseAddress; h256 stateRoot; h256 transactionsRoot; h256 receiptsRoot; LogBloom logBloom; u256 difficulty; u256 number; u256 gasLimit; u256 gasUsed; u256 timestamp = Invalid256; bytes extraData; h256 mixHash; Nonce nonce; BlockInfo(); explicit BlockInfo(bytes const& _block, Strictness _s = IgnoreNonce, h256 const& _h = h256()): BlockInfo(&_block, _s, _h) {} explicit BlockInfo(bytesConstRef _block, Strictness _s = IgnoreNonce, h256 const& _h = h256()); static h256 headerHash(bytes const& _block) { return headerHash(&_block); } static h256 headerHash(bytesConstRef _block); static BlockInfo fromHeader(bytes const& _header, Strictness _s = IgnoreNonce, h256 const& _h = h256()) { return fromHeader(bytesConstRef(&_header), _s, _h); } static BlockInfo fromHeader(bytesConstRef _header, Strictness _s = IgnoreNonce, h256 const& _h = h256()); explicit operator bool() const { return timestamp != Invalid256; } bool operator==(BlockInfo const& _cmp) const { return parentHash == _cmp.parentHash && sha3Uncles == _cmp.sha3Uncles && coinbaseAddress == _cmp.coinbaseAddress && stateRoot == _cmp.stateRoot && transactionsRoot == _cmp.transactionsRoot && receiptsRoot == _cmp.receiptsRoot && logBloom == _cmp.logBloom && difficulty == _cmp.difficulty && number == _cmp.number && gasLimit == _cmp.gasLimit && gasUsed == _cmp.gasUsed && timestamp == _cmp.timestamp && extraData == _cmp.extraData && mixHash == _cmp.mixHash && nonce == _cmp.nonce; } bool operator!=(BlockInfo const& _cmp) const { return !operator==(_cmp); } void clear(); void noteDirty() const { m_hash = m_seedHash = h256(); } void populateFromHeader(RLP const& _header, Strictness _s = IgnoreNonce, h256 const& _h = h256()); void populate(bytesConstRef _block, Strictness _s = IgnoreNonce, h256 const& _h = h256()); void populate(bytes const& _block, Strictness _s = IgnoreNonce, h256 const& _h = h256()) { populate(&_block, _s, _h); } void verifyInternals(bytesConstRef _block) const; void verifyParent(BlockInfo const& _parent) const; void populateFromParent(BlockInfo const& parent); u256 calculateDifficulty(BlockInfo const& _parent) const; u256 selectGasLimit(BlockInfo const& _parent) const; h256 const& seedHash() const; h256 const& hash() const; /// sha3 of the header only. h256 headerHash(IncludeNonce _n) const; void streamRLP(RLPStream& _s, IncludeNonce _n) const; private: mutable h256 m_seedHash; mutable h256 m_hash; ///< SHA3 hash of the block header! Not serialised. }; inline std::ostream& operator<<(std::ostream& _out, BlockInfo const& _bi) { _out << _bi.hash() << " " << _bi.parentHash << " " << _bi.sha3Uncles << " " << _bi.coinbaseAddress << " " << _bi.stateRoot << " " << _bi.transactionsRoot << " " << _bi.receiptsRoot << " " << _bi.logBloom << " " << _bi.difficulty << " " << _bi.number << " " << _bi.gasLimit << " " << _bi.gasUsed << " " << _bi.timestamp << " " << _bi.mixHash << " " << _bi.nonce << " (" << _bi.seedHash() << ")"; return _out; } } }