Paweł Bylica
8 years ago
committed by
GitHub
7 changed files with 136 additions and 296 deletions
@ -0,0 +1,121 @@ |
|||||
|
/*
|
||||
|
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 <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file BlockInfo.h
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <libdevcore/Common.h> |
||||
|
#include <libdevcore/RLP.h> |
||||
|
#include <libdevcore/SHA3.h> |
||||
|
#include "Exceptions.h" |
||||
|
|
||||
|
namespace dev |
||||
|
{ |
||||
|
namespace eth |
||||
|
{ |
||||
|
|
||||
|
/// An Ethereum address: 20 bytes.
|
||||
|
using Address = h160; |
||||
|
|
||||
|
/// The log bloom's size (2048-bit).
|
||||
|
using LogBloom = h2048; |
||||
|
|
||||
|
using Nonce = h64; |
||||
|
|
||||
|
using BlockNumber = unsigned; |
||||
|
|
||||
|
|
||||
|
/** @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. |
||||
|
*/ |
||||
|
class BlockHeader |
||||
|
{ |
||||
|
public: |
||||
|
static const unsigned BasicFields = 13; |
||||
|
|
||||
|
BlockHeader() = default; |
||||
|
explicit BlockHeader(bytesConstRef _data); |
||||
|
explicit BlockHeader(bytes const& _data): BlockHeader(&_data) {} |
||||
|
|
||||
|
static RLP extractHeader(bytesConstRef _block); |
||||
|
|
||||
|
explicit operator bool() const { return m_timestamp != Invalid256; } |
||||
|
|
||||
|
h256 const& boundary() const; |
||||
|
|
||||
|
void setNumber(u256 const& _v) { m_number = _v; noteDirty(); } |
||||
|
void setDifficulty(u256 const& _v) { m_difficulty = _v; noteDirty(); } |
||||
|
|
||||
|
u256 const& number() const { return m_number; } |
||||
|
|
||||
|
/// sha3 of the header only.
|
||||
|
h256 const& hashWithout() const; |
||||
|
|
||||
|
void noteDirty() const { m_hashWithout = m_boundary = h256(); } |
||||
|
|
||||
|
h256 const& seedHash() const; |
||||
|
Nonce const& nonce() const { return m_nonce; } |
||||
|
|
||||
|
private: |
||||
|
void populateFromHeader(RLP const& _header); |
||||
|
void streamRLPFields(RLPStream& _s) const; |
||||
|
|
||||
|
h256 m_parentHash; |
||||
|
h256 m_sha3Uncles; |
||||
|
Address m_coinbaseAddress; |
||||
|
h256 m_stateRoot; |
||||
|
h256 m_transactionsRoot; |
||||
|
h256 m_receiptsRoot; |
||||
|
LogBloom m_logBloom; |
||||
|
u256 m_number; |
||||
|
u256 m_gasLimit; |
||||
|
u256 m_gasUsed; |
||||
|
u256 m_timestamp = Invalid256; |
||||
|
bytes m_extraData; |
||||
|
|
||||
|
u256 m_difficulty; |
||||
|
|
||||
|
mutable h256 m_hashWithout; ///< SHA3 hash of the block header! Not serialised.
|
||||
|
mutable h256 m_boundary; ///< 2^256 / difficulty
|
||||
|
|
||||
|
Nonce m_nonce; |
||||
|
mutable h256 m_seedHash; |
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
} |
@ -1,255 +0,0 @@ |
|||||
/*
|
|
||||
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 <http://www.gnu.org/licenses/>.
|
|
||||
*/ |
|
||||
/** @file BlockInfo.h
|
|
||||
* @author Gav Wood <i@gavwood.com> |
|
||||
* @date 2014 |
|
||||
*/ |
|
||||
|
|
||||
#pragma once |
|
||||
|
|
||||
#include <libdevcore/Common.h> |
|
||||
#include <libdevcore/RLP.h> |
|
||||
#include <libdevcore/SHA3.h> |
|
||||
#include "Exceptions.h" |
|
||||
|
|
||||
namespace dev |
|
||||
{ |
|
||||
namespace eth |
|
||||
{ |
|
||||
|
|
||||
/// An Ethereum address: 20 bytes.
|
|
||||
using Address = h160; |
|
||||
|
|
||||
/// The log bloom's size (2048-bit).
|
|
||||
using LogBloom = h2048; |
|
||||
|
|
||||
using Nonce = h64; |
|
||||
|
|
||||
using BlockNumber = unsigned; |
|
||||
|
|
||||
enum IncludeProof |
|
||||
{ |
|
||||
WithoutProof = 0, |
|
||||
WithProof = 1 |
|
||||
}; |
|
||||
|
|
||||
enum Strictness |
|
||||
{ |
|
||||
CheckEverything, |
|
||||
JustSeal, |
|
||||
QuickNonce, |
|
||||
IgnoreSeal, |
|
||||
CheckNothing |
|
||||
}; |
|
||||
|
|
||||
enum BlockDataType |
|
||||
{ |
|
||||
HeaderData, |
|
||||
BlockData |
|
||||
}; |
|
||||
|
|
||||
DEV_SIMPLE_EXCEPTION(NoHashRecorded); |
|
||||
DEV_SIMPLE_EXCEPTION(GenesisBlockCannotBeCalculated); |
|
||||
|
|
||||
/** @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. |
|
||||
*/ |
|
||||
class BlockInfo |
|
||||
{ |
|
||||
public: |
|
||||
static const unsigned BasicFields = 13; |
|
||||
|
|
||||
BlockInfo(); |
|
||||
explicit BlockInfo(bytesConstRef _data, Strictness _s = CheckEverything, h256 const& _hashWith = h256(), BlockDataType _bdt = BlockData); |
|
||||
explicit BlockInfo(bytes const& _data, Strictness _s = CheckEverything, h256 const& _hashWith = h256(), BlockDataType _bdt = BlockData): BlockInfo(&_data, _s, _hashWith, _bdt) {} |
|
||||
|
|
||||
static RLP extractHeader(bytesConstRef _block); |
|
||||
|
|
||||
explicit operator bool() const { return m_timestamp != Invalid256; } |
|
||||
|
|
||||
bool operator==(BlockInfo const& _cmp) const |
|
||||
{ |
|
||||
return m_parentHash == _cmp.parentHash() && |
|
||||
m_sha3Uncles == _cmp.sha3Uncles() && |
|
||||
m_coinbaseAddress == _cmp.beneficiary() && |
|
||||
m_stateRoot == _cmp.stateRoot() && |
|
||||
m_transactionsRoot == _cmp.transactionsRoot() && |
|
||||
m_receiptsRoot == _cmp.receiptsRoot() && |
|
||||
m_logBloom == _cmp.logBloom() && |
|
||||
m_difficulty == _cmp.difficulty() && |
|
||||
m_number == _cmp.number() && |
|
||||
m_gasLimit == _cmp.gasLimit() && |
|
||||
m_gasUsed == _cmp.gasUsed() && |
|
||||
m_timestamp == _cmp.timestamp() && |
|
||||
m_extraData == _cmp.extraData(); |
|
||||
} |
|
||||
bool operator!=(BlockInfo const& _cmp) const { return !operator==(_cmp); } |
|
||||
|
|
||||
h256 const& boundary() const; |
|
||||
|
|
||||
h256 const& parentHash() const { return m_parentHash; } |
|
||||
h256 const& sha3Uncles() const { return m_sha3Uncles; } |
|
||||
|
|
||||
void setNumber(u256 const& _v) { m_number = _v; noteDirty(); } |
|
||||
void setDifficulty(u256 const& _v) { m_difficulty = _v; noteDirty(); } |
|
||||
|
|
||||
Address const& beneficiary() const { return m_coinbaseAddress; } |
|
||||
h256 const& stateRoot() const { return m_stateRoot; } |
|
||||
h256 const& transactionsRoot() const { return m_transactionsRoot; } |
|
||||
h256 const& receiptsRoot() const { return m_receiptsRoot; } |
|
||||
LogBloom const& logBloom() const { return m_logBloom; } |
|
||||
u256 const& number() const { return m_number; } |
|
||||
u256 const& gasLimit() const { return m_gasLimit; } |
|
||||
u256 const& gasUsed() const { return m_gasUsed; } |
|
||||
u256 const& timestamp() const { return m_timestamp; } |
|
||||
bytes const& extraData() const { return m_extraData; } |
|
||||
|
|
||||
u256 const& difficulty() const { return m_difficulty; } // TODO: pull out into BlockHeader
|
|
||||
|
|
||||
/// sha3 of the header only.
|
|
||||
h256 const& hashWithout() const; |
|
||||
h256 const& hash() const { if (m_hash) return m_hash; BOOST_THROW_EXCEPTION(NoHashRecorded()); } |
|
||||
|
|
||||
void clear(); |
|
||||
void noteDirty() const { m_hashWithout = m_boundary = m_hash = h256(); } |
|
||||
|
|
||||
protected: |
|
||||
void populateFromHeader(RLP const& _header, Strictness _s = IgnoreSeal); |
|
||||
void streamRLPFields(RLPStream& _s) const; |
|
||||
|
|
||||
mutable h256 m_hash; ///< SHA3 hash of the block header! Not serialised.
|
|
||||
|
|
||||
h256 m_parentHash; |
|
||||
h256 m_sha3Uncles; |
|
||||
Address m_coinbaseAddress; |
|
||||
h256 m_stateRoot; |
|
||||
h256 m_transactionsRoot; |
|
||||
h256 m_receiptsRoot; |
|
||||
LogBloom m_logBloom; |
|
||||
u256 m_number; |
|
||||
u256 m_gasLimit; |
|
||||
u256 m_gasUsed; |
|
||||
u256 m_timestamp = Invalid256; |
|
||||
bytes m_extraData; |
|
||||
|
|
||||
u256 m_difficulty; // TODO: pull out into BlockHeader
|
|
||||
|
|
||||
private: |
|
||||
mutable h256 m_hashWithout; ///< SHA3 hash of the block header! Not serialised.
|
|
||||
mutable h256 m_boundary; ///< 2^256 / difficulty
|
|
||||
}; |
|
||||
|
|
||||
template <class BlockInfoSub> |
|
||||
class BlockHeaderPolished: public BlockInfoSub |
|
||||
{ |
|
||||
public: |
|
||||
BlockHeaderPolished() {} |
|
||||
BlockHeaderPolished(BlockInfo const& _bi): BlockInfoSub(_bi) {} |
|
||||
explicit BlockHeaderPolished(bytes const& _data, Strictness _s = IgnoreSeal, h256 const& _h = h256(), BlockDataType _bdt = BlockData) { populate(&_data, _s, _h, _bdt); } |
|
||||
explicit BlockHeaderPolished(bytesConstRef _data, Strictness _s = IgnoreSeal, h256 const& _h = h256(), BlockDataType _bdt = BlockData) { populate(_data, _s, _h, _bdt); } |
|
||||
|
|
||||
// deprecated for public API - use constructor.
|
|
||||
// TODO: make private.
|
|
||||
void populate(bytesConstRef _data, Strictness _s, h256 const& _h = h256(), BlockDataType _bdt = BlockData) |
|
||||
{ |
|
||||
populateFromHeader(_bdt == BlockData ? BlockInfo::extractHeader(_data) : RLP(_data), _s, _h); |
|
||||
} |
|
||||
|
|
||||
// deprecated for public API - use constructor.
|
|
||||
// TODO: make private.
|
|
||||
void populateFromHeader(RLP const& _header, Strictness _s = IgnoreSeal, h256 const& _h = h256()) |
|
||||
{ |
|
||||
BlockInfo::m_hash = _h; |
|
||||
if (_h) |
|
||||
assert(_h == dev::sha3(_header.data())); |
|
||||
else |
|
||||
BlockInfo::m_hash = dev::sha3(_header.data()); |
|
||||
|
|
||||
if (_header.itemCount() != BlockInfo::BasicFields + BlockInfoSub::SealFields) |
|
||||
BOOST_THROW_EXCEPTION(InvalidBlockHeaderItemCount()); |
|
||||
|
|
||||
BlockInfo::populateFromHeader(_header, _s); |
|
||||
BlockInfoSub::populateFromHeader(_header, _s); |
|
||||
} |
|
||||
|
|
||||
void clear() { BlockInfo::clear(); BlockInfoSub::clear(); BlockInfoSub::noteDirty(); } |
|
||||
void noteDirty() const { BlockInfo::noteDirty(); BlockInfoSub::noteDirty(); } |
|
||||
|
|
||||
h256 headerHash(IncludeProof _i = WithProof) const |
|
||||
{ |
|
||||
RLPStream s; |
|
||||
streamRLP(s, _i); |
|
||||
return sha3(s.out()); |
|
||||
} |
|
||||
|
|
||||
h256 const& hash() const |
|
||||
{ |
|
||||
if (!BlockInfo::m_hash) |
|
||||
BlockInfo::m_hash = headerHash(WithProof); |
|
||||
return BlockInfo::m_hash; |
|
||||
} |
|
||||
|
|
||||
void streamRLP(RLPStream& _s, IncludeProof _i = WithProof) const |
|
||||
{ |
|
||||
_s.appendList(BlockInfo::BasicFields + (_i == WithProof ? BlockInfoSub::SealFields : 0)); |
|
||||
BlockInfo::streamRLPFields(_s); |
|
||||
if (_i == WithProof) |
|
||||
BlockInfoSub::streamRLPFields(_s); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
class BlockHeaderRaw: public BlockInfo |
|
||||
{ |
|
||||
public: |
|
||||
h256 const& seedHash() const; |
|
||||
Nonce const& nonce() const { return m_nonce; } |
|
||||
|
|
||||
protected: |
|
||||
BlockHeaderRaw() = default; |
|
||||
BlockHeaderRaw(BlockInfo const& _bi): BlockInfo(_bi) {} |
|
||||
|
|
||||
void clear() { m_mixHash = h256(); m_nonce = Nonce(); } |
|
||||
|
|
||||
private: |
|
||||
Nonce m_nonce; |
|
||||
h256 m_mixHash; |
|
||||
|
|
||||
mutable h256 m_seedHash; |
|
||||
}; |
|
||||
|
|
||||
using BlockHeader = BlockHeaderPolished<BlockHeaderRaw>; |
|
||||
|
|
||||
} |
|
||||
} |
|
Loading…
Reference in new issue