Browse Source

Fix for mining reversion.

cl-refactor
Gav Wood 11 years ago
parent
commit
992fadfd08
  1. 58
      libethereum/State.cpp
  2. 5
      libethereum/State.h

58
libethereum/State.cpp

@ -67,19 +67,19 @@ State::State(Address _coinbaseAddress, Overlay const& _db):
// 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."); paranoia("beginning of normal construction.", true);
eth::commit(genesisState(), m_db, m_state); eth::commit(genesisState(), m_db, m_state);
m_db.commit(); m_db.commit();
paranoia("after DB commit of normal construction."); paranoia("after DB commit of normal construction.", true);
m_previousBlock = BlockChain::genesis(); m_previousBlock = BlockChain::genesis();
resetCurrent(); resetCurrent();
assert(m_state.root() == m_previousBlock.stateRoot); assert(m_state.root() == m_previousBlock.stateRoot);
paranoia("end of normal construction."); paranoia("end of normal construction.", true);
} }
State::State(State const& _s): State::State(State const& _s):
@ -94,15 +94,15 @@ State::State(State const& _s):
m_ourAddress(_s.m_ourAddress), m_ourAddress(_s.m_ourAddress),
m_blockReward(_s.m_blockReward) m_blockReward(_s.m_blockReward)
{ {
paranoia("after state cloning (copy cons)."); paranoia("after state cloning (copy cons).", true);
} }
void State::paranoia(std::string const& _when) const void State::paranoia(std::string const& _when, bool _enforceRefs) const
{ {
#if ETH_PARANOIA #if ETH_PARANOIA
// TODO: variable on context; just need to work out when there should be no leftovers // TODO: variable on context; just need to work out when there should be no leftovers
// [in general this is hard since contract alteration will result in nodes in the DB that are no directly part of the state DB]. // [in general this is hard since contract alteration will result in nodes in the DB that are no directly part of the state DB].
if (!isTrieGood(false)) if (!isTrieGood(_enforceRefs, false))
{ {
cwarn << "BAD TRIE" << _when; cwarn << "BAD TRIE" << _when;
throw InvalidTrie(); throw InvalidTrie();
@ -114,7 +114,6 @@ void State::paranoia(std::string const& _when) const
State& State::operator=(State const& _s) State& State::operator=(State const& _s)
{ {
paranoia("prior state cloning (assignment op)");
m_db = _s.m_db; m_db = _s.m_db;
m_state.open(&m_db, _s.m_state.root()); m_state.open(&m_db, _s.m_state.root());
m_transactions = _s.m_transactions; m_transactions = _s.m_transactions;
@ -125,7 +124,7 @@ State& State::operator=(State const& _s)
m_currentBlock = _s.m_currentBlock; m_currentBlock = _s.m_currentBlock;
m_ourAddress = _s.m_ourAddress; m_ourAddress = _s.m_ourAddress;
m_blockReward = _s.m_blockReward; m_blockReward = _s.m_blockReward;
paranoia("after state cloning (assignment op)"); paranoia("after state cloning (assignment op)", true);
return *this; return *this;
} }
@ -369,9 +368,10 @@ void State::resetCurrent()
// Update timestamp according to clock. // Update timestamp according to clock.
// TODO: check. // TODO: check.
m_lastTx = m_db;
m_state.setRoot(m_currentBlock.stateRoot); m_state.setRoot(m_currentBlock.stateRoot);
paranoia("begin resetCurrent"); paranoia("begin resetCurrent", true);
} }
bool State::cull(TransactionQueue& _tq) const bool State::cull(TransactionQueue& _tq) const
@ -556,12 +556,12 @@ u256 State::playbackRaw(bytesConstRef _block, BlockInfo const& _grandParent, boo
if (_fullCommit) if (_fullCommit)
{ {
paranoia("immediately before database commit"); paranoia("immediately before database commit", true);
// Commit the new trie to disk. // Commit the new trie to disk.
m_db.commit(); m_db.commit();
paranoia("immediately after database commit"); paranoia("immediately after database commit", true);
m_previousBlock = m_currentBlock; m_previousBlock = m_currentBlock;
} }
else else
@ -576,12 +576,18 @@ u256 State::playbackRaw(bytesConstRef _block, BlockInfo const& _grandParent, boo
void State::uncommitToMine() void State::uncommitToMine()
{ {
m_cache.clear(); if (m_currentBlock.sha3Uncles)
if (!m_transactions.size()) {
m_state.setRoot(m_previousBlock.stateRoot); m_cache.clear();
else if (!m_transactions.size())
m_state.setRoot(m_transactions[m_transactions.size() - 1].stateRoot); m_state.setRoot(m_previousBlock.stateRoot);
m_currentBlock.sha3Uncles = h256(); else
m_state.setRoot(m_transactions[m_transactions.size() - 1].stateRoot);
m_db = m_lastTx;
m_transactionManifest.init();
paranoia("Uncommited to mine", true);
m_currentBlock.sha3Uncles = h256();
}
} }
bool State::amIJustParanoid(BlockChain const& _bc) bool State::amIJustParanoid(BlockChain const& _bc)
@ -632,6 +638,8 @@ void State::commitToMine(BlockChain const& _bc)
cnote << "Pre-reward stateRoot:" << m_state.root(); cnote << "Pre-reward stateRoot:" << m_state.root();
#endif #endif
m_lastTx = m_db;
RLPStream uncles; RLPStream uncles;
Addresses uncleAddresses; Addresses uncleAddresses;
@ -654,7 +662,6 @@ void State::commitToMine(BlockChain const& _bc)
uncles.appendList(0); uncles.appendList(0);
// cnote << *this; // cnote << *this;
applyRewards(uncleAddresses);
if (m_transactionManifest.isNull()) if (m_transactionManifest.isNull())
m_transactionManifest.init(); m_transactionManifest.init();
else else
@ -680,6 +687,9 @@ void State::commitToMine(BlockChain const& _bc)
m_currentBlock.transactionsRoot = m_transactionManifest.root(); m_currentBlock.transactionsRoot = m_transactionManifest.root();
m_currentBlock.sha3Uncles = sha3(m_currentUncles); m_currentBlock.sha3Uncles = sha3(m_currentUncles);
// Apply rewards last of all.
applyRewards(uncleAddresses);
// Commit any and all changes to the trie that are in the cache, then update the state root accordingly. // Commit any and all changes to the trie that are in the cache, then update the state root accordingly.
commit(); commit();
@ -856,9 +866,9 @@ bytes const& State::code(Address _contract) const
return m_cache[_contract].code(); return m_cache[_contract].code();
} }
bool State::isTrieGood(bool _requireNoLeftOvers) const bool State::isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const
{ {
for (int e = 0; e < 2; ++e) for (int e = 0; e < (_enforceRefs ? 2 : 1); ++e)
try try
{ {
EnforceRefs r(m_db, !!e); EnforceRefs r(m_db, !!e);
@ -871,6 +881,7 @@ bool State::isTrieGood(bool _requireNoLeftOvers) const
m_state.debugStructure(cerr); m_state.debugStructure(cerr);
return false; return false;
} }
// TODO: Enable once fixed.
for (auto const& i: m_state) for (auto const& i: m_state)
{ {
RLP r(i.second); RLP r(i.second);
@ -890,13 +901,16 @@ bool State::isTrieGood(bool _requireNoLeftOvers) const
return true; return true;
} }
// TODO: kill temp nodes automatically in TrieDB
// TODO: maintain node overlay revisions for stateroots -> each commit gives a stateroot + Overlay; allow overlay copying for rewind operations.
u256 State::execute(bytesConstRef _rlp) u256 State::execute(bytesConstRef _rlp)
{ {
#ifndef RELEASE #ifndef RELEASE
commit(); // get an updated hash commit(); // get an updated hash
#endif #endif
paranoia("start of execution."); paranoia("start of execution.", true);
State old(*this); State old(*this);
#if ETH_PARANOIA #if ETH_PARANOIA
@ -929,7 +943,7 @@ u256 State::execute(bytesConstRef _rlp)
ctrace << "Executed; now" << rootHash(); ctrace << "Executed; now" << rootHash();
ctrace << old.diff(*this); ctrace << old.diff(*this);
paranoia("after execution commit."); paranoia("after execution commit.", true);
if (e.t().receiveAddress) if (e.t().receiveAddress)
{ {

5
libethereum/State.h

@ -297,14 +297,15 @@ private:
/// @returns gas used by transactions thus far executed. /// @returns gas used by transactions thus far executed.
u256 gasUsed() const { return m_transactions.size() ? m_transactions.back().gasUsed : 0; } u256 gasUsed() const { return m_transactions.size() ? m_transactions.back().gasUsed : 0; }
bool isTrieGood(bool _requireNoLeftOvers) const; bool isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const;
void paranoia(std::string const& _when) const; void paranoia(std::string const& _when, bool _enforceRefs = false) const;
Overlay m_db; ///< Our overlay for the state tree. Overlay m_db; ///< Our overlay for the state tree.
TrieDB<Address, Overlay> m_state; ///< Our state tree, as an Overlay DB. TrieDB<Address, Overlay> m_state; ///< Our state tree, as an Overlay DB.
std::vector<TransactionReceipt> m_transactions; ///< The current list of transactions that we've included in the state. std::vector<TransactionReceipt> m_transactions; ///< The current list of transactions that we've included in the state.
std::set<h256> m_transactionSet; ///< The set of transaction hashes that we've included in the state. std::set<h256> m_transactionSet; ///< The set of transaction hashes that we've included in the state.
GenericTrieDB<Overlay> m_transactionManifest; ///< The transactions trie; saved from the last commitToMine, or invalid/empty if commitToMine was never called. GenericTrieDB<Overlay> m_transactionManifest; ///< The transactions trie; saved from the last commitToMine, or invalid/empty if commitToMine was never called.
Overlay m_lastTx;
mutable std::map<Address, AddressState> m_cache; ///< Our address cache. This stores the states of each address that has (or at least might have) been changed. mutable std::map<Address, AddressState> m_cache; ///< Our address cache. This stores the states of each address that has (or at least might have) been changed.

Loading…
Cancel
Save