Skip to content

Commit

Permalink
Fix transient storage
Browse files Browse the repository at this point in the history
  • Loading branch information
timemarkovqtum committed Sep 11, 2024
1 parent 052b98c commit b457176
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 19 deletions.
5 changes: 5 additions & 0 deletions src/eth_client/libethereum/ExtVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,11 @@ void ExtVM::setStore(u256 _n, u256 _v)
m_s.setStorage(myAddress, _n, _v);
}

void ExtVM::setTransientStore(u256 _n, u256 _v)
{
m_s.setTransientStorage(myAddress, _n, _v);
}

CreateResult ExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _code, Instruction _op, u256 _salt, OnOpFunc const& _onOp)
{
Executive e{m_s, envInfo(), m_sealEngine, depth + 1};
Expand Down
6 changes: 6 additions & 0 deletions src/eth_client/libethereum/ExtVM.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ class ExtVM : public ExtVMFace
/// Write a value in storage.
void setStore(u256 _n, u256 _v) final;

/// Read transient storage location.
u256 transientStore(u256 _n) final { return m_s.transientStorage(myAddress, _n); }

/// Write a value in transient storage.
void setTransientStore(u256 _n, u256 _v) final;

/// Read original storage value (before modifications in the current transaction).
u256 originalStorageValue(u256 const& _key) final
{
Expand Down
22 changes: 22 additions & 0 deletions src/eth_client/libethereum/State.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,23 @@ void State::setStorage(Address const& _contract, u256 const& _key, u256 const& _
m_cache[_contract].setStorage(_key, _value);
}

u256 State::transientStorage(Address const& _id, u256 const& _key) const
{
const auto accountIter = m_transientCache.find(_id);
if (accountIter == m_transientCache.end())
return {};

const auto storageIter = accountIter->second.transientStorage.find(_key);
if (storageIter != accountIter->second.transientStorage.end())
return storageIter->second;
return {};
}

void State::setTransientStorage(Address const& _contract, u256 const& _key, u256 const& _value)
{
m_transientCache[_contract].transientStorage[_key] = _value;
}

u256 State::originalStorageValue(Address const& _contract, u256 const& _key) const
{
if (Account const* a = account(_contract))
Expand All @@ -460,6 +477,11 @@ void State::clearStorage(Address const& _contract)
m_cache[_contract].clearStorage();
}

void State::clearTransientStorage()
{
m_transientCache.clear();
}

map<h256, pair<u256, u256>> State::storage(Address const& _id) const
{
#if ETH_FATDB
Expand Down
19 changes: 19 additions & 0 deletions src/eth_client/libethereum/State.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,13 @@ struct Change

using ChangeLog = std::vector<Change>;

class TransientAccount
{
public:
/// The account transient storage.
std::unordered_map<u256, u256> transientStorage;
};

/**
* Model of an Ethereum state, essentially a facade for the trie.
*
Expand Down Expand Up @@ -233,6 +240,13 @@ class State
/// Set the value of a storage position of an account.
void setStorage(Address const& _contract, u256 const& _location, u256 const& _value);

/// Get the value of a transient storage position of an account.
/// @returns 0 if no account exists at that address.
u256 transientStorage(Address const& _contract, u256 const& _memory) const;

/// Set the value of a transient storage position of an account.
void setTransientStorage(Address const& _contract, u256 const& _location, u256 const& _value);

/// Get the original value of a storage position of an account (before modifications saved in
/// account cache).
/// @returns 0 if no account exists at that address.
Expand All @@ -241,6 +255,9 @@ class State
/// Clear the storage root hash of an account to the hash of the empty trie.
void clearStorage(Address const& _contract);

/// Clear the transient storage.
void clearTransientStorage();

/// Create a contract at the given address (with unset code and unchanged balance).
void createContract(Address const& _address);

Expand Down Expand Up @@ -340,6 +357,8 @@ class State
/// Our address cache. This stores the states of each address that has (or at least might have)
/// been changed.
mutable std::unordered_map<Address, Account> m_cache;
/// Our address cache. This stores the states of each address that has transient storage.
mutable std::unordered_map<Address, TransientAccount> m_transientCache;
/// Tracks entries in m_cache that can potentially be purged if it grows too large.
mutable std::vector<Address> m_unchangedCacheEntries;
/// Tracks addresses that are known to not exist.
Expand Down
28 changes: 12 additions & 16 deletions src/eth_client/libevm/ExtVMFace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,26 +239,22 @@ evmc_access_status EvmCHost::access_storage(const evmc::address& addr,
return access_status;
}

evmc::bytes32 EvmCHost::get_transient_storage(const evmc::address& addr, const evmc::bytes32& key) const noexcept
evmc::bytes32 EvmCHost::get_transient_storage(const evmc::address& _addr, const evmc::bytes32& _key) const noexcept
{
record_account_access(addr);

const auto account_iter = accounts.find(addr);
if (account_iter == accounts.end())
return {};

const auto storage_iter = account_iter->second.transient_storage.find(key);
if (storage_iter != account_iter->second.transient_storage.end())
return storage_iter->second;
return {};
assert(fromEvmC(_addr) == m_extVM.myAddress);
record_account_access(_addr);
return toEvmC(m_extVM.transientStore(fromEvmC(_key)));
}

void EvmCHost::set_transient_storage(const evmc::address& addr,
const evmc::bytes32& key,
const evmc::bytes32& value) noexcept
void EvmCHost::set_transient_storage(const evmc::address& _addr,
const evmc::bytes32& _key,
const evmc::bytes32& _value) noexcept
{
record_account_access(addr);
accounts[addr].transient_storage[key] = value;
assert(fromEvmC(_addr) == m_extVM.myAddress);
record_account_access(_addr);
u256 const index = fromEvmC(_key);
u256 const newValue = fromEvmC(_value);
m_extVM.setTransientStore(index, newValue);
}

void EvmCHost::record_account_access(const evmc::address& addr) const
Expand Down
9 changes: 6 additions & 3 deletions src/eth_client/libevm/ExtVMFace.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,12 @@ class ExtVMFace
/// Write a value in storage.
virtual void setStore(u256, u256) {}

/// Read transient storage location.
virtual u256 transientStore(u256) { return 0; }

/// Write a value in transient storage.
virtual void setTransientStore(u256, u256) {}

/// Read original storage value (before modifications in the current transaction).
virtual u256 originalStorageValue(u256 const&) { return 0; }

Expand Down Expand Up @@ -308,9 +314,6 @@ struct AccessAccount
/// The account storage map.
std::map<evmc::bytes32, access_value> storage;

/// The account transient storage.
std::unordered_map<evmc::bytes32, evmc::bytes32> transient_storage;

/// Default constructor.
AccessAccount() noexcept = default;
};
Expand Down
13 changes: 13 additions & 0 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2936,7 +2936,20 @@ void LastHashes::clear()
m_lastHashes.clear();
}

class ExecTransientStorage
{
public:
void init() {
globalState->clearTransientStorage();
}
~ExecTransientStorage() {
globalState->clearTransientStorage();
}
};

bool ByteCodeExec::performByteCode(dev::eth::Permanence type){
ExecTransientStorage storage;
storage.init();
for(QtumTransaction& tx : txs){
//validate VM version
if(tx.getVersion().toRaw() != VersionVM::GetEVMDefault().toRaw()){
Expand Down

0 comments on commit b457176

Please sign in to comment.