Browse Source

Move hash to a hidden function, and provide a datapath to it so avoid

unneeded SHA3s.
cl-refactor
Gav Wood 10 years ago
parent
commit
f2b56e7647
  1. 4
      alethzero/MainWin.cpp
  2. 33
      libethcore/BlockInfo.cpp
  3. 21
      libethcore/BlockInfo.h
  4. 3
      libethcore/Ethasher.cpp
  5. 18
      libethereum/BlockChain.cpp
  6. 4
      libethereum/BlockChain.h
  7. 16
      libethereum/Client.cpp
  8. 2
      libethereum/ClientBase.cpp
  9. 27
      libethereum/State.cpp
  10. 19
      libethereum/State.h
  11. 2
      libtestutils/StateLoader.cpp
  12. 2
      libweb3jsonrpc/WebThreeStubServerBase.cpp
  13. 2
      mix/ClientModel.cpp
  14. 2
      mix/MixClient.cpp
  15. 18
      test/ClientBase.cpp
  16. 7
      test/TestHelper.cpp
  17. 2
      test/TestHelper.h
  18. 6
      test/blockchain.cpp
  19. 2
      test/stateOriginal.cpp
  20. 4
      test/vm.cpp

4
alethzero/MainWin.cpp

@ -148,7 +148,7 @@ Main::Main(QWidget *parent) :
cerr << "State root: " << CanonBlockChain::genesis().stateRoot << endl; cerr << "State root: " << CanonBlockChain::genesis().stateRoot << endl;
auto block = CanonBlockChain::createGenesisBlock(); auto block = CanonBlockChain::createGenesisBlock();
cerr << "Block Hash: " << CanonBlockChain::genesis().hash << endl; cerr << "Block Hash: " << CanonBlockChain::genesis().hash() << endl;
cerr << "Block RLP: " << RLP(block) << endl; cerr << "Block RLP: " << RLP(block) << endl;
cerr << "Block Hex: " << toHex(block) << endl; cerr << "Block Hex: " << toHex(block) << endl;
cerr << "eth Network protocol version: " << eth::c_protocolVersion << endl; cerr << "eth Network protocol version: " << eth::c_protocolVersion << endl;
@ -1491,7 +1491,7 @@ void Main::on_blocks_currentItemChanged()
{ {
BlockInfo uncle = BlockInfo::fromHeader(u.data()); BlockInfo uncle = BlockInfo::fromHeader(u.data());
char const* line = "<div><span style=\"margin-left: 2em\">&nbsp;</span>"; char const* line = "<div><span style=\"margin-left: 2em\">&nbsp;</span>";
s << line << "Hash: <b>" << uncle.hash << "</b>" << "</div>"; s << line << "Hash: <b>" << uncle.hash() << "</b>" << "</div>";
s << line << "Parent: <b>" << uncle.parentHash << "</b>" << "</div>"; s << line << "Parent: <b>" << uncle.parentHash << "</b>" << "</div>";
s << line << "Number: <b>" << uncle.number << "</b>" << "</div>"; s << line << "Number: <b>" << uncle.number << "</b>" << "</div>";
s << line << "Coinbase: <b>" << pretty(uncle.coinbaseAddress).toHtmlEscaped().toStdString() << " " << uncle.coinbaseAddress << "</b>" << "</div>"; s << line << "Coinbase: <b>" << pretty(uncle.coinbaseAddress).toHtmlEscaped().toStdString() << " " << uncle.coinbaseAddress << "</b>" << "</div>";

33
libethcore/BlockInfo.cpp

@ -35,9 +35,9 @@ BlockInfo::BlockInfo(): timestamp(Invalid256)
{ {
} }
BlockInfo::BlockInfo(bytesConstRef _block, Strictness _s) BlockInfo::BlockInfo(bytesConstRef _block, Strictness _s, h256 const& _h)
{ {
populate(_block, _s); populate(_block, _s, _h);
} }
void BlockInfo::setEmpty() void BlockInfo::setEmpty()
@ -57,8 +57,7 @@ void BlockInfo::setEmpty()
extraData.clear(); extraData.clear();
mixHash = h256(); mixHash = h256();
nonce = Nonce(); nonce = Nonce();
m_seedHash = h256(); m_hash = m_seedHash = h256();
hash = headerHash(WithNonce);
} }
h256 const& BlockInfo::seedHash() const h256 const& BlockInfo::seedHash() const
@ -69,10 +68,17 @@ h256 const& BlockInfo::seedHash() const
return m_seedHash; return m_seedHash;
} }
BlockInfo BlockInfo::fromHeader(bytesConstRef _header, Strictness _s) h256 const& BlockInfo::hash() const
{
if (!m_hash)
m_hash = headerHash(WithNonce);
return m_hash;
}
BlockInfo BlockInfo::fromHeader(bytesConstRef _header, Strictness _s, h256 const& _h)
{ {
BlockInfo ret; BlockInfo ret;
ret.populateFromHeader(RLP(_header), _s); ret.populateFromHeader(RLP(_header), _s, _h);
return ret; return ret;
} }
@ -97,9 +103,11 @@ h256 BlockInfo::headerHash(bytesConstRef _block)
return sha3(RLP(_block)[0].data()); return sha3(RLP(_block)[0].data());
} }
void BlockInfo::populateFromHeader(RLP const& _header, Strictness _s) void BlockInfo::populateFromHeader(RLP const& _header, Strictness _s, h256 const& _h)
{ {
hash = dev::sha3(_header.data()); // m_hash = dev::sha3(_header.data());
m_hash = _h;
m_seedHash = h256();
int field = 0; int field = 0;
try try
@ -149,14 +157,14 @@ void BlockInfo::populateFromHeader(RLP const& _header, Strictness _s)
} }
} }
void BlockInfo::populate(bytesConstRef _block, Strictness _s) void BlockInfo::populate(bytesConstRef _block, Strictness _s, h256 const& _h)
{ {
RLP root(_block); RLP root(_block);
RLP header = root[0]; RLP header = root[0];
if (!header.isList()) if (!header.isList())
BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("block header needs to be a list") << BadFieldError(0, header.data().toString())); BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("block header needs to be a list") << BadFieldError(0, header.data().toString()));
populateFromHeader(header, _s); populateFromHeader(header, _s, _h);
if (!root[1].isList()) if (!root[1].isList())
BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("block transactions need to be a list") << BadFieldError(1, root[1].data().toString())); BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("block transactions need to be a list") << BadFieldError(1, root[1].data().toString()));
@ -191,8 +199,9 @@ void BlockInfo::verifyInternals(bytesConstRef _block) const
void BlockInfo::populateFromParent(BlockInfo const& _parent) void BlockInfo::populateFromParent(BlockInfo const& _parent)
{ {
m_hash = m_seedHash = h256();
stateRoot = _parent.stateRoot; stateRoot = _parent.stateRoot;
parentHash = _parent.hash; parentHash = _parent.hash();
number = _parent.number + 1; number = _parent.number + 1;
gasLimit = selectGasLimit(_parent); gasLimit = selectGasLimit(_parent);
gasUsed = 0; gasUsed = 0;
@ -230,7 +239,7 @@ void BlockInfo::verifyParent(BlockInfo const& _parent) const
// Check timestamp is after previous timestamp. // Check timestamp is after previous timestamp.
if (parentHash) if (parentHash)
{ {
if (parentHash != _parent.hash) if (parentHash != _parent.hash())
BOOST_THROW_EXCEPTION(InvalidParentHash()); BOOST_THROW_EXCEPTION(InvalidParentHash());
if (timestamp <= _parent.timestamp) if (timestamp <= _parent.timestamp)

21
libethcore/BlockInfo.h

@ -68,7 +68,6 @@ struct BlockInfo
{ {
public: public:
// TODO: make them all private! // TODO: make them all private!
h256 hash; ///< SHA3 hash of the block header! Not serialised (the only member not contained in a block header).
h256 parentHash; h256 parentHash;
h256 sha3Uncles; h256 sha3Uncles;
Address coinbaseAddress; Address coinbaseAddress;
@ -86,14 +85,14 @@ public:
Nonce nonce; Nonce nonce;
BlockInfo(); BlockInfo();
explicit BlockInfo(bytes const& _block, Strictness _s = IgnoreNonce): BlockInfo(&_block, _s) {} explicit BlockInfo(bytes const& _block, Strictness _s = IgnoreNonce, h256 const& _h = h256()): BlockInfo(&_block, _s, _h) {}
explicit BlockInfo(bytesConstRef _block, Strictness _s = IgnoreNonce); explicit BlockInfo(bytesConstRef _block, Strictness _s = IgnoreNonce, h256 const& _h = h256());
static h256 headerHash(bytes const& _block) { return headerHash(&_block); } static h256 headerHash(bytes const& _block) { return headerHash(&_block); }
static h256 headerHash(bytesConstRef _block); static h256 headerHash(bytesConstRef _block);
static BlockInfo fromHeader(bytes const& _header, Strictness _s = IgnoreNonce) { return fromHeader(bytesConstRef(&_header), _s); } 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); static BlockInfo fromHeader(bytesConstRef _header, Strictness _s = IgnoreNonce, h256 const& _h = h256());
explicit operator bool() const { return timestamp != Invalid256; } explicit operator bool() const { return timestamp != Invalid256; }
@ -119,9 +118,11 @@ public:
void setEmpty(); void setEmpty();
void populateFromHeader(RLP const& _header, Strictness _s = IgnoreNonce); void noteDirty() const { m_hash = m_seedHash= h256(); }
void populate(bytesConstRef _block, Strictness _s = IgnoreNonce);
void populate(bytes const& _block, Strictness _s = IgnoreNonce) { populate(&_block, _s); } 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 verifyInternals(bytesConstRef _block) const;
void verifyParent(BlockInfo const& _parent) const; void verifyParent(BlockInfo const& _parent) const;
void populateFromParent(BlockInfo const& parent); void populateFromParent(BlockInfo const& parent);
@ -129,6 +130,7 @@ public:
u256 calculateDifficulty(BlockInfo const& _parent) const; u256 calculateDifficulty(BlockInfo const& _parent) const;
u256 selectGasLimit(BlockInfo const& _parent) const; u256 selectGasLimit(BlockInfo const& _parent) const;
h256 const& seedHash() const; h256 const& seedHash() const;
h256 const& hash() const;
/// sha3 of the header only. /// sha3 of the header only.
h256 headerHash(IncludeNonce _n) const; h256 headerHash(IncludeNonce _n) const;
@ -136,11 +138,12 @@ public:
private: private:
mutable h256 m_seedHash; 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) inline std::ostream& operator<<(std::ostream& _out, BlockInfo const& _bi)
{ {
_out << _bi.hash << " " << _bi.parentHash << " " << _bi.sha3Uncles << " " << _bi.coinbaseAddress << " " << _bi.stateRoot << " " << _bi.transactionsRoot << " " << _out << _bi.hash() << " " << _bi.parentHash << " " << _bi.sha3Uncles << " " << _bi.coinbaseAddress << " " << _bi.stateRoot << " " << _bi.transactionsRoot << " " <<
_bi.receiptsRoot << " " << _bi.logBloom << " " << _bi.difficulty << " " << _bi.number << " " << _bi.gasLimit << " " << _bi.receiptsRoot << " " << _bi.logBloom << " " << _bi.difficulty << " " << _bi.number << " " << _bi.gasLimit << " " <<
_bi.gasUsed << " " << _bi.timestamp << " " << _bi.mixHash << " " << _bi.nonce << " (" << _bi.seedHash() << ")"; _bi.gasUsed << " " << _bi.timestamp << " " << _bi.mixHash << " " << _bi.nonce << " (" << _bi.seedHash() << ")";
return _out; return _out;

3
libethcore/Ethasher.cpp

@ -173,6 +173,9 @@ Ethasher::Result Ethasher::eval(BlockInfo const& _header, Nonce const& _nonce)
{ {
auto p = Ethasher::params(_header); auto p = Ethasher::params(_header);
ethash_return_value r; ethash_return_value r;
if (Ethasher::get()->m_fulls.count(_header.seedHash()))
ethash_compute_full(&r, Ethasher::get()->full(_header).data(), &p, _header.headerHash(WithoutNonce).data(), (uint64_t)(u64)_nonce);
else
ethash_compute_light(&r, Ethasher::get()->light(_header), &p, _header.headerHash(WithoutNonce).data(), (uint64_t)(u64)_nonce); ethash_compute_light(&r, Ethasher::get()->light(_header), &p, _header.headerHash(WithoutNonce).data(), (uint64_t)(u64)_nonce);
// cdebug << "Ethasher::eval sha3(cache):" << sha3(Ethasher::get()->cache(_header)) << "hh:" << _header.headerHash(WithoutNonce) << "nonce:" << _nonce << " => " << h256(r.result, h256::ConstructFromPointer); // cdebug << "Ethasher::eval sha3(cache):" << sha3(Ethasher::get()->cache(_header)) << "hh:" << _header.headerHash(WithoutNonce) << "nonce:" << _nonce << " => " << h256(r.result, h256::ConstructFromPointer);
return Result{h256(r.result, h256::ConstructFromPointer), h256(r.mix_hash, h256::ConstructFromPointer)}; return Result{h256(r.result, h256::ConstructFromPointer), h256(r.mix_hash, h256::ConstructFromPointer)};

18
libethereum/BlockChain.cpp

@ -33,6 +33,7 @@
#include <libethcore/Exceptions.h> #include <libethcore/Exceptions.h>
#include <libethcore/ProofOfWork.h> #include <libethcore/ProofOfWork.h>
#include <libethcore/BlockInfo.h> #include <libethcore/BlockInfo.h>
#include <libethcore/Ethasher.h>
#include <liblll/Compiler.h> #include <liblll/Compiler.h>
#include "GenesisInfo.h" #include "GenesisInfo.h"
#include "State.h" #include "State.h"
@ -200,7 +201,7 @@ void BlockChain::rebuild(std::string const& _path, std::function<void(unsigned,
ldb::DB::Open(o, _path + "/details", &m_extrasDB); ldb::DB::Open(o, _path + "/details", &m_extrasDB);
// Open a fresh state DB // Open a fresh state DB
State s(Address(), State::openDB(_path, WithExisting::Kill), BaseState::CanonGenesis); State s(State::openDB(_path, WithExisting::Kill), BaseState::CanonGenesis);
// Clear all memos ready for replay. // Clear all memos ready for replay.
m_details.clear(); m_details.clear();
@ -226,12 +227,15 @@ void BlockChain::rebuild(std::string const& _path, std::function<void(unsigned,
bytes b = block(queryExtras<BlockHash, ExtraBlockHash>(h256(u256(d)), m_blockHashes, x_blockHashes, NullBlockHash, oldExtrasDB).value); bytes b = block(queryExtras<BlockHash, ExtraBlockHash>(h256(u256(d)), m_blockHashes, x_blockHashes, NullBlockHash, oldExtrasDB).value);
BlockInfo bi(b); BlockInfo bi(b);
if (bi.number % c_ethashEpochLength == 1)
Ethasher::get()->full(bi);
if (bi.parentHash != lastHash) if (bi.parentHash != lastHash)
{ {
cwarn << "DISJOINT CHAIN DETECTED; " << bi.hash.abridged() << "#" << d << " -> parent is" << bi.parentHash.abridged() << "; expected" << lastHash.abridged() << "#" << (d - 1); cwarn << "DISJOINT CHAIN DETECTED; " << bi.hash().abridged() << "#" << d << " -> parent is" << bi.parentHash.abridged() << "; expected" << lastHash.abridged() << "#" << (d - 1);
return; return;
} }
lastHash = bi.hash; lastHash = bi.hash();
import(b, s.db(), true); import(b, s.db(), true);
} }
catch (...) catch (...)
@ -414,7 +418,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, bool _force)
{ {
// Check transactions are valid and that they result in a state equivalent to our state_root. // Check transactions are valid and that they result in a state equivalent to our state_root.
// Get total difficulty increase and update state, checking it. // Get total difficulty increase and update state, checking it.
State s(bi.coinbaseAddress, _db); State s(_db); //, bi.coinbaseAddress
auto tdIncrease = s.enactOn(&_block, bi, *this); auto tdIncrease = s.enactOn(&_block, bi, *this);
BlockLogBlooms blb; BlockLogBlooms blb;
@ -493,7 +497,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, bool _force)
{ {
clog(BlockChainWarn) << " Malformed block: " << diagnostic_information(_e); clog(BlockChainWarn) << " Malformed block: " << diagnostic_information(_e);
_e << errinfo_comment("Malformed block "); _e << errinfo_comment("Malformed block ");
clog(BlockChainWarn) << "Block: " << bi.hash; clog(BlockChainWarn) << "Block: " << bi.hash();
clog(BlockChainWarn) << bi; clog(BlockChainWarn) << bi;
clog(BlockChainWarn) << "Block parent: " << bi.parentHash; clog(BlockChainWarn) << "Block parent: " << bi.parentHash;
clog(BlockChainWarn) << BlockInfo(block(bi.parentHash)); clog(BlockChainWarn) << BlockInfo(block(bi.parentHash));
@ -560,7 +564,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, bool _force)
{ {
RLP blockRLP(b); RLP blockRLP(b);
TransactionAddress ta; TransactionAddress ta;
ta.blockHash = bi.hash; ta.blockHash = bi.hash();
WriteGuard l(x_transactionAddresses); WriteGuard l(x_transactionAddresses);
for (ta.index = 0; ta.index < blockRLP[1].itemCount(); ++ta.index) for (ta.index = 0; ta.index < blockRLP[1].itemCount(); ++ta.index)
{ {
@ -570,7 +574,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, bool _force)
} }
{ {
WriteGuard l(x_blockHashes); WriteGuard l(x_blockHashes);
m_blockHashes[h256(bi.number)].value = bi.hash; m_blockHashes[h256(bi.number)].value = bi.hash();
} }
// Update database with them. // Update database with them.

4
libethereum/BlockChain.h

@ -113,8 +113,8 @@ public:
bool isKnown(h256 const& _hash) const; bool isKnown(h256 const& _hash) const;
/// Get the familial details concerning a block (or the most recent mined if none given). Thread-safe. /// Get the familial details concerning a block (or the most recent mined if none given). Thread-safe.
BlockInfo info(h256 const& _hash) const { return BlockInfo(block(_hash)); } BlockInfo info(h256 const& _hash) const { return BlockInfo(block(_hash), IgnoreNonce, _hash); }
BlockInfo info() const { return BlockInfo(block()); } BlockInfo info() const { return info(currentHash()); }
/// Get a block (RLP format) for the given hash (or the most recent mined if none given). Thread-safe. /// Get a block (RLP format) for the given hash (or the most recent mined if none given). Thread-safe.
bytes block(h256 const& _hash) const; bytes block(h256 const& _hash) const;

16
libethereum/Client.cpp

@ -90,7 +90,7 @@ void BasicGasPricer::update(BlockChain const& _bc)
{ {
auto bb = _bc.block(p); auto bb = _bc.block(p);
RLP r(bb); RLP r(bb);
BlockReceipts brs(_bc.receipts(bi.hash)); BlockReceipts brs(_bc.receipts(bi.hash()));
for (unsigned i = 0; i < r[1].size(); ++i) for (unsigned i = 0; i < r[1].size(); ++i)
{ {
auto gu = brs.receipts[i].gasUsed(); auto gu = brs.receipts[i].gasUsed();
@ -123,8 +123,8 @@ Client::Client(p2p::Host* _extNet, std::string const& _dbPath, WithExisting _for
m_bc(_dbPath, max(m_vc.action(), _forceAction), [](unsigned d, unsigned t){ cerr << "REVISING BLOCKCHAIN: Processed " << d << " of " << t << "...\r"; }), m_bc(_dbPath, max(m_vc.action(), _forceAction), [](unsigned d, unsigned t){ cerr << "REVISING BLOCKCHAIN: Processed " << d << " of " << t << "...\r"; }),
m_gp(new TrivialGasPricer), m_gp(new TrivialGasPricer),
m_stateDB(State::openDB(_dbPath, max(m_vc.action(), _forceAction))), m_stateDB(State::openDB(_dbPath, max(m_vc.action(), _forceAction))),
m_preMine(Address(), m_stateDB), m_preMine(m_stateDB),
m_postMine(Address(), m_stateDB) m_postMine(m_stateDB)
{ {
m_gp->update(m_bc); m_gp->update(m_bc);
@ -148,8 +148,8 @@ Client::Client(p2p::Host* _extNet, std::shared_ptr<GasPricer> _gp, std::string c
m_bc(_dbPath, max(m_vc.action(), _forceAction), [](unsigned d, unsigned t){ cerr << "REVISING BLOCKCHAIN: Processed " << d << " of " << t << "...\r"; }), m_bc(_dbPath, max(m_vc.action(), _forceAction), [](unsigned d, unsigned t){ cerr << "REVISING BLOCKCHAIN: Processed " << d << " of " << t << "...\r"; }),
m_gp(_gp), m_gp(_gp),
m_stateDB(State::openDB(_dbPath, max(m_vc.action(), _forceAction))), m_stateDB(State::openDB(_dbPath, max(m_vc.action(), _forceAction))),
m_preMine(Address(), m_stateDB), m_preMine(m_stateDB),
m_postMine(Address(), m_stateDB) m_postMine(m_stateDB)
{ {
m_gp->update(m_bc); m_gp->update(m_bc);
@ -221,8 +221,8 @@ void Client::killChain()
} }
m_bc.reopen(Defaults::dbPath(), WithExisting::Kill); m_bc.reopen(Defaults::dbPath(), WithExisting::Kill);
m_preMine = State(Address(), m_stateDB); m_preMine = State(m_stateDB);
m_postMine = State(Address(), m_stateDB); m_postMine = State(m_stateDB);
if (auto h = m_host.lock()) if (auto h = m_host.lock())
h->reset(); h->reset();
@ -313,7 +313,7 @@ void Client::appendFromNewBlock(h256 const& _block, h256Set& io_changed)
auto m = i.second.filter.matches(tr); auto m = i.second.filter.matches(tr);
if (m.size()) if (m.size())
{ {
auto transactionHash = transaction(d.hash, j).sha3(); auto transactionHash = transaction(d.hash(), j).sha3();
// filter catches them // filter catches them
for (LogEntry const& l: m) for (LogEntry const& l: m)
i.second.changes.push_back(LocalisedLogEntry(l, (unsigned)d.number, transactionHash)); i.second.changes.push_back(LocalisedLogEntry(l, (unsigned)d.number, transactionHash));

2
libethereum/ClientBase.cpp

@ -182,7 +182,7 @@ LocalisedLogEntries ClientBase::logs(LogFilter const& _f) const
if (_f.matches(receipt.bloom())) if (_f.matches(receipt.bloom()))
{ {
auto info = bc().info(h); auto info = bc().info(h);
auto th = transaction(info.hash, i).sha3(); auto th = transaction(info.hash(), i).sha3();
LogEntries le = _f.matches(receipt); LogEntries le = _f.matches(receipt);
if (le.size()) if (le.size())
{ {

27
libethereum/State.cpp

@ -78,23 +78,24 @@ OverlayDB State::openDB(std::string _path, WithExisting _we)
return OverlayDB(db); return OverlayDB(db);
} }
State::State(Address _coinbaseAddress, OverlayDB const& _db, BaseState _bs): State::State(OverlayDB const& _db, BaseState _bs, Address _coinbaseAddress):
m_db(_db), m_db(_db),
m_state(&m_db), m_state(&m_db),
m_ourAddress(_coinbaseAddress), m_ourAddress(_coinbaseAddress),
m_blockReward(c_blockReward) m_blockReward(c_blockReward)
{ {
if (_bs != BaseState::PreExisting)
// Initialise to the state entailed by the genesis block; this guarantees the trie is built correctly. // Initialise to the state entailed by the genesis block; this guarantees the trie is built correctly.
m_state.init(); m_state.init();
paranoia("beginning of normal construction.", true); paranoia("beginning of Genesis construction.", true);
if (_bs == BaseState::CanonGenesis) if (_bs == BaseState::CanonGenesis)
{ {
dev::eth::commit(genesisState(), m_db, m_state); dev::eth::commit(genesisState(), m_db, m_state);
m_db.commit(); m_db.commit();
paranoia("after DB commit of normal construction.", true); paranoia("after DB commit of Genesis construction.", true);
m_previousBlock = CanonBlockChain::genesis(); m_previousBlock = CanonBlockChain::genesis();
} }
else else
@ -321,7 +322,7 @@ bool State::sync(BlockChain const& _bc, h256 _block, BlockInfo const& _bi)
std::vector<h256> chain; std::vector<h256> chain;
while (bi.number != 0 && m_db.lookup(bi.stateRoot).empty()) // while we don't have the state root of the latest block... while (bi.number != 0 && m_db.lookup(bi.stateRoot).empty()) // while we don't have the state root of the latest block...
{ {
chain.push_back(bi.hash); // push back for later replay. chain.push_back(bi.hash()); // push back for later replay.
bi.populate(_bc.block(bi.parentHash)); // move to parent. bi.populate(_bc.block(bi.parentHash)); // move to parent.
} }
@ -537,18 +538,18 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
{ {
// m_currentBlock is assumed to be prepopulated and reset. // m_currentBlock is assumed to be prepopulated and reset.
#if !ETH_RELEASE
BlockInfo bi(_block, _checkNonce ? CheckEverything : IgnoreNonce); BlockInfo bi(_block, _checkNonce ? CheckEverything : IgnoreNonce);
assert(m_previousBlock.hash == bi.parentHash); #if !ETH_RELEASE
assert(m_previousBlock.hash() == bi.parentHash);
assert(m_currentBlock.parentHash == bi.parentHash); assert(m_currentBlock.parentHash == bi.parentHash);
assert(rootHash() == m_previousBlock.stateRoot); assert(rootHash() == m_previousBlock.stateRoot);
#endif #endif
if (m_currentBlock.parentHash != m_previousBlock.hash) if (m_currentBlock.parentHash != m_previousBlock.hash())
BOOST_THROW_EXCEPTION(InvalidParentHash()); BOOST_THROW_EXCEPTION(InvalidParentHash());
// Populate m_currentBlock with the correct values. // Populate m_currentBlock with the correct values.
m_currentBlock.populate(_block, _checkNonce ? CheckEverything : IgnoreNonce); m_currentBlock = bi;
m_currentBlock.verifyInternals(_block); m_currentBlock.verifyInternals(_block);
// cnote << "playback begins:" << m_state.root(); // cnote << "playback begins:" << m_state.root();
@ -598,7 +599,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce)
cwarn << TransactionReceipt(&b); cwarn << TransactionReceipt(&b);
} }
cwarn << "Recorded: " << m_currentBlock.receiptsRoot; cwarn << "Recorded: " << m_currentBlock.receiptsRoot;
auto rs = _bc.receipts(m_currentBlock.hash); auto rs = _bc.receipts(m_currentBlock.hash());
for (unsigned j = 0; j < rs.receipts.size(); ++j) for (unsigned j = 0; j < rs.receipts.size(); ++j)
{ {
auto b = rs.receipts[j].rlp(); auto b = rs.receipts[j].rlp();
@ -840,7 +841,7 @@ void State::commitToMine(BlockChain const& _bc)
m_currentBlock.gasUsed = gasUsed(); m_currentBlock.gasUsed = gasUsed();
m_currentBlock.stateRoot = m_state.root(); m_currentBlock.stateRoot = m_state.root();
m_currentBlock.parentHash = m_previousBlock.hash; m_currentBlock.parentHash = m_previousBlock.hash();
} }
MineInfo State::mine(unsigned _msTimeout, bool _turbo) MineInfo State::mine(unsigned _msTimeout, bool _turbo)
@ -890,10 +891,10 @@ void State::completeMine()
ret.appendRaw(m_currentTxs); ret.appendRaw(m_currentTxs);
ret.appendRaw(m_currentUncles); ret.appendRaw(m_currentUncles);
ret.swapOut(m_currentBytes); ret.swapOut(m_currentBytes);
m_currentBlock.hash = sha3(RLP(m_currentBytes)[0].data()); m_currentBlock.noteDirty();
cnote << "Mined " << m_currentBlock.hash.abridged() << "(parent: " << m_currentBlock.parentHash.abridged() << ")"; cnote << "Mined " << m_currentBlock.hash().abridged() << "(parent: " << m_currentBlock.parentHash.abridged() << ")";
StructuredLogger::minedNewBlock( StructuredLogger::minedNewBlock(
m_currentBlock.hash.abridged(), m_currentBlock.hash().abridged(),
m_currentBlock.nonce.abridged(), m_currentBlock.nonce.abridged(),
"", //TODO: chain head hash here ?? "", //TODO: chain head hash here ??
m_currentBlock.parentHash.abridged() m_currentBlock.parentHash.abridged()

19
libethereum/State.h

@ -54,7 +54,12 @@ struct StateTrace: public LogChannel { static const char* name() { return "=S=";
struct StateDetail: public LogChannel { static const char* name() { return "/S/"; } static const int verbosity = 14; }; struct StateDetail: public LogChannel { static const char* name() { return "/S/"; } static const int verbosity = 14; };
struct StateSafeExceptions: public LogChannel { static const char* name() { return "(S)"; } static const int verbosity = 21; }; struct StateSafeExceptions: public LogChannel { static const char* name() { return "(S)"; } static const int verbosity = 21; };
enum class BaseState { Empty, CanonGenesis }; enum class BaseState
{
PreExisting,
Empty,
CanonGenesis
};
enum class TransactionPriority enum class TransactionPriority
{ {
@ -103,8 +108,15 @@ class State
friend class Executive; friend class Executive;
public: public:
/// Construct state object. /// Default constructor; creates with a blank database prepopulated with the genesis block.
State(Address _coinbaseAddress = Address(), OverlayDB const& _db = OverlayDB(), BaseState _bs = BaseState::CanonGenesis); State(): State(OverlayDB(), BaseState::Empty) {}
/// Basic state object from database.
/// Use the default when you already have a database and you just want to make a State object
/// which uses it. If you have no preexisting database then set BaseState to something other
/// than BaseState::PreExisting in order to prepopulate the Trie.
/// You can also set the coinbase address.
explicit State(OverlayDB const& _db, BaseState _bs = BaseState::PreExisting, Address _coinbaseAddress = Address());
/// Construct state object from arbitrary point in blockchain. /// Construct state object from arbitrary point in blockchain.
State(OverlayDB const& _db, BlockChain const& _bc, h256 _hash); State(OverlayDB const& _db, BlockChain const& _bc, h256 _hash);
@ -335,6 +347,7 @@ private:
/// Debugging only. Good for checking the Trie is in shape. /// Debugging only. Good for checking the Trie is in shape.
void paranoia(std::string const& _when, bool _enforceRefs = false) const; void paranoia(std::string const& _when, bool _enforceRefs = false) const;
OverlayDB m_db; ///< Our overlay for the state tree. OverlayDB m_db; ///< Our overlay for the state tree.
SecureTrieDB<Address, OverlayDB> m_state; ///< Our state tree, as an OverlayDB DB. SecureTrieDB<Address, OverlayDB> m_state; ///< Our state tree, as an OverlayDB DB.
Transactions m_transactions; ///< The current list of transactions that we've included in the state. Transactions m_transactions; ///< The current list of transactions that we've included in the state.

2
libtestutils/StateLoader.cpp

@ -26,7 +26,7 @@ using namespace dev;
using namespace dev::eth; using namespace dev::eth;
using namespace dev::test; using namespace dev::test;
StateLoader::StateLoader(Json::Value const& _json) : m_state(Address(), OverlayDB(), BaseState::Empty) StateLoader::StateLoader(Json::Value const& _json)
{ {
for (string const& name: _json.getMemberNames()) for (string const& name: _json.getMemberNames())
{ {

2
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -59,7 +59,7 @@ static Json::Value toJson(dev::eth::BlockInfo const& _bi)
Json::Value res; Json::Value res;
if (_bi) if (_bi)
{ {
res["hash"] = toJS(_bi.hash); res["hash"] = toJS(_bi.hash());
res["parentHash"] = toJS(_bi.parentHash); res["parentHash"] = toJS(_bi.parentHash);
res["sha3Uncles"] = toJS(_bi.sha3Uncles); res["sha3Uncles"] = toJS(_bi.sha3Uncles);
res["miner"] = toJS(_bi.coinbaseAddress); res["miner"] = toJS(_bi.coinbaseAddress);

2
mix/ClientModel.cpp

@ -469,7 +469,7 @@ RecordLogEntry* ClientModel::lastBlock() const
strGas << blockInfo.gasUsed; strGas << blockInfo.gasUsed;
std::stringstream strNumber; std::stringstream strNumber;
strNumber << blockInfo.number; strNumber << blockInfo.number;
RecordLogEntry* record = new RecordLogEntry(0, QString::fromStdString(strNumber.str()), tr(" - Block - "), tr("Hash: ") + QString(QString::fromStdString(toHex(blockInfo.hash.ref()))), tr("Gas Used: ") + QString::fromStdString(strGas.str()), QString(), QString(), false, RecordLogEntry::RecordType::Block); RecordLogEntry* record = new RecordLogEntry(0, QString::fromStdString(strNumber.str()), tr(" - Block - "), tr("Hash: ") + QString(QString::fromStdString(toHex(blockInfo.hash().ref()))), tr("Gas Used: ") + QString::fromStdString(strGas.str()), QString(), QString(), false, RecordLogEntry::RecordType::Block);
QQmlEngine::setObjectOwnership(record, QQmlEngine::JavaScriptOwnership); QQmlEngine::setObjectOwnership(record, QQmlEngine::JavaScriptOwnership);
return record; return record;
} }

2
mix/MixClient.cpp

@ -93,7 +93,7 @@ void MixClient::resetState(std::map<Secret, u256> _accounts)
h256 stateRoot = accountState.root(); h256 stateRoot = accountState.root();
m_bc.reset(); m_bc.reset();
m_bc.reset(new MixBlockChain(m_dbPath, stateRoot)); m_bc.reset(new MixBlockChain(m_dbPath, stateRoot));
m_state = eth::State(genesisState.begin()->first , m_stateDB, BaseState::Empty); m_state = eth::State(m_stateDB, BaseState::PreExisting, genesisState.begin()->first);
m_state.sync(bc()); m_state.sync(bc());
m_startState = m_state; m_startState = m_state;
WriteGuard lx(x_executions); WriteGuard lx(x_executions);

18
test/ClientBase.cpp

@ -120,11 +120,15 @@ BOOST_AUTO_TEST_CASE(blocks)
ETH_CHECK_EQUAL(expectedBlockInfoBloom, _blockInfo.logBloom); ETH_CHECK_EQUAL(expectedBlockInfoBloom, _blockInfo.logBloom);
ETH_CHECK_EQUAL(expectedBlockInfoCoinbase, _blockInfo.coinbaseAddress); ETH_CHECK_EQUAL(expectedBlockInfoCoinbase, _blockInfo.coinbaseAddress);
ETH_CHECK_EQUAL(expectedBlockInfoDifficulty, _blockInfo.difficulty); ETH_CHECK_EQUAL(expectedBlockInfoDifficulty, _blockInfo.difficulty);
ETH_CHECK_EQUAL_COLLECTIONS(expectedBlockInfoExtraData.begin(), expectedBlockInfoExtraData.end(), ETH_CHECK_EQUAL_COLLECTIONS(
_blockInfo.extraData.begin(), _blockInfo.extraData.end()); expectedBlockInfoExtraData.begin(),
expectedBlockInfoExtraData.end(),
_blockInfo.extraData.begin(),
_blockInfo.extraData.end()
);
ETH_CHECK_EQUAL(expectedBlockInfoGasLimit, _blockInfo.gasLimit); ETH_CHECK_EQUAL(expectedBlockInfoGasLimit, _blockInfo.gasLimit);
ETH_CHECK_EQUAL(expectedBlockInfoGasUsed, _blockInfo.gasUsed); ETH_CHECK_EQUAL(expectedBlockInfoGasUsed, _blockInfo.gasUsed);
ETH_CHECK_EQUAL(expectedBlockInfoHash, _blockInfo.hash); ETH_CHECK_EQUAL(expectedBlockInfoHash, _blockInfo.hash());
ETH_CHECK_EQUAL(expectedBlockInfoMixHash, _blockInfo.mixHash); ETH_CHECK_EQUAL(expectedBlockInfoMixHash, _blockInfo.mixHash);
ETH_CHECK_EQUAL(expectedBlockInfoNonce, _blockInfo.nonce); ETH_CHECK_EQUAL(expectedBlockInfoNonce, _blockInfo.nonce);
ETH_CHECK_EQUAL(expectedBlockInfoNumber, _blockInfo.number); ETH_CHECK_EQUAL(expectedBlockInfoNumber, _blockInfo.number);
@ -155,8 +159,12 @@ BOOST_AUTO_TEST_CASE(blocks)
u256 expectedTransactionSignatureS = h256(fromHex(_t["s"].asString())); u256 expectedTransactionSignatureS = h256(fromHex(_t["s"].asString()));
// unsigned expectedTransactionSignatureV = jsToInt(t["v"].asString()); // unsigned expectedTransactionSignatureV = jsToInt(t["v"].asString());
ETH_CHECK_EQUAL_COLLECTIONS(expectedTransactionData.begin(), expectedTransactionData.end(), ETH_CHECK_EQUAL_COLLECTIONS(
_transaction.data().begin(), _transaction.data().end()); expectedTransactionData.begin(),
expectedTransactionData.end(),
_transaction.data().begin(),
_transaction.data().end()
);
ETH_CHECK_EQUAL(expectedTransactionGasLimit, _transaction.gas()); ETH_CHECK_EQUAL(expectedTransactionGasLimit, _transaction.gas());
ETH_CHECK_EQUAL(expectedTransactionGasPrice, _transaction.gasPrice()); ETH_CHECK_EQUAL(expectedTransactionGasPrice, _transaction.gasPrice());
ETH_CHECK_EQUAL(expectedTransactionNonce, _transaction.nonce()); ETH_CHECK_EQUAL(expectedTransactionNonce, _transaction.nonce());

7
test/TestHelper.cpp

@ -70,7 +70,10 @@ namespace test
struct ValueTooLarge: virtual Exception {}; struct ValueTooLarge: virtual Exception {};
bigint const c_max256plus1 = bigint(1) << 256; bigint const c_max256plus1 = bigint(1) << 256;
ImportTest::ImportTest(json_spirit::mObject& _o, bool isFiller) : m_statePre(Address(_o["env"].get_obj()["currentCoinbase"].get_str()), OverlayDB(), eth::BaseState::Empty), m_statePost(Address(_o["env"].get_obj()["currentCoinbase"].get_str()), OverlayDB(), eth::BaseState::Empty), m_TestObject(_o) ImportTest::ImportTest(json_spirit::mObject& _o, bool isFiller):
m_statePre(OverlayDB(), eth::BaseState::Empty, Address(_o["env"].get_obj()["currentCoinbase"].get_str())),
m_statePost(OverlayDB(), eth::BaseState::Empty, Address(_o["env"].get_obj()["currentCoinbase"].get_str())),
m_TestObject(_o)
{ {
importEnv(_o["env"].get_obj()); importEnv(_o["env"].get_obj());
importState(_o["pre"].get_obj(), m_statePre); importState(_o["pre"].get_obj(), m_statePre);
@ -92,7 +95,7 @@ void ImportTest::importEnv(json_spirit::mObject& _o)
assert(_o.count("currentCoinbase") > 0); assert(_o.count("currentCoinbase") > 0);
assert(_o.count("currentNumber") > 0); assert(_o.count("currentNumber") > 0);
m_environment.previousBlock.hash = h256(_o["previousHash"].get_str()); m_environment.currentBlock.parentHash = h256(_o["parentHash"].get_str());
m_environment.currentBlock.number = toInt(_o["currentNumber"]); m_environment.currentBlock.number = toInt(_o["currentNumber"]);
m_environment.currentBlock.gasLimit = toInt(_o["currentGasLimit"]); m_environment.currentBlock.gasLimit = toInt(_o["currentGasLimit"]);
m_environment.currentBlock.difficulty = toInt(_o["currentDifficulty"]); m_environment.currentBlock.difficulty = toInt(_o["currentDifficulty"]);

2
test/TestHelper.h

@ -101,7 +101,7 @@ namespace test
class ImportTest class ImportTest
{ {
public: public:
ImportTest(json_spirit::mObject& _o) : m_statePre(Address(), OverlayDB(), eth::BaseState::Empty), m_statePost(Address(), OverlayDB(), eth::BaseState::Empty), m_TestObject(_o) {} ImportTest(json_spirit::mObject& _o): m_TestObject(_o) {}
ImportTest(json_spirit::mObject& _o, bool isFiller); ImportTest(json_spirit::mObject& _o, bool isFiller);
// imports // imports
void importEnv(json_spirit::mObject& _o); void importEnv(json_spirit::mObject& _o);

6
test/blockchain.cpp

@ -52,7 +52,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
BOOST_REQUIRE(o.count("pre")); BOOST_REQUIRE(o.count("pre"));
ImportTest importer(o["pre"].get_obj()); ImportTest importer(o["pre"].get_obj());
State state(biGenesisBlock.coinbaseAddress, OverlayDB(), BaseState::Empty); State state(OverlayDB(), BaseState::Empty, biGenesisBlock.coinbaseAddress);
importer.importState(o["pre"].get_obj(), state); importer.importState(o["pre"].get_obj(), state);
o["pre"] = fillJsonWithState(state); o["pre"] = fillJsonWithState(state);
state.commit(); state.commit();
@ -599,7 +599,7 @@ void updatePoW(BlockInfo& _bi)
ret = pow.mine(_bi, 10000, true, true); ret = pow.mine(_bi, 10000, true, true);
Ethash::assignResult(ret.second, _bi); Ethash::assignResult(ret.second, _bi);
} }
_bi.hash = _bi.headerHash(WithNonce); _bi.noteDirty();
} }
void writeBlockHeaderToJson(mObject& _o, BlockInfo const& _bi) void writeBlockHeaderToJson(mObject& _o, BlockInfo const& _bi)
@ -619,7 +619,7 @@ void writeBlockHeaderToJson(mObject& _o, BlockInfo const& _bi)
_o["extraData"] ="0x" + toHex(_bi.extraData); _o["extraData"] ="0x" + toHex(_bi.extraData);
_o["mixHash"] = toString(_bi.mixHash); _o["mixHash"] = toString(_bi.mixHash);
_o["nonce"] = toString(_bi.nonce); _o["nonce"] = toString(_bi.nonce);
_o["hash"] = toString(_bi.hash); _o["hash"] = toString(_bi.hash());
} }
RLPStream createFullBlockFromHeader(BlockInfo const& _bi, bytes const& _txs, bytes const& _uncles) RLPStream createFullBlockFromHeader(BlockInfo const& _bi, bytes const& _txs, bytes const& _uncles)

2
test/stateOriginal.cpp

@ -58,7 +58,7 @@ BOOST_AUTO_TEST_CASE(Complex)
CanonBlockChain bc; CanonBlockChain bc;
cout << bc; cout << bc;
State s(myMiner.address(), stateDB); State s(stateDB, BaseState::Empty, myMiner.address());
cout << s; cout << s;
// Sync up - this won't do much until we use the last state. // Sync up - this won't do much until we use the last state.

4
test/vm.cpp

@ -96,7 +96,7 @@ void FakeExtVM::push(mArray& a, u256 _v)
mObject FakeExtVM::exportEnv() mObject FakeExtVM::exportEnv()
{ {
mObject ret; mObject ret;
ret["previousHash"] = toString(previousBlock.hash); ret["previousHash"] = toString(currentBlock.parentHash);
push(ret, "currentDifficulty", currentBlock.difficulty); push(ret, "currentDifficulty", currentBlock.difficulty);
push(ret, "currentTimestamp", currentBlock.timestamp); push(ret, "currentTimestamp", currentBlock.timestamp);
ret["currentCoinbase"] = toString(currentBlock.coinbaseAddress); ret["currentCoinbase"] = toString(currentBlock.coinbaseAddress);
@ -115,7 +115,7 @@ void FakeExtVM::importEnv(mObject& _o)
assert(_o.count("currentCoinbase") > 0); assert(_o.count("currentCoinbase") > 0);
assert(_o.count("currentNumber") > 0); assert(_o.count("currentNumber") > 0);
previousBlock.hash = h256(_o["previousHash"].get_str()); currentBlock.parentHash = h256(_o["previousHash"].get_str());
currentBlock.number = toInt(_o["currentNumber"]); currentBlock.number = toInt(_o["currentNumber"]);
lastHashes = test::lastHashes(currentBlock.number); lastHashes = test::lastHashes(currentBlock.number);
currentBlock.gasLimit = toInt(_o["currentGasLimit"]); currentBlock.gasLimit = toInt(_o["currentGasLimit"]);

Loading…
Cancel
Save