Browse Source

Merge branch 'state' of https://github.com/arkpar/cpp-ethereum into arkpar-state

Minor miner fix.

Conflicts:
	libethereum/State.cpp
cl-refactor
Gav Wood 10 years ago
parent
commit
74042678f3
  1. 2
      ethminer/MinerAux.h
  2. 4
      libdevcore/TrieDB.h
  3. 1
      libethcore/Exceptions.h
  4. 6
      libethereum/BlockChain.cpp
  5. 22
      libethereum/Client.cpp
  6. 1
      libethereum/Client.h
  7. 119
      libethereum/State.cpp
  8. 44
      libethereum/State.h

2
ethminer/MinerAux.h

@ -297,7 +297,9 @@ public:
{
if (m_shouldListDevices)
{
#if ETH_ETHASHCL || !ETH_TRUE
EthashGPUMiner::listDevices();
#endif
exit(0);
}

4
libdevcore/TrieDB.h

@ -158,8 +158,6 @@ public:
iterator lower_bound(bytesConstRef _key) const { return iterator(this, _key); }
void debugPrint() {}
/// Used for debugging, scans the whole trie.
void descendKey(h256 const& _k, h256Hash& _keyMask, bool _wasExt, std::ostream* _out, int _indent = 0) const
{
@ -390,6 +388,7 @@ public:
using Super::leftOvers;
using Super::check;
using Super::debugStructure;
std::string at(bytesConstRef _key) const { return Super::at(sha3(_key)); }
bool contains(bytesConstRef _key) { return Super::contains(sha3(_key)); }
@ -440,6 +439,7 @@ public:
using Super::open;
using Super::setRoot;
using Super::db;
using Super::debugStructure;
std::string at(bytesConstRef _key) const { return Super::at(sha3(_key)); }
bool contains(bytesConstRef _key) { return Super::contains(sha3(_key)); }

1
libethcore/Exceptions.h

@ -71,6 +71,7 @@ DEV_SIMPLE_EXCEPTION(InvalidBlockHeaderItemCount);
DEV_SIMPLE_EXCEPTION(InvalidBlockNonce);
DEV_SIMPLE_EXCEPTION(InvalidParentHash);
DEV_SIMPLE_EXCEPTION(InvalidNumber);
DEV_SIMPLE_EXCEPTION(BlockNotFound);
DEV_SIMPLE_EXCEPTION(DatabaseAlreadyOpen);
DEV_SIMPLE_EXCEPTION(DAGCreationFailure);

6
libethereum/BlockChain.cpp

@ -731,8 +731,10 @@ ImportRoute BlockChain::import(VerifiedBlockRef const& _block, OverlayDB const&
exit(-1);
}
try {
State canary(_db, *this, _block.info.hash(), ImportRequirements::DontHave);
try
{
State canary(_db, BaseState::Empty);
canary.populateFromChain(*this, _block.info.hash(), ImportRequirements::DontHave);
}
catch (...)
{

22
libethereum/Client.cpp

@ -40,6 +40,8 @@
#include "Executive.h"
#include "EthereumHost.h"
#include "Utility.h"
#include "TransactionQueue.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
@ -462,20 +464,8 @@ uint64_t Client::hashrate() const
std::list<MineInfo> Client::miningHistory()
{
std::list<MineInfo> ret;
/* ReadGuard l(x_localMiners);
if (m_localMiners.empty())
return ret;
ret = m_localMiners[0].miningHistory();
for (unsigned i = 1; i < m_localMiners.size(); ++i)
{
auto l = m_localMiners[i].miningHistory();
auto ri = ret.begin();
auto li = l.begin();
for (; ri != ret.end() && li != l.end(); ++ri, ++li)
ri->combine(*li);
}*/
return ret;
//TODO: reimplement for CPU/GPU miner
return std::list<MineInfo> {};
}
ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256 _value, u256 _gasPrice, Address const& _from)
@ -484,7 +474,7 @@ ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256
try
{
State temp;
// clog(ClientTrace) << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret));
clog(ClientDetail) << "Nonce at " << _dest << " pre:" << m_preMine.transactionsFrom(_dest) << " post:" << m_postMine.transactionsFrom(_dest);
DEV_READ_GUARDED(x_postMine)
temp = m_postMine;
temp.addBalance(_from, _value + _gasPrice * _gas);
@ -496,7 +486,7 @@ ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256
}
catch (...)
{
// TODO: Some sort of notification of failure.
cwarn << "Client::call failed: " << boost::current_exception_diagnostic_information();
}
return ret;
}

1
libethereum/Client.h

@ -40,7 +40,6 @@
#include <libethcore/ABI.h>
#include <libp2p/Common.h>
#include "CanonBlockChain.h"
#include "TransactionQueue.h"
#include "State.h"
#include "CommonNet.h"
#include "ClientBase.h"

119
libethereum/State.cpp

@ -73,8 +73,8 @@ OverlayDB State::openDB(std::string const& _basePath, h256 const& _genesisHash,
o.max_open_files = 256;
o.create_if_missing = true;
ldb::DB* db = nullptr;
ldb::DB::Open(o, path + "/state", &db);
if (!db)
ldb::Status status = ldb::DB::Open(o, path + "/state", &db);
if (!status.ok() || !db)
{
if (boost::filesystem::space(path + "/state").available < 1024)
{
@ -83,6 +83,7 @@ OverlayDB State::openDB(std::string const& _basePath, h256 const& _genesisHash,
}
else
{
cwarn << status.ToString();
cwarn << "Database already open. You appear to have another instance of ethereum running. Bailing.";
BOOST_THROW_EXCEPTION(DatabaseAlreadyOpen());
}
@ -119,7 +120,7 @@ PopulationStatistics State::populateFromChain(BlockChain const& _bc, h256 const&
{
// Might be worth throwing here.
cwarn << "Invalid block given for state population: " << _h;
return ret;
BOOST_THROW_EXCEPTION(BlockNotFound() << errinfo_target(_h));
}
auto b = _bc.block(_h);
@ -203,10 +204,6 @@ State& State::operator=(State const& _s)
return *this;
}
State::~State()
{
}
StateDiff State::diff(State const& _c, bool _quick) const
{
StateDiff ret;
@ -237,9 +234,6 @@ StateDiff State::diff(State const& _c, bool _quick) const
for (auto const& i: _c.m_cache)
ads.insert(i.first);
// cnote << *this;
// cnote << _c;
for (auto const& i: ads)
{
auto it = m_cache.find(i);
@ -254,12 +248,12 @@ StateDiff State::diff(State const& _c, bool _quick) const
return ret;
}
void State::ensureCached(Address _a, bool _requireCode, bool _forceCreate) const
void State::ensureCached(Address const& _a, bool _requireCode, bool _forceCreate) const
{
ensureCached(m_cache, _a, _requireCode, _forceCreate);
}
void State::ensureCached(std::unordered_map<Address, Account>& _cache, Address _a, bool _requireCode, bool _forceCreate) const
void State::ensureCached(std::unordered_map<Address, Account>& _cache, const Address& _a, bool _requireCode, bool _forceCreate) const
{
auto it = _cache.find(_a);
if (it == _cache.end())
@ -297,14 +291,14 @@ bool State::sync(BlockChain const& _bc, h256 const& _block, BlockInfo const& _bi
bool ret = false;
// BLOCK
BlockInfo bi = _bi ? _bi : _bc.info(_block);
/* if (!bi)
#if ETH_PARANOIA
if (!bi)
while (1)
{
try
{
auto b = _bc.block(_block);
bi.populate(b);
// bi.verifyInternals(_bc.block(_block)); // Unneeded - we already verify on import into the blockchain.
break;
}
catch (Exception const& _e)
@ -319,7 +313,8 @@ bool State::sync(BlockChain const& _bc, h256 const& _block, BlockInfo const& _bi
cerr << "ERROR: Corrupt block-chain! Delete your block-chain DB and restart." << endl;
cerr << _e.what() << endl;
}
}*/
}
#endif
if (bi == m_currentBlock)
{
// We mined the last block.
@ -344,7 +339,7 @@ bool State::sync(BlockChain const& _bc, h256 const& _block, BlockInfo const& _bi
cwarn << "Unable to sync to" << bi.hash() << "; state root" << bi.stateRoot() << "not found in database.";
cwarn << "Database corrupt: contains block without stateRoot:" << bi;
cwarn << "Try rescuing the database by running: eth --rescue";
exit(-1);
BOOST_THROW_EXCEPTION(InvalidStateRoot() << errinfo_target(bi.stateRoot()));
}
m_previousBlock = bi;
resetCurrent();
@ -467,7 +462,6 @@ void State::resetCurrent()
m_currentBlock.setTimestamp(max(m_previousBlock.timestamp() + 1, (u256)time(0)));
m_currentBlock.populateFromParent(m_previousBlock);
// Update timestamp according to clock.
// TODO: check.
m_lastTx = m_db;
@ -547,7 +541,6 @@ pair<TransactionReceipts, bool> State::sync(BlockChain const& _bc, TransactionQu
// Temporarily no gas left in current block.
// OPTIMISE: could note this and then we don't evaluate until a block that does have the gas left.
// for now, just leave alone.
// _tq.setFuture(t.sha3());
}
}
catch (Exception const& _e)
@ -773,7 +766,8 @@ void State::cleanup(bool _fullCommit)
if (isChannelVisible<StateTrace>()) // Avoid calling toHex if not needed
clog(StateTrace) << "Committing to disk: stateRoot" << m_currentBlock.stateRoot() << "=" << rootHash() << "=" << toHex(asBytes(m_db.lookup(rootHash())));
try {
try
{
EnforceRefs er(m_db, true);
rootHash();
}
@ -814,45 +808,6 @@ void State::uncommitToMine()
}
}
bool State::amIJustParanoid(BlockChain const& _bc)
{
(void)_bc;
/*
commitToMine(_bc);
// Update difficulty according to timestamp.
m_currentBlock.difficulty = m_currentBlock.calculateDifficulty(m_previousBlock);
// Compile block:
RLPStream block;
block.appendList(3);
m_currentBlock.streamRLP(block, WithProof);
block.appendRaw(m_currentTxs);
block.appendRaw(m_currentUncles);
State s(*this);
s.resetCurrent();
try
{
cnote << "PARANOIA root:" << s.rootHash();
// s.m_currentBlock.populate(&block.out(), false);
// s.m_currentBlock.verifyInternals(&block.out());
s.enact(BlockChain::verifyBlock(block.out(), std::function<void(Exception&)>(), ImportRequirements::CheckUncles | ImportRequirements::CheckTransactions), _bc); // don't check nonce for this since we haven't mined it yet.
s.cleanup(false);
return true;
}
catch (Exception const& _e)
{
cwarn << "Bad block: " << diagnostic_information(_e);
}
catch (std::exception const& _e)
{
cwarn << "Bad block: " << _e.what();
}
*/
return false;
}
LogBloom State::logBloom() const
{
LogBloom ret;
@ -865,12 +820,6 @@ void State::commitToMine(BlockChain const& _bc, bytes const& _extraData)
{
uncommitToMine();
// cnote << "Committing to mine on block" << m_previousBlock.hash;
#if ETH_PARANOIA && 0
commit();
cnote << "Pre-reward stateRoot:" << m_state.root();
#endif
m_lastTx = m_db;
vector<BlockInfo> uncleBlockHeaders;
@ -880,7 +829,7 @@ void State::commitToMine(BlockChain const& _bc, bytes const& _extraData)
if (m_previousBlock.number() != 0)
{
// Find great-uncles (or second-cousins or whatever they are) - children of great-grandparents, great-great-grandparents... that were not already uncles in previous generations.
// cout << "Checking " << m_previousBlock.hash << ", parent=" << m_previousBlock.parentHash() << endl;
clog(StateDetail) << "Checking " << m_previousBlock.hash() << ", parent=" << m_previousBlock.parentHash();
h256Hash excluded = _bc.allKinFrom(m_currentBlock.parentHash(), 6);
auto p = m_previousBlock.parentHash();
for (unsigned gen = 0; gen < 6 && p != _bc.genesisHash() && unclesCount < 2; ++gen, p = _bc.details(p).parent)
@ -931,9 +880,9 @@ void State::commitToMine(BlockChain const& _bc, bytes const& _extraData)
// Commit any and all changes to the trie that are in the cache, then update the state root accordingly.
commit();
// cnote << "Post-reward stateRoot:" << m_state.root();
// cnote << m_state;
// cnote << *this;
clog(StateDetail) << "Post-reward stateRoot:" << m_state.root();
clog(StateDetail) << m_state;
clog(StateDetail) << *this;
m_currentBlock.setLogBloom(logBloom());
m_currentBlock.setGasUsed(gasUsed());
@ -956,7 +905,7 @@ bool State::sealBlock(bytesConstRef _header)
if (!m_committedToMine)
return false;
cdebug << "Sealing block!";
clog(StateDetail) << "Sealing block!";
// Got it!
// Compile block:
@ -986,7 +935,7 @@ bool State::sealBlock(bytesConstRef _header)
return true;
}
bool State::addressInUse(Address _id) const
bool State::addressInUse(Address const& _id) const
{
ensureCached(_id, false, false);
auto it = m_cache.find(_id);
@ -995,7 +944,7 @@ bool State::addressInUse(Address _id) const
return true;
}
bool State::addressHasCode(Address _id) const
bool State::addressHasCode(Address const& _id) const
{
ensureCached(_id, false, false);
auto it = m_cache.find(_id);
@ -1004,7 +953,7 @@ bool State::addressHasCode(Address _id) const
return it->second.isFreshCode() || it->second.codeHash() != EmptySHA3;
}
u256 State::balance(Address _id) const
u256 State::balance(Address const& _id) const
{
ensureCached(_id, false, false);
auto it = m_cache.find(_id);
@ -1013,7 +962,7 @@ u256 State::balance(Address _id) const
return it->second.balance();
}
void State::noteSending(Address _id)
void State::noteSending(Address const& _id)
{
ensureCached(_id, false, false);
auto it = m_cache.find(_id);
@ -1027,7 +976,7 @@ void State::noteSending(Address _id)
it->second.incNonce();
}
void State::addBalance(Address _id, u256 _amount)
void State::addBalance(Address const& _id, u256 const& _amount)
{
ensureCached(_id, false, false);
auto it = m_cache.find(_id);
@ -1037,7 +986,7 @@ void State::addBalance(Address _id, u256 _amount)
it->second.addBalance(_amount);
}
void State::subBalance(Address _id, bigint _amount)
void State::subBalance(Address const& _id, bigint const& _amount)
{
ensureCached(_id, false, false);
auto it = m_cache.find(_id);
@ -1047,7 +996,7 @@ void State::subBalance(Address _id, bigint _amount)
it->second.addBalance(-_amount);
}
Address State::newContract(u256 _balance, bytes const& _code)
Address State::newContract(u256 const& _balance, bytes const& _code)
{
auto h = sha3(_code);
m_db.insert(h, &_code);
@ -1064,7 +1013,7 @@ Address State::newContract(u256 _balance, bytes const& _code)
}
}
u256 State::transactionsFrom(Address _id) const
u256 State::transactionsFrom(Address const& _id) const
{
ensureCached(_id, false, false);
auto it = m_cache.find(_id);
@ -1074,7 +1023,7 @@ u256 State::transactionsFrom(Address _id) const
return it->second.nonce();
}
u256 State::storage(Address _id, u256 _memory) const
u256 State::storage(Address const& _id, u256 const& _memory) const
{
ensureCached(_id, false, false);
auto it = m_cache.find(_id);
@ -1096,7 +1045,7 @@ u256 State::storage(Address _id, u256 _memory) const
return ret;
}
unordered_map<u256, u256> State::storage(Address _id) const
unordered_map<u256, u256> State::storage(Address const& _id) const
{
unordered_map<u256, u256> ret;
@ -1122,7 +1071,7 @@ unordered_map<u256, u256> State::storage(Address _id) const
return ret;
}
h256 State::storageRoot(Address _id) const
h256 State::storageRoot(Address const& _id) const
{
string s = m_state.at(_id);
if (s.size())
@ -1133,7 +1082,7 @@ h256 State::storageRoot(Address _id) const
return EmptyTrie;
}
bytes const& State::code(Address _contract) const
bytes const& State::code(Address const& _contract) const
{
if (!addressHasCode(_contract))
return NullBytes;
@ -1141,7 +1090,7 @@ bytes const& State::code(Address _contract) const
return m_cache[_contract].code();
}
h256 State::codeHash(Address _contract) const
h256 State::codeHash(Address const& _contract) const
{
if (!addressHasCode(_contract))
return EmptySHA3;
@ -1162,7 +1111,7 @@ bool State::isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const
cwarn << "LEFTOVERS" << (e ? "[enforced" : "[unenforced") << "refs]";
cnote << "Left:" << lo;
cnote << "Keys:" << m_db.keys();
// m_state.debugStructure(cerr);
m_state.debugStructure(cerr);
return false;
}
// TODO: Enable once fixed.
@ -1179,14 +1128,12 @@ bool State::isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const
{
cwarn << "BAD TRIE" << (e ? "[enforced" : "[unenforced") << "refs]";
cnote << m_db.keys();
// m_state.debugStructure(cerr);
m_state.debugStructure(cerr);
return false;
}
return true;
}
#define ETH_VMTIMER 1
ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Permanence _p, OnOpFunc const& _onOp)
{
#if ETH_PARANOIA

44
libethereum/State.h

@ -121,8 +121,6 @@ public:
/// Copy state object.
State& operator=(State const& _s);
~State();
/// Construct state object from arbitrary point in blockchain.
PopulationStatistics populateFromChain(BlockChain const& _bc, h256 const& _hash, ImportRequirements::value _ir = ImportRequirements::None);
@ -144,11 +142,6 @@ public:
/// Get the header information on the present block.
BlockInfo const& info() const { return m_currentBlock; }
/// @brief Checks that mining the current object will result in a valid block.
/// Effectively attempts to import the serialised block.
/// @returns true if all is ok. If it's false, worry.
bool amIJustParanoid(BlockChain const& _bc);
/// Prepares the current state for mining.
/// Commits all transactions into the trie, compiles uncles and transactions list, applies all
/// rewards and populates the current block header with the appropriate hashes.
@ -157,9 +150,6 @@ public:
/// This may be called multiple times and without issue.
void commitToMine(BlockChain const& _bc, bytes const& _extraData = {});
/// @returns true iff commitToMine() has been called without any subsequest transactions added &c.
bool isCommittedToMine() const { return m_committedToMine; }
/// Pass in a solution to the proof-of-work.
/// @returns true iff we were previously committed to mining.
/// TODO: verify it prior to calling this.
@ -193,24 +183,24 @@ public:
u256 gasLimitRemaining() const { return m_currentBlock.gasLimit() - gasUsed(); }
/// Check if the address is in use.
bool addressInUse(Address _address) const;
bool addressInUse(Address const& _address) const;
/// Check if the address contains executable code.
bool addressHasCode(Address _address) const;
bool addressHasCode(Address const& _address) const;
/// Get an account's balance.
/// @returns 0 if the address has never been used.
u256 balance(Address _id) const;
u256 balance(Address const& _id) const;
/// Add some amount to balance.
/// Will initialise the address if it has never been used.
void addBalance(Address _id, u256 _amount);
void addBalance(Address const& _id, u256 const& _amount);
/** Subtract some amount from balance.
* @throws NotEnoughCash if balance of @a _id is less than @a _value (or has never been used).
* @note We use bigint here as we don't want any accidental problems with negative numbers.
*/
void subBalance(Address _id, bigint _value);
void subBalance(Address const& _id, bigint const& _value);
/**
* @brief Transfers "the balance @a _value between two accounts.
@ -218,40 +208,40 @@ public:
* @param _to Account to which @a _value will be added.
* @param _value Amount to be transferred.
*/
void transferBalance(Address _from, Address _to, u256 _value) { subBalance(_from, _value); addBalance(_to, _value); }
void transferBalance(Address const& _from, Address const& _to, u256 const& _value) { subBalance(_from, _value); addBalance(_to, _value); }
/// Get the root of the storage of an account.
h256 storageRoot(Address _contract) const;
h256 storageRoot(Address const& _contract) const;
/// Get the value of a storage position of an account.
/// @returns 0 if no account exists at that address.
u256 storage(Address _contract, u256 _memory) const;
u256 storage(Address const& _contract, u256 const& _memory) const;
/// Set the value of a storage position of an account.
void setStorage(Address _contract, u256 _location, u256 _value) { m_cache[_contract].setStorage(_location, _value); }
void setStorage(Address const& _contract, u256 const& _location, u256 const& _value) { m_cache[_contract].setStorage(_location, _value); }
/// Create a new contract.
Address newContract(u256 _balance, bytes const& _code);
Address newContract(u256 const& _balance, bytes const& _code);
/// Get the storage of an account.
/// @note This is expensive. Don't use it unless you need to.
/// @returns std::unordered_map<u256, u256> if no account exists at that address.
std::unordered_map<u256, u256> storage(Address _contract) const;
std::unordered_map<u256, u256> storage(Address const& _contract) const;
/// Get the code of an account.
/// @returns bytes() if no account exists at that address.
bytes const& code(Address _contract) const;
bytes const& code(Address const& _contract) const;
/// Get the code hash of an account.
/// @returns EmptySHA3 if no account exists at that address or if there is no code associated with the address.
h256 codeHash(Address _contract) const;
h256 codeHash(Address const& _contract) const;
/// Note that the given address is sending a transaction and thus increment the associated ticker.
void noteSending(Address _id);
void noteSending(Address const& _id);
/// Get the number of transactions a particular address has sent (used for the transaction nonce).
/// @returns 0 if the address has never been used.
u256 transactionsFrom(Address _address) const;
u256 transactionsFrom(Address const& _address) const;
/// The hash of the root of our state tree.
h256 rootHash() const { return m_state.root(); }
@ -317,10 +307,10 @@ private:
/// If _requireMemory is true, grab the full memory should it be a contract item.
/// If _forceCreate is true, then insert a default item into the cache, in the case it doesn't
/// exist in the DB.
void ensureCached(Address _a, bool _requireCode, bool _forceCreate) const;
void ensureCached(Address const& _a, bool _requireCode, bool _forceCreate) const;
/// Retrieve all information about a given address into a cache.
void ensureCached(std::unordered_map<Address, Account>& _cache, Address _a, bool _requireCode, bool _forceCreate) const;
void ensureCached(std::unordered_map<Address, Account>& _cache, Address const& _a, bool _requireCode, bool _forceCreate) const;
/// Execute the given block, assuming it corresponds to m_currentBlock.
/// Throws on failure.

Loading…
Cancel
Save