From 6e2df6a0b84073f68ff282b607c0296ea928ee7d Mon Sep 17 00:00:00 2001 From: kladkogex <13399135+kladkogex@users.noreply.github.com> Date: Wed, 3 May 2023 19:58:46 +0100 Subject: [PATCH 1/7] State delete fixes --- libbatched-io/batched_db.cpp | 12 ++++++++++++ libbatched-io/batched_db.h | 11 ++++++++++- libdevcore/LevelDB.cpp | 19 +++++++++++++++++++ libdevcore/LevelDB.h | 3 +++ libdevcore/ManuallyRotatingLevelDB.cpp | 9 +++++++++ libdevcore/ManuallyRotatingLevelDB.h | 3 +++ libdevcore/SplitDB.cpp | 14 ++++++++++++++ libdevcore/SplitDB.h | 3 +++ libdevcore/db.h | 5 +++++ libskale/OverlayDB.cpp | 6 +++++- libskale/State.cpp | 7 +++++-- 11 files changed, 88 insertions(+), 4 deletions(-) diff --git a/libbatched-io/batched_db.cpp b/libbatched-io/batched_db.cpp index 92e0019a9..08bd424ce 100644 --- a/libbatched-io/batched_db.cpp +++ b/libbatched-io/batched_db.cpp @@ -59,4 +59,16 @@ void db_splitter::prefixed_db::forEach( } ); } +void db_splitter::prefixed_db::forEachWithPrefix(std::string& _prefix, + std::function< bool( dev::db::Slice, dev::db::Slice ) > f ) const { + backend->forEachWithPrefix(_prefix, [&]( dev::db::Slice _key, dev::db::Slice _val ) -> bool { + if ( _key[0] != this->prefix ) + return true; + dev::db::Slice key_short = dev::db::Slice( _key.data() + 1, _key.size() - 1 ); + return f( key_short, _val ); + } ); +} + + + } // namespace batched_io diff --git a/libbatched-io/batched_db.h b/libbatched-io/batched_db.h index aad77550d..7ee023552 100644 --- a/libbatched-io/batched_db.h +++ b/libbatched-io/batched_db.h @@ -18,7 +18,8 @@ class db_operations_face { virtual std::string lookup( dev::db::Slice _key ) const = 0; virtual bool exists( dev::db::Slice _key ) const = 0; virtual void forEach( std::function< bool( dev::db::Slice, dev::db::Slice ) > f ) const = 0; - + virtual void forEachWithPrefix( + std::string& _prefix, std::function< bool( dev::db::Slice, dev::db::Slice ) > f ) const = 0; virtual ~db_operations_face() = default; }; @@ -69,6 +70,12 @@ class batched_db : public db_face { m_db->forEach( f ); } + virtual void forEachWithPrefix( + std::string& _prefix, std::function< bool( dev::db::Slice, dev::db::Slice ) > f ) const { + std::lock_guard< std::mutex > foreach_lock( m_batch_mutex ); + m_db->forEachWithPrefix( _prefix, f ); + } + virtual ~batched_db(); protected: @@ -105,6 +112,8 @@ class db_splitter { virtual std::string lookup( dev::db::Slice _key ) const; virtual bool exists( dev::db::Slice _key ) const; virtual void forEach( std::function< bool( dev::db::Slice, dev::db::Slice ) > f ) const; + virtual void forEachWithPrefix( + std::string& _prefix, std::function< bool( dev::db::Slice, dev::db::Slice ) > f ) const; protected: virtual void recover() { /* nothing */ diff --git a/libdevcore/LevelDB.cpp b/libdevcore/LevelDB.cpp index 331935832..152c0df34 100644 --- a/libdevcore/LevelDB.cpp +++ b/libdevcore/LevelDB.cpp @@ -198,6 +198,25 @@ void LevelDB::forEach( std::function< bool( Slice, Slice ) > f ) const { } } + +void LevelDB::forEachWithPrefix(std::string& _prefix, std::function< bool( Slice, Slice ) > f ) const { + cwarn << "Iterating over the entire LevelDB database: " << this->m_path; + std::unique_ptr< leveldb::Iterator > itr( m_db->NewIterator( m_readOptions ) ); + if ( itr == nullptr ) { + BOOST_THROW_EXCEPTION( DatabaseError() << errinfo_comment( "null iterator" ) ); + } + auto keepIterating = true; + auto prefixSlice = leveldb::Slice(_prefix); + for ( itr->Seek(prefixSlice); keepIterating && itr->Valid() + && itr->key().starts_with(prefixSlice); itr->Next() ) { + auto const dbKey = itr->key(); + auto const dbValue = itr->value(); + Slice const key( dbKey.data(), dbKey.size() ); + Slice const value( dbValue.data(), dbValue.size() ); + keepIterating = f( key, value ); + } +} + h256 LevelDB::hashBase() const { std::unique_ptr< leveldb::Iterator > it( m_db->NewIterator( m_readOptions ) ); if ( it == nullptr ) { diff --git a/libdevcore/LevelDB.h b/libdevcore/LevelDB.h index 69d43df81..e5c1e0171 100644 --- a/libdevcore/LevelDB.h +++ b/libdevcore/LevelDB.h @@ -52,6 +52,9 @@ class LevelDB : public DatabaseFace { void forEach( std::function< bool( Slice, Slice ) > f ) const override; + void forEachWithPrefix( + std::string& _prefix, std::function< bool( Slice, Slice ) > f ) const override; + h256 hashBase() const override; h256 hashBaseWithPrefix( char _prefix ) const; diff --git a/libdevcore/ManuallyRotatingLevelDB.cpp b/libdevcore/ManuallyRotatingLevelDB.cpp index 16103d474..4f36242c0 100644 --- a/libdevcore/ManuallyRotatingLevelDB.cpp +++ b/libdevcore/ManuallyRotatingLevelDB.cpp @@ -67,6 +67,15 @@ void ManuallyRotatingLevelDB::forEach( std::function< bool( Slice, Slice ) > f ) } } +void ManuallyRotatingLevelDB::forEachWithPrefix( + std::string& _prefix, std::function< bool( Slice, Slice ) > f ) const { + std::shared_lock< std::shared_mutex > lock( m_mutex ); + for ( const auto& p : *io_backend ) { + p->forEachWithPrefix( _prefix, f ); + } +} + + h256 ManuallyRotatingLevelDB::hashBase() const { std::shared_lock< std::shared_mutex > lock( m_mutex ); secp256k1_sha256_t ctx; diff --git a/libdevcore/ManuallyRotatingLevelDB.h b/libdevcore/ManuallyRotatingLevelDB.h index bdedf5d54..12b98ce3f 100644 --- a/libdevcore/ManuallyRotatingLevelDB.h +++ b/libdevcore/ManuallyRotatingLevelDB.h @@ -41,6 +41,9 @@ class ManuallyRotatingLevelDB : public DatabaseFace { } virtual void forEach( std::function< bool( Slice, Slice ) > f ) const; + virtual void forEachWithPrefix( + std::string& _prefix, std::function< bool( Slice, Slice ) > f ) const; + virtual h256 hashBase() const; }; diff --git a/libdevcore/SplitDB.cpp b/libdevcore/SplitDB.cpp index 2ba662738..8965628d5 100644 --- a/libdevcore/SplitDB.cpp +++ b/libdevcore/SplitDB.cpp @@ -100,6 +100,20 @@ void SplitDB::PrefixedDB::forEach( std::function< bool( Slice, Slice ) > f ) con } ); } + +void SplitDB::PrefixedDB::forEachWithPrefix( + std::string& _prefix, std::function< bool( Slice, Slice ) > f ) const { + std::unique_lock< std::shared_mutex > lock( this->backend_mutex ); + auto prefixedString = std::to_string( this->prefix ) + _prefix; + backend->forEachWithPrefix( prefixedString, [&]( Slice _key, Slice _val ) -> bool { + if ( _key[0] != this->prefix ) + return true; + Slice key_short = Slice( _key.data() + 1, _key.size() - 1 ); + return f( key_short, _val ); + } ); +} + + h256 SplitDB::PrefixedDB::hashBase() const { // HACK TODO implement that it would work with any DatabaseFace* const LevelDB* ldb = dynamic_cast< const LevelDB* >( backend.get() ); diff --git a/libdevcore/SplitDB.h b/libdevcore/SplitDB.h index 3a1774b55..1f939ff6d 100644 --- a/libdevcore/SplitDB.h +++ b/libdevcore/SplitDB.h @@ -36,6 +36,9 @@ class SplitDB { virtual void commit( std::unique_ptr< WriteBatchFace > _batch ); virtual void forEach( std::function< bool( Slice, Slice ) > f ) const; + virtual void forEachWithPrefix( + std::string& _prefix, std::function< bool( Slice, Slice ) > f ) const; + virtual h256 hashBase() const; private: diff --git a/libdevcore/db.h b/libdevcore/db.h index a978cb302..4c0f39e22 100644 --- a/libdevcore/db.h +++ b/libdevcore/db.h @@ -66,6 +66,11 @@ class DatabaseFace { // of each record in the database. If `f` returns false, the `forEach` // method must return immediately. virtual void forEach( std::function< bool( Slice, Slice ) > f ) const = 0; + + virtual void forEachWithPrefix( + std::string& _prefix, std::function< bool( Slice, Slice ) > f ) const = 0; + + virtual h256 hashBase() const = 0; virtual bool discardCreatedBatches() { return false; } diff --git a/libskale/OverlayDB.cpp b/libskale/OverlayDB.cpp index bb1c5fa1d..12470d395 100644 --- a/libskale/OverlayDB.cpp +++ b/libskale/OverlayDB.cpp @@ -330,7 +330,9 @@ std::unordered_map< h160, string > OverlayDB::accounts() const { std::unordered_map< u256, u256 > OverlayDB::storage( const dev::h160& _address ) const { unordered_map< u256, u256 > storage; if ( m_db_face ) { - m_db_face->forEach( [&storage, &_address]( Slice key, Slice value ) { + // iterate of a keys that start with the given substring + string prefix((const char*) _address.data(), _address.size); + m_db_face->forEachWithPrefix(prefix, [&storage, &_address]( Slice key, Slice value ) { if ( key.size() == h160::size + h256::size ) { // key is storage address string keyString( key.begin(), key.end() ); @@ -342,6 +344,8 @@ std::unordered_map< u256, u256 > OverlayDB::storage( const dev::h160& _address ) u256 memoryValue = h256( string( value.begin(), value.end() ), h256::ConstructFromStringType::FromBinary ); storage[memoryAddress] = memoryValue; + } else { + cerror << "Address mismatch in:" << __FUNCTION__; } } return true; diff --git a/libskale/State.cpp b/libskale/State.cpp index 99f0e3ab6..45d222fbd 100644 --- a/libskale/State.cpp +++ b/libskale/State.cpp @@ -508,7 +508,11 @@ void State::commit( dev::eth::CommitBehaviour _commitBehaviour ) { if ( !account.isAlive() ) { m_db_ptr->kill( address ); m_db_ptr->killAuxiliary( address, Auxiliary::CODE ); - // TODO: remove account storage + + if (2023) { + clearStorage( address ); + } + } else { RLPStream rlpStream( 4 ); @@ -777,7 +781,6 @@ void State::clearStorage( Address const& _contract ) { totalStorageUsed_ -= ( accStorageUsed + storageUsage[_contract] ); acc->updateStorageUsage( -accStorageUsed ); - // TODO Do we need to clear storageUsage[_contract] here? } bytes const& State::code( Address const& _addr ) const { From bcb5bda21c01a5fcfcbc8a4ed1210233c9e32838 Mon Sep 17 00:00:00 2001 From: kladkogex <13399135+kladkogex@users.noreply.github.com> Date: Sun, 18 Jun 2023 14:33:32 +0100 Subject: [PATCH 2/7] 1347 clang format --- libskale/OverlayDB.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libskale/OverlayDB.cpp b/libskale/OverlayDB.cpp index 12470d395..2c6b5eebb 100644 --- a/libskale/OverlayDB.cpp +++ b/libskale/OverlayDB.cpp @@ -331,8 +331,8 @@ std::unordered_map< u256, u256 > OverlayDB::storage( const dev::h160& _address ) unordered_map< u256, u256 > storage; if ( m_db_face ) { // iterate of a keys that start with the given substring - string prefix((const char*) _address.data(), _address.size); - m_db_face->forEachWithPrefix(prefix, [&storage, &_address]( Slice key, Slice value ) { + string prefix( ( const char* ) _address.data(), _address.size ); + m_db_face->forEachWithPrefix( prefix, [&storage, &_address]( Slice key, Slice value ) { if ( key.size() == h160::size + h256::size ) { // key is storage address string keyString( key.begin(), key.end() ); @@ -345,7 +345,7 @@ std::unordered_map< u256, u256 > OverlayDB::storage( const dev::h160& _address ) h256::ConstructFromStringType::FromBinary ); storage[memoryAddress] = memoryValue; } else { - cerror << "Address mismatch in:" << __FUNCTION__; + cerror << "Address mismatch in:" << __FUNCTION__; } } return true; From cbf18f0da4f5030a2dffe58e3fb7d89d245adf1b Mon Sep 17 00:00:00 2001 From: kladkogex <13399135+kladkogex@users.noreply.github.com> Date: Sun, 18 Jun 2023 14:34:32 +0100 Subject: [PATCH 3/7] 1347 clang format --- libbatched-io/batched_db.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libbatched-io/batched_db.h b/libbatched-io/batched_db.h index 7ee023552..e2465d087 100644 --- a/libbatched-io/batched_db.h +++ b/libbatched-io/batched_db.h @@ -71,7 +71,7 @@ class batched_db : public db_face { } virtual void forEachWithPrefix( - std::string& _prefix, std::function< bool( dev::db::Slice, dev::db::Slice ) > f ) const { + std::string& _prefix, std::function< bool( dev::db::Slice, dev::db::Slice ) > f ) const { std::lock_guard< std::mutex > foreach_lock( m_batch_mutex ); m_db->forEachWithPrefix( _prefix, f ); } From 7f69ca458ed9d96e0737a4ba24966d434ea2f2c5 Mon Sep 17 00:00:00 2001 From: kladkogex <13399135+kladkogex@users.noreply.github.com> Date: Sun, 18 Jun 2023 14:36:15 +0100 Subject: [PATCH 4/7] 1347 clang format --- libdevcore/LevelDB.cpp | 9 +++++---- libskale/State.cpp | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libdevcore/LevelDB.cpp b/libdevcore/LevelDB.cpp index 152c0df34..e3efb967c 100644 --- a/libdevcore/LevelDB.cpp +++ b/libdevcore/LevelDB.cpp @@ -199,16 +199,17 @@ void LevelDB::forEach( std::function< bool( Slice, Slice ) > f ) const { } -void LevelDB::forEachWithPrefix(std::string& _prefix, std::function< bool( Slice, Slice ) > f ) const { +void LevelDB::forEachWithPrefix( + std::string& _prefix, std::function< bool( Slice, Slice ) > f ) const { cwarn << "Iterating over the entire LevelDB database: " << this->m_path; std::unique_ptr< leveldb::Iterator > itr( m_db->NewIterator( m_readOptions ) ); if ( itr == nullptr ) { BOOST_THROW_EXCEPTION( DatabaseError() << errinfo_comment( "null iterator" ) ); } auto keepIterating = true; - auto prefixSlice = leveldb::Slice(_prefix); - for ( itr->Seek(prefixSlice); keepIterating && itr->Valid() - && itr->key().starts_with(prefixSlice); itr->Next() ) { + auto prefixSlice = leveldb::Slice( _prefix ); + for ( itr->Seek( prefixSlice ); + keepIterating && itr->Valid() && itr->key().starts_with( prefixSlice ); itr->Next() ) { auto const dbKey = itr->key(); auto const dbValue = itr->value(); Slice const key( dbKey.data(), dbKey.size() ); diff --git a/libskale/State.cpp b/libskale/State.cpp index 45d222fbd..6f84e3849 100644 --- a/libskale/State.cpp +++ b/libskale/State.cpp @@ -509,7 +509,7 @@ void State::commit( dev::eth::CommitBehaviour _commitBehaviour ) { m_db_ptr->kill( address ); m_db_ptr->killAuxiliary( address, Auxiliary::CODE ); - if (2023) { + if ( 2023 ) { clearStorage( address ); } From 07af226a5a6a29b89ae9a0e630bae8b57e4a1e82 Mon Sep 17 00:00:00 2001 From: kladkogex <13399135+kladkogex@users.noreply.github.com> Date: Sun, 18 Jun 2023 14:37:35 +0100 Subject: [PATCH 5/7] 1347 clang format --- libbatched-io/batched_db.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libbatched-io/batched_db.cpp b/libbatched-io/batched_db.cpp index 08bd424ce..4168ca41f 100644 --- a/libbatched-io/batched_db.cpp +++ b/libbatched-io/batched_db.cpp @@ -59,9 +59,9 @@ void db_splitter::prefixed_db::forEach( } ); } -void db_splitter::prefixed_db::forEachWithPrefix(std::string& _prefix, - std::function< bool( dev::db::Slice, dev::db::Slice ) > f ) const { - backend->forEachWithPrefix(_prefix, [&]( dev::db::Slice _key, dev::db::Slice _val ) -> bool { +void db_splitter::prefixed_db::forEachWithPrefix( + std::string& _prefix, std::function< bool( dev::db::Slice, dev::db::Slice ) > f ) const { + backend->forEachWithPrefix( _prefix, [&]( dev::db::Slice _key, dev::db::Slice _val ) -> bool { if ( _key[0] != this->prefix ) return true; dev::db::Slice key_short = dev::db::Slice( _key.data() + 1, _key.size() - 1 ); @@ -70,5 +70,4 @@ void db_splitter::prefixed_db::forEachWithPrefix(std::string& _prefix, } - } // namespace batched_io From f902c5478fa942933deb73c315b94de57fd40b3c Mon Sep 17 00:00:00 2001 From: kladkogex <13399135+kladkogex@users.noreply.github.com> Date: Sun, 18 Jun 2023 16:12:33 +0100 Subject: [PATCH 6/7] 1347 add patch --- libethcore/ChainOperationParams.h | 1 + libethereum/ChainParams.cpp | 5 +++++ libethereum/Client.cpp | 4 ++++ libskale/CMakeLists.txt | 1 + libskale/State.cpp | 3 ++- libskale/StorageDestructionPatch.cpp | 8 ++++++++ libskale/StorageDestructionPatch.h | 21 +++++++++++++++++++++ 7 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 libskale/StorageDestructionPatch.cpp create mode 100644 libskale/StorageDestructionPatch.h diff --git a/libethcore/ChainOperationParams.h b/libethcore/ChainOperationParams.h index b4bde16a7..9f528aaf5 100644 --- a/libethcore/ChainOperationParams.h +++ b/libethcore/ChainOperationParams.h @@ -173,6 +173,7 @@ struct SChain { time_t contractStoragePatchTimestamp = 0; time_t contractStorageZeroValuePatchTimestamp = 0; time_t verifyDaSigsPatchTimestamp = 0; + time_t storageDestructionPatchTimestamp = 0; SChain() { name = "TestChain"; diff --git a/libethereum/ChainParams.cpp b/libethereum/ChainParams.cpp index ea78be838..b69e209f3 100644 --- a/libethereum/ChainParams.cpp +++ b/libethereum/ChainParams.cpp @@ -257,6 +257,11 @@ ChainParams ChainParams::loadConfig( sChainObj.at( "verifyDaSigsPatchTimestamp" ).get_int64() : 0; + s.storageDestructionPatchTimestamp = + sChainObj.count( "storageDestructionPatchTimestamp" ) ? + sChainObj.at( "storageDestructionPatchTimestamp" ).get_int64() : + 0; + if ( sChainObj.count( "nodeGroups" ) ) { std::vector< NodeGroup > nodeGroups; for ( const auto& nodeGroupConf : sChainObj["nodeGroups"].get_obj() ) { diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 8c133c43a..4ca6b874c 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -155,6 +156,8 @@ Client::Client( ChainParams const& _params, int _networkID, chainParams().sChain.contractStorageZeroValuePatchTimestamp; VerifyDaSigsPatch::verifyDaSigsPatchTimestamp = chainParams().sChain.verifyDaSigsPatchTimestamp; RevertableFSPatch::revertableFSPatchTimestamp = chainParams().sChain.revertableFSPatchTimestamp; + StorageDestructionPatch::storageDestructionPatchTimestamp = + chainParams().sChain.storageDestructionPatchTimestamp; } Client::~Client() { @@ -747,6 +750,7 @@ size_t Client::syncTransactions( ContractStorageLimitPatch::lastBlockTimestamp = blockChain().info().timestamp(); ContractStorageZeroValuePatch::lastBlockTimestamp = blockChain().info().timestamp(); RevertableFSPatch::lastBlockTimestamp = blockChain().info().timestamp(); + StorageDestructionPatch::lastBlockTimestamp = blockChain().info().timestamp(); DEV_WRITE_GUARDED( x_working ) { diff --git a/libskale/CMakeLists.txt b/libskale/CMakeLists.txt index 9a8e361cc..8554401ff 100644 --- a/libskale/CMakeLists.txt +++ b/libskale/CMakeLists.txt @@ -18,6 +18,7 @@ set(sources AmsterdamFixPatch.cpp RevertableFSPatch.cpp OverlayFS.cpp + StorageDestructionPatch.cpp ) set(headers diff --git a/libskale/State.cpp b/libskale/State.cpp index 6f84e3849..5d861c2e1 100644 --- a/libskale/State.cpp +++ b/libskale/State.cpp @@ -46,6 +46,7 @@ #include #include +#include namespace fs = boost::filesystem; @@ -509,7 +510,7 @@ void State::commit( dev::eth::CommitBehaviour _commitBehaviour ) { m_db_ptr->kill( address ); m_db_ptr->killAuxiliary( address, Auxiliary::CODE ); - if ( 2023 ) { + if ( StorageDestructionPatch::isEnabled() ) { clearStorage( address ); } diff --git a/libskale/StorageDestructionPatch.cpp b/libskale/StorageDestructionPatch.cpp new file mode 100644 index 000000000..95ba9abe9 --- /dev/null +++ b/libskale/StorageDestructionPatch.cpp @@ -0,0 +1,8 @@ +#include "StorageDestructionPatch.h" + +time_t StorageDestructionPatch::storageDestructionPatchTimestamp; +time_t StorageDestructionPatch::lastBlockTimestamp; + +bool StorageDestructionPatch::isEnabled() { + return storageDestructionPatchTimestamp <= lastBlockTimestamp; +} \ No newline at end of file diff --git a/libskale/StorageDestructionPatch.h b/libskale/StorageDestructionPatch.h new file mode 100644 index 000000000..17340977b --- /dev/null +++ b/libskale/StorageDestructionPatch.h @@ -0,0 +1,21 @@ +#include +#include + +namespace dev { +namespace eth { +class Client; +} +} // namespace dev + +/* + * Context: enable effective storage destruction + */ +class StorageDestructionPatch : public SchainPatch { +public: + static bool isEnabled(); + +private: + friend class dev::eth::Client; + static time_t storageDestructionPatchTimestamp; + static time_t lastBlockTimestamp; +}; \ No newline at end of file From ce027e10c8f6eefd714f3acb26254d520840f14e Mon Sep 17 00:00:00 2001 From: kladkogex <13399135+kladkogex@users.noreply.github.com> Date: Sun, 18 Jun 2023 23:23:16 +0100 Subject: [PATCH 7/7] 1347 renaming --- libethereum/Executive.cpp | 3 ++- libskale/State.cpp | 19 ++++++++++--------- libskale/State.h | 5 +++++ 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 2ab8015e5..d3e93b6b8 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -55,7 +55,8 @@ std::string dumpStackAndMemory( LegacyVM const& _vm ) { std::string dumpStorage( ExtVM const& _ext ) { ostringstream o; o << " STORAGE\n"; - for ( auto const& i : _ext.state().storage( _ext.myAddress ) ) + // this function is called when a lock over the state already is acquired + for ( auto const& i : _ext.state().storage_WITHOUT_LOCK( _ext.myAddress ) ) o << showbase << hex << i.second.first << ": " << i.second.second << "\n"; return o.str(); } diff --git a/libskale/State.cpp b/libskale/State.cpp index 5d861c2e1..57430869d 100644 --- a/libskale/State.cpp +++ b/libskale/State.cpp @@ -658,8 +658,14 @@ void State::kill( Address _addr ) { // If the account is not in the db, nothing to kill. } + std::map< h256, std::pair< u256, u256 > > State::storage( const Address& _contract ) const { boost::shared_lock< boost::shared_mutex > lock( *x_db_ptr ); + return storage_WITHOUT_LOCK( _contract ); +} + + +std::map< h256, std::pair< u256, u256 > > State::storage_WITHOUT_LOCK( const Address& _contract ) const { if ( !checkVersion() ) { cerror << "Current state version is " << m_currentVersion << " but stored version is " << *m_storedVersion << endl; @@ -756,13 +762,6 @@ u256 State::originalStorageValue( Address const& _contract, u256 const& _key ) c } -// Clear storage needs to be called when a new contract is -// created for an address that included a different contract -// that was destroyed using selfdestruct op code -// The only way this can happen if one calls -// CREATE2, self-destruct, and then CREATE2 again, which is -// extremely rare and a bad security practice -// Note that in Shanhai fork the selfdestruct op code will be removed void State::clearStorage( Address const& _contract ) { // only clear storage if the storage used is not 0 @@ -773,8 +772,10 @@ void State::clearStorage( Address const& _contract ) { return; } - // TODO: This is extremely inefficient - for ( auto const& hashPairPair : storage( _contract ) ) { + // clearStorage is called from functions that already hold a read + // or write lock over the state Therefore, we can use + // storage_WITHOUT_LOCK() here + for ( auto const& hashPairPair : storage_WITHOUT_LOCK( _contract ) ) { auto const& key = hashPairPair.second.first; setStorage( _contract, key, 0 ); acc->setStorageCache( key, 0 ); diff --git a/libskale/State.h b/libskale/State.h index fae2671a7..31d26daa2 100644 --- a/libskale/State.h +++ b/libskale/State.h @@ -292,6 +292,11 @@ class State { std::map< dev::h256, std::pair< dev::u256, dev::u256 > > storage( dev::Address const& _contract ) const; + /// Not thread safe version of storage() that does not hold any locks + std::map< dev::h256, std::pair< dev::u256, dev::u256 > > storage_WITHOUT_LOCK( + const Address& _contract ) const; + + /// Get the code of an account. /// @returns bytes() if no account exists at that address. /// @warning The reference to the code is only valid until the access to