Browse Source

Merge pull request #35 from ethereum-mining/header

BlockHeader cleanup
cl-refactor
Paweł Bylica 8 years ago
committed by GitHub
parent
commit
24c5633976
  1. 49
      libethcore/BlockHeader.cpp
  2. 121
      libethcore/BlockHeader.h
  3. 255
      libethcore/BlockInfo.h
  4. 1
      libethcore/CMakeLists.txt
  5. 2
      libethcore/EthashAux.cpp
  6. 2
      libethcore/EthashAux.h
  7. 2
      libethcore/Farm.h

49
libethcore/BlockInfo.cpp → libethcore/BlockHeader.cpp

@ -19,58 +19,31 @@
* @date 2014
*/
#include "BlockHeader.h"
#include <libdevcore/Common.h>
#include <libdevcore/Log.h>
#include <libdevcore/RLP.h>
#include "EthashAux.h"
#include "Exceptions.h"
#include "BlockInfo.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
namespace
{
h256 const EmptyTrie = sha3(rlp(""));
}
BlockInfo::BlockInfo(): m_timestamp(Invalid256)
{
}
BlockInfo::BlockInfo(bytesConstRef _block, Strictness _s, h256 const& _hashWith, BlockDataType _bdt)
{
RLP header = _bdt == BlockData ? extractHeader(_block) : RLP(_block);
m_hash = _hashWith ? _hashWith : sha3(header.data());
populateFromHeader(header, _s);
}
void BlockInfo::clear()
BlockHeader::BlockHeader(bytesConstRef _block)
{
m_parentHash = h256();
m_sha3Uncles = EmptyListSHA3;
m_coinbaseAddress = Address();
m_stateRoot = EmptyTrie;
m_transactionsRoot = EmptyTrie;
m_receiptsRoot = EmptyTrie;
m_logBloom = LogBloom();
m_difficulty = 0;
m_number = 0;
m_gasLimit = 0;
m_gasUsed = 0;
m_timestamp = 0;
m_extraData.clear();
noteDirty();
RLP header = extractHeader(_block);
populateFromHeader(header);
}
h256 const& BlockInfo::boundary() const
h256 const& BlockHeader::boundary() const
{
if (!m_boundary && m_difficulty)
m_boundary = (h256)(u256)((bigint(1) << 256) / m_difficulty);
return m_boundary;
}
h256 const& BlockInfo::hashWithout() const
h256 const& BlockHeader::hashWithout() const
{
if (!m_hashWithout)
{
@ -81,13 +54,13 @@ h256 const& BlockInfo::hashWithout() const
return m_hashWithout;
}
void BlockInfo::streamRLPFields(RLPStream& _s) const
void BlockHeader::streamRLPFields(RLPStream& _s) const
{
_s << m_parentHash << m_sha3Uncles << m_coinbaseAddress << m_stateRoot << m_transactionsRoot << m_receiptsRoot << m_logBloom
<< m_difficulty << m_number << m_gasLimit << m_gasUsed << m_timestamp << m_extraData;
}
RLP BlockInfo::extractHeader(bytesConstRef _block)
RLP BlockHeader::extractHeader(bytesConstRef _block)
{
RLP root(_block);
if (!root.isList())
@ -102,7 +75,7 @@ RLP BlockInfo::extractHeader(bytesConstRef _block)
return header;
}
void BlockInfo::populateFromHeader(RLP const& _header, Strictness _s)
void BlockHeader::populateFromHeader(RLP const& _header)
{
int field = 0;
try
@ -130,6 +103,6 @@ void BlockInfo::populateFromHeader(RLP const& _header, Strictness _s)
if (m_number > ~(unsigned)0)
BOOST_THROW_EXCEPTION(InvalidNumber());
if (_s != CheckNothing && m_gasUsed > m_gasLimit)
if (m_gasUsed > m_gasLimit)
BOOST_THROW_EXCEPTION(TooMuchGasUsed() << RequirementError(bigint(m_gasLimit), bigint(m_gasUsed)));
}

121
libethcore/BlockHeader.h

@ -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;
};
}
}

255
libethcore/BlockInfo.h

@ -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>;
}
}

1
libethcore/CMakeLists.txt

@ -1,6 +1,7 @@
file(GLOB SOURCES "*.cpp")
file(GLOB HEADERS "*.h")
include_directories(BEFORE ..)
add_library(ethcore ${SOURCES} ${HEADERS})

2
libethcore/EthashAux.cpp

@ -27,7 +27,7 @@ using namespace chrono;
using namespace dev;
using namespace eth;
h256 const& BlockHeaderRaw::seedHash() const
h256 const& BlockHeader::seedHash() const
{
if (!m_seedHash)
m_seedHash = EthashAux::seedHash((unsigned)m_number);

2
libethcore/EthashAux.h

@ -25,7 +25,7 @@
#include <libethash/ethash.h>
#include <libdevcore/Log.h>
#include <libdevcore/Worker.h>
#include "BlockInfo.h"
#include "BlockHeader.h"
namespace dev
{

2
libethcore/Farm.h

@ -27,7 +27,7 @@
#include <libdevcore/Common.h>
#include <libdevcore/Worker.h>
#include <libethcore/Miner.h>
#include <libethcore/BlockInfo.h>
#include <libethcore/BlockHeader.h>
namespace dev
{

Loading…
Cancel
Save