32 #include <boost/filesystem.hpp> 33 #include <boost/timer.hpp> 38 namespace fs = boost::filesystem;
43 m_accountStartNonce(_accountStartNonce)
54 m_unchangedCacheEntries(_s.m_unchangedCacheEntries),
55 m_nonExistingAccountsCache(_s.m_nonExistingAccountsCache),
56 m_touched(_s.m_touched),
57 m_accountStartNonce(_s.m_accountStartNonce)
67 fs::remove_all(path / fs::path(
"state"));
73 fs::create_directories(path);
83 catch (boost::exception
const& ex)
85 cwarn << boost::diagnostic_information(ex) <<
'\n';
88 else if (fs::space(path / fs::path(
"state")).available < 1024)
90 cwarn <<
"Not enough available space found on hard drive. Please free some up and then re-run. Bailing.";
91 BOOST_THROW_EXCEPTION(NotEnoughAvailableSpace());
97 (path / fs::path(
"state")) <<
98 "already open. You appear to have another instance of ethereum running. Bailing.";
99 BOOST_THROW_EXCEPTION(DatabaseAlreadyOpen());
113 BOOST_THROW_EXCEPTION(InvalidAccountStartNonceInState());
114 return m_accountStartNonce;
120 m_accountStartNonce = _actual;
121 else if (m_accountStartNonce != _actual)
122 BOOST_THROW_EXCEPTION(IncorrectAccountStartNonceInState());
125 void State::removeEmptyAccounts()
127 for (
auto& i: m_cache)
128 if (i.second.isDirty() && i.second.isEmpty())
139 m_cache = _s.m_cache;
140 m_unchangedCacheEntries = _s.m_unchangedCacheEntries;
141 m_nonExistingAccountsCache = _s.m_nonExistingAccountsCache;
142 m_touched = _s.m_touched;
143 m_accountStartNonce = _s.m_accountStartNonce;
149 return const_cast<State*
>(
this)->account(_a);
154 auto it = m_cache.find(_addr);
155 if (it != m_cache.end())
158 if (m_nonExistingAccountsCache.count(_addr))
162 string stateBack = m_state.at(_addr);
163 if (stateBack.empty())
165 m_nonExistingAccountsCache.insert(_addr);
169 clearCacheIfTooLarge();
171 RLP state(stateBack);
172 auto i = m_cache.emplace(
173 std::piecewise_construct,
174 std::forward_as_tuple(_addr),
175 std::forward_as_tuple(state[0].toInt<u256>(), state[1].toInt<u256>(), state[2].toHash<h256>(), state[3].toHash<h256>(),
Account::Unchanged)
177 m_unchangedCacheEntries.push_back(_addr);
178 return &i.first->second;
181 void State::clearCacheIfTooLarge()
const 184 while (m_unchangedCacheEntries.size() > 1000)
188 size_t const randomIndex = std::uniform_int_distribution<size_t>(0, m_unchangedCacheEntries.size() - 1)(
dev::s_fixedHashEngine);
190 Address const addr = m_unchangedCacheEntries[randomIndex];
191 swap(m_unchangedCacheEntries[randomIndex], m_unchangedCacheEntries.back());
192 m_unchangedCacheEntries.pop_back();
194 auto cacheEntry = m_cache.find(addr);
195 if (cacheEntry != m_cache.end() && !cacheEntry->second.isDirty())
196 m_cache.erase(cacheEntry);
203 removeEmptyAccounts();
207 m_unchangedCacheEntries.clear();
213 unordered_map<Address, u256> ret;
214 for (
auto& i: m_cache)
215 if (i.second.isAlive())
216 ret[i.first] = i.second.balance();
217 for (
auto const& i: m_state)
218 if (m_cache.find(i.first) == m_cache.end())
222 BOOST_THROW_EXCEPTION(InterfaceNotSupported() <<
errinfo_interface(
"State::addresses()"));
227 h256 const& _beginHash,
size_t _maxResults)
const 233 for (
auto it = m_state.hashedLowerBound(_beginHash); it != m_state.hashedEnd(); ++it)
235 auto const address =
Address(it.key());
236 auto const itCachedAddress = m_cache.find(address);
239 if (itCachedAddress != m_cache.
end() && itCachedAddress->second.isDirty() &&
240 !itCachedAddress->second.isAlive())
246 nextKey =
h256((*it).first);
250 h256 const hashedAddress((*it).first);
258 for (
auto const& addressAndAccount : m_cache)
260 auto const& address = addressAndAccount.first;
261 auto const addressHash =
sha3(address);
262 auto const& account = addressAndAccount.second;
263 if (account.
isDirty() && account.
isAlive() && addressHash >= _beginHash)
264 cacheAddresses.emplace(addressHash, address);
268 addresses.insert(cacheAddresses.begin(), cacheAddresses.end());
273 auto itEnd = std::next(
addresses.begin(), _maxResults);
274 nextKey = itEnd->first;
285 m_unchangedCacheEntries.clear();
286 m_nonExistingAccountsCache.clear();
293 return !!account(_id);
298 if (
Account const* a = account(_address))
299 return !a->isEmpty();
306 if (
auto a = account(_id))
314 if (
auto a = account(_id))
322 if (
Account* a = account(_addr))
324 auto oldNonce = a->nonce();
326 m_changeLog.emplace_back(_addr, oldNonce);
335 if (
Account* a = account(_addr))
337 auto oldNonce = a->nonce();
338 a->setNonce(_newNonce);
339 m_changeLog.emplace_back(_addr, oldNonce);
343 createAccount(_addr,
Account(_newNonce, 0));
356 if (!a->isDirty() && a->isEmpty())
362 a->addBalance(_amount);
377 if (!a || a->
balance() < _value)
399 void State::createAccount(
Address const& _address,
Account const&& _account)
401 assert(!
addressInUse(_address) &&
"Account already exists");
402 m_cache[_address] = std::move(_account);
403 m_nonExistingAccountsCache.erase(_address);
409 if (
auto a = account(_addr))
416 if (
auto a = account(_addr))
419 return m_accountStartNonce;
424 if (
Account const* a = account(_id))
425 return a->storageValue(_key, m_db);
432 m_changeLog.emplace_back(_contract, _key,
storage(_contract, _key));
433 m_cache[_contract].setStorage(_key, _value);
438 if (
Account const* a = account(_contract))
439 return a->originalStorageValue(_key, m_db);
446 h256 const& oldHash{m_cache[_contract].baseRoot()};
450 m_cache[_contract].clearStorage();
456 map<h256, pair<u256, u256>> ret;
458 if (
Account const* a = account(_id))
461 if (
h256 root = a->baseRoot())
465 for (
auto it = memdb.hashedBegin(); it != memdb.hashedEnd(); ++it)
467 h256 const hashedKey((*it).first);
470 ret[hashedKey] = make_pair(key, value);
475 for (
auto const& i : a->storageOverlay())
477 h256 const key = i.first;
482 ret.erase(hashedKey);
488 BOOST_THROW_EXCEPTION(InterfaceNotSupported() <<
errinfo_interface(
"State::storage(Address const& _id)"));
494 string s = m_state.at(_id);
505 Account const* a = account(_addr);
509 if (a->
code().empty())
522 m_changeLog.emplace_back(_address,
code(_address));
523 m_cache[_address].setCode(std::move(_code));
528 if (
Account const* a = account(_a))
529 return a->codeHash();
536 if (
Account const* a = account(_a))
539 return a->code().size();
542 if (codeSizeCache.contains(
codeHash))
546 size_t size =
code(_a).size();
547 codeSizeCache.store(
codeHash, size);
557 return m_changeLog.size();
562 while (_savepoint != m_changeLog.size())
564 auto& change = m_changeLog.back();
565 auto& account = m_cache[change.address];
584 m_cache.erase(change.address);
587 account.
setCode(std::move(change.oldCode));
591 m_unchangedCacheEntries.emplace_back(change.address);
594 m_changeLog.pop_back();
602 Executive e(*
this, _envInfo, _sealEngine);
612 bool const statusCode = executeTransaction(e, _t, onOp);
614 bool removeEmptyAccounts =
false;
631 return make_pair(res, receipt);
637 for (
unsigned i = 0; i < _txCount; ++i)
639 EnvInfo envInfo(_block.
info(), _lastHashes, gasUsed);
641 Executive e(*
this, envInfo, _sealEngine);
644 gasUsed += e.gasUsed();
670 _out <<
"--- " << _s.
rootHash() << std::endl;
672 std::set<Address> dtr;
675 d.
insert(i.first), dtr.insert(i.first);
676 for (
auto i: _s.m_cache)
681 auto it = _s.m_cache.find(i);
682 Account* cache = it != _s.m_cache.end() ? &it->second :
nullptr;
683 string rlpString = dtr.count(i) ? trie.at(i) :
"";
687 if (cache && !cache->
isAlive())
688 _out <<
"XXX " << i << std::endl;
691 string lead = (cache ? r ?
" * " :
" + " :
" ");
695 stringstream contout;
699 std::map<u256, u256> mem;
701 std::set<u256> delta;
702 std::set<u256> cached;
706 for (
auto const& j: memdb)
707 mem[j.first] =
RLP(j.second).
toInt<
u256>(), back.insert(j.first);
712 if ((!mem.count(j.first) && j.second) || (mem.count(j.first) && mem.at(j.first) != j.second))
713 mem[j.first] = j.second, delta.insert(j.first);
715 cached.insert(j.first);
718 lead = (lead ==
" . ") ?
"*.* " :
"*** ";
730 for (
auto const& j: mem)
732 contout << std::endl << (delta.count(j.first) ? back.count(j.first) ?
" * " :
" + " : cached.count(j.first) ?
" . " :
" ") << std::hex << nouppercase << std::setw(64) << j.first <<
": " << std::setw(0) << j.second ;
734 contout << std::endl <<
"XXX " << std::hex << nouppercase << std::setw(64) << j.first <<
"";
737 contout <<
" [SIMPLE]";
738 _out << lead << i <<
": " << std::dec << (cache ? cache->
nonce() : r[0].
toInt<
u256>()) <<
" #:" << (cache ? cache->
balance() : r[1].
toInt<
u256>()) << contout.str() << std::endl;
746 o_s = _block.
state();
762 for (
auto const& i: _cache)
763 if (i.second.isDirty())
765 if (!i.second.isAlive())
770 s << i.second.nonce() << i.second.balance();
772 if (i.second.storageOverlay().empty())
774 assert(i.second.baseRoot());
775 s.
append(i.second.baseRoot());
780 for (
auto const& j: i.second.storageOverlay())
782 storageDB.
insert(j.first,
rlp(j.second));
784 storageDB.remove(j.first);
785 assert(storageDB.root());
786 s.
append(storageDB.root());
789 if (i.second.hasNewCode())
791 h256 ch = i.second.codeHash();
794 _state.db()->
insert(ch, &i.second.code());
798 s << i.second.codeHash();
h256 stateRootBeforeTx(unsigned _i) const
u256 getNonce(Address const &_addr) const
State(u256 const &_accountStartNonce)
Default constructor; creates with a blank database prepopulated with the genesis block.
u256 originalStorageValue(Address const &_contract, u256 const &_key) const
_T toInt(int _flags=Strict) const
Converts to int of type given; if isData(), decodes as big-endian bytestream.
std::unordered_map< Address, u256 > addresses() const
bytes const & code(Address const &_addr) const
u256 storage(Address const &_contract, u256 const &_memory) const
vector_ref< _T > cropped(size_t _begin, size_t _count) const
std::function< void(uint64_t, uint64_t, Instruction, bigint, bigint, bigint, VMFace const *, ExtVMFace const *)> OnOpFunc
auto end() const -> typename std::array< byte, N >::const_iterator
void commit(CommitBehaviour _commitBehaviour)
SealEngineFace * sealEngine() const
std::unordered_map< Address, Account > AccountMap
void swap(dev::eth::Watch &_a, dev::eth::Watch &_b)
Implements the blockchain database. All data this gives is disk-backed. .
bytes rlp(_T _t)
Export a single item in RLP format, returning a byte array.
RLPStream & append(unsigned _s)
Append given datum to the byte stream.
void noteAccountStartNonce(u256 const &_actual)
std::ostream & operator<<(std::ostream &_out, BlockHeader const &_bi)
void rollback(size_t _savepoint)
Revert all recent changes up to the given _savepoint savepoint.
void clearStorage(Address const &_contract)
Clear the storage root hash of an account to the hash of the empty trie.
std::unordered_map< u256, u256 > const & storageOverlay() const
Account starts as though it has not been changed.
void setCode(Address const &_address, bytes &&_code)
Sets the code of the account. Must only be called during / after contract creation.
LastBlockHashesFace const & lastBlockHashes() const
Interface for getting a list of recent block hashes .
Transactions const & pending() const
Get the list of pending transactions.
void noteCode(bytesConstRef _code)
void setNonce(u256 const &_nonce)
New code was added to an account (by "create" message execution).
std::string toString(std::chrono::time_point< T > const &_e, std::string const &_format="%F %T")
Description of the result of executing a transaction.
Account was touched for the first time.
bool go(OnOpFunc const &_onOp=OnOpFunc())
void populateFrom(AccountMap const &_map)
Populate the state from the given AccountMap. Just uses dev::eth::commit().
bool sha3(bytesConstRef _input, bytesRef o_output) noexcept
std::random_device s_fixedHashEngine
bytes const & code() const
Active model of a block within the block chain. Keeps track of all transactions, receipts and state f...
void setStorageRoot(h256 const &_root)
Set the storage root. Used when clearStorage() is reverted.
ChainOperationParams const & chainParams() const
void kill(Address _a)
Delete an account (used for processing suicides).
Base class for all exceptions.
std::pair< ExecutionResult, TransactionReceipt > execute(EnvInfo const &_envInfo, SealEngineFace const &_sealEngine, Transaction const &_t, Permanence _p=Permanence::Committed, OnOpFunc const &_onOp=OnOpFunc())
void store(h256 const &_hash, size_t size)
void createContract(Address const &_address)
Create a contract at the given address (with unset code and unchanged balance).
bool addressInUse(Address const &_address) const
Check if the address is in use.
u256 constexpr Invalid256
void setBalance(Address const &_addr, u256 const &_value)
void insert(KeyType _k, bytesConstRef _value)
std::vector< byte > bytes
h256 storageRoot(Address const &_contract) const
Get the root of the storage of an account.
static std::unique_ptr< DatabaseFace > create()
bool addressHasCode(Address const &_address) const
Check if the address contains executable code.
Message-call/contract-creation executor; useful for executing transactions.
u256 balance(Address const &_id) const
bytes const & out() const
Read the byte stream.
Encodes a transaction, ready to be exported to or freshly imported from RLP.
u256 const & gasUsed() const
Account nonce was changed.
void setCode(bytes &&_code)
Sets the code of the account. Used by "create" messages.
std::string lookup(h256 const &_h) const
void setRoot(h256 const &_root)
Resets any uncommitted changes to the cache.
std::map< h256, Address > AddressMap
void initialize(bytesConstRef _transaction)
Initializes the executive for evaluating a transaction. You must call finalize() at some point follow...
State const & state() const
Get the backing state object.
State & operator=(State const &_s)
Copy state object.
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void > > u256
u256 const & requireAccountStartNonce() const
void setStorage(Address const &_contract, u256 const &_location, u256 const &_value)
Set the value of a storage position of an account.
void addBalance(u256 _value)
Increments the balance of this account by the given amount.
void setStorage(u256 _p, u256 _v)
BlockHeader const & info() const
Get the header information on the present block.
void addBalance(Address const &_id, u256 const &_amount)
#define clog(SEVERITY, CHANNEL)
static CodeSizeCache & instance()
Uncommitted state for change log readings in tests.
h256 rootHash() const
The hash of the root of our state tree.
const unsigned c_databaseVersion
Current database version.
void setNonce(Address const &_addr, u256 const &_newNonce)
Set the account nonce.
void executeBlockTransactions(Block const &_block, unsigned _txCount, LastBlockHashesFace const &_lastHashes, SealEngineFace const &_sealEngine)
std::string toHex(Iterator _it, Iterator _end, std::string const &_prefix)
u256 const & balance() const
AddressHash commit(AccountMap const &_cache, SecureTrieDB< Address, DB > &_state)
static OverlayDB openDB(boost::filesystem::path const &_path, h256 const &_genesisHash, WithExisting _we=WithExisting::Trust)
Open a DB - useful for passing into the constructor & keeping for other states that are necessary...
OnOpFunc simpleTrace()
Operation function for providing a simple trace of the VM execution.
boost::error_info< struct tag_interface, std::string > errinfo_interface
Class for writing to an RLP bytestream.
_N toHash(int _flags=Strict) const
void subBalance(Address const &_addr, u256 const &_value)
#define DEV_IGNORE_EXCEPTIONS(X)
size_t codeSize(Address const &_contract) const
State & createIntermediateState(State &o_s, Block const &_block, unsigned _txIndex, BlockChain const &_bc)
LogEntries const & logs() const
void setResultRecipient(ExecutionResult &_res)
Collect execution results in the result storage provided.
OverlayDB const & db() const
Account was created (it was not existing before).
bool accountNonemptyAndExisting(Address const &_address) const
void incNonce(Address const &_id)
Increament the account nonce.
h256 codeHash(Address const &_contract) const
std::unordered_set< h160 > AddressHash
A hash set of Ethereum addresses.