diff --git a/libdevcore/Exceptions.h b/libdevcore/Exceptions.h index 74315ff26..932276d01 100644 --- a/libdevcore/Exceptions.h +++ b/libdevcore/Exceptions.h @@ -44,6 +44,6 @@ struct FileError: virtual Exception {}; // error information to be added to exceptions typedef boost::error_info errinfo_invalidSymbol; -typedef boost::error_info errinfo_wrongAddress; +typedef boost::error_info errinfo_wrongAddress; typedef boost::error_info errinfo_comment; } diff --git a/libethereum/AddressState.cpp b/libethereum/Account.cpp similarity index 90% rename from libethereum/AddressState.cpp rename to libethereum/Account.cpp index 268440314..74b6ebe7b 100644 --- a/libethereum/AddressState.cpp +++ b/libethereum/Account.cpp @@ -14,17 +14,17 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file AddressState.cpp +/** @file Account.cpp * @author Gav Wood * @date 2014 */ -#include "AddressState.h" +#include "Account.h" #include using namespace std; using namespace dev; using namespace dev::eth; #pragma GCC diagnostic ignored "-Wunused-variable" -namespace { char dummy; }; +const h256 Account::c_contractConceptionCodeHash; diff --git a/libethereum/Account.h b/libethereum/Account.h new file mode 100644 index 000000000..ce7004083 --- /dev/null +++ b/libethereum/Account.h @@ -0,0 +1,190 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file Account.h + * @author Gav Wood + * @date 2014 + */ + +#pragma once + +#include +#include +#include +#include + +namespace dev +{ +namespace eth +{ + +/** + * Models the state of a single Ethereum account. + * Used to cache a portion of the full Ethereum state. State keeps a mapping of Address's to Accounts. + * + * Aside from storing the nonce and balance, the account may also be "dead" (where isAlive() returns false). + * This allows State to explicitly store the notion of a deleted account in it's cache. kill() can be used + * for this. + * + * For the account's storage, the class operates a cache. baseRoot() specifies the base state of the storage + * given as the Trie root to be looked up in the state database. Alterations beyond this base are specified + * in the overlay, stored in this class and retrieved with storageOverlay(). setStorage allows the overlay + * to be altered. + * + * The code handling explicitly supports a two-stage commit model needed for contract-creation. When creating + * a contract (running the initialisation code), the code of the account is considered empty. The attribute + * of emptiness can be retrieved with codeBearing(). After initialisation one must set the code accordingly; + * the code of the Account can be set with setCode(). To validate a setCode() call, this class records the + * state of being in contract-creation (and thus in a state where setCode may validly be called). It can be + * determined through isFreshCode(). + * + * The code can be retrieved through code(), and its hash through codeHash(). codeHash() is only valid when + * the account is not in the contract-creation phase (i.e. when isFreshCode() returns false). This class + * supports populating code on-demand from the state database. To determine if the code has been prepopulated + * call codeCacheValid(). To populate the code, look it up with codeHash() and populate with noteCode(). + * + * @todo: need to make a noteCodeCommitted(). + * + * The constructor allows you to create an one of a number of "types" of accounts. The default constructor + * makes a dead account (this is ignored by State when writing out the Trie). Another three allow a basic + * or contract account to be specified along with an initial balance. The fina two allow either a basic or + * a contract account to be created with arbitrary values. + */ +class Account +{ +public: + /// Type of account to create. + enum NewAccountType + { + /// Normal account. + NormalCreation, + /// Contract account - we place this object into the contract-creation state (and as such we + /// expect setCode(), but codeHash() won't work). + ContractConception + }; + + /// Construct a dead Account. + Account() {} + + /// Construct an alive Account, with given endowment, for either a normal (non-contract) account or for a + /// contract account in the + /// conception phase, where the code is not yet known. + Account(u256 _balance, NewAccountType _t): m_isAlive(true), m_balance(_balance), m_codeHash(_t == NormalCreation ? c_contractConceptionCodeHash : EmptySHA3) {} + /// Explicit constructor for wierd cases of construction of a normal account. + Account(u256 _nonce, u256 _balance): m_isAlive(true), m_nonce(_nonce), m_balance(_balance) {} + + /// Explicit constructor for wierd cases of construction or a contract account. + Account(u256 _nonce, u256 _balance, h256 _contractRoot, h256 _codeHash): m_isAlive(true), m_nonce(_nonce), m_balance(_balance), m_storageRoot(_contractRoot), m_codeHash(_codeHash) { assert(_contractRoot); } + + + /// Kill this account. Useful for the suicide opcode. Following this call, isAlive() returns false. + void kill() { m_isAlive = false; m_storageOverlay.clear(); m_codeHash = EmptySHA3; m_storageRoot = EmptyTrie; m_balance = 0; m_nonce = 0; } + + /// @returns true iff this object represents an account in the state. Returns false if this object + /// represents an account that should no longer exist in the trie (an account that never existed or was + /// suicided). + bool isAlive() const { return m_isAlive; } + + + /// @returns the balance of this account. Can be altered in place. + u256& balance() { return m_balance; } + + /// @returns the balance of this account. + u256 const& balance() const { return m_balance; } + + /// Increments the balance of this account by the given amount. It's a bigint, so can be negative. + void addBalance(bigint _i) { m_balance = (u256)((bigint)m_balance + _i); } + + /// @returns the nonce of the account. Can be altered in place. + u256& nonce() { return m_nonce; } + + /// @returns the nonce of the account. + u256 const& nonce() const { return m_nonce; } + + /// Increment the nonce of the account by one. + void incNonce() { m_nonce++; } + + + /// @returns the root of the trie (whose nodes are stored in the state db externally to this class) + /// which encodes the base-state of the account's storage (upon which the storage is overlaid). + h256 baseRoot() const { assert(m_storageRoot); return m_storageRoot; } + + /// @returns the storage overlay as a simple map. + std::map const& storageOverlay() const { return m_storageOverlay; } + + /// Set a key/value pair in the account's storage. This actually goes into the overlay, for committing + /// to the trie later. + void setStorage(u256 _p, u256 _v) { m_storageOverlay[_p] = _v; } + + /// @returns true if we are in the contract-conception state and setCode is valid to call. + bool isFreshCode() const { return m_codeHash == c_contractConceptionCodeHash; } + + /// @returns true if we are either in the contract-conception state or if the account's code is not + /// empty. + bool codeBearing() const { return m_codeHash != EmptySHA3; } + + /// @returns the hash of the account's code. Must only be called when isFreshCode() returns false. + h256 codeHash() const { assert(!isFreshCode()); return m_codeHash; } + + /// Sets the code of the account. Must only be called when isFreshCode() returns true. + void setCode(bytesConstRef _code) { assert(isFreshCode()); m_codeCache = _code.toBytes(); } + + /// @returns true if the account's code is available through code(). + bool codeCacheValid() const { return m_codeHash == EmptySHA3 || m_codeHash == c_contractConceptionCodeHash || m_codeCache.size(); } + + /// Specify to the object what the actual code is for the account. @a _code must have a SHA3 equal to + /// codeHash() and must only be called when isFreshCode() returns false. + void noteCode(bytesConstRef _code) { assert(sha3(_code) == m_codeHash); m_codeCache = _code.toBytes(); } + + /// @returns the account's code. Must only be called when codeCacheValid returns true. + bytes const& code() const { assert(codeCacheValid()); return m_codeCache; } + +private: + /// Is this account existant? If not, it represents a deleted account. + bool m_isAlive = false; + + /// Account's nonce. + u256 m_nonce = 0; + + /// Account's balance. + u256 m_balance = 0; + + /// The base storage root. Used with the state DB to give a base to the storage. m_storageOverlay is + /// overlaid on this and takes precedence for all values set. + h256 m_storageRoot = EmptyTrie; + + /** If c_contractConceptionCodeHash then we're in the limbo where we're running the initialisation code. + * We expect a setCode() at some point later. + * If EmptySHA3, then m_code, which should be empty, is valid. + * If anything else, then m_code is valid iff it's not empty, otherwise, State::ensureCached() needs to + * be called with the correct args. + */ + h256 m_codeHash = EmptySHA3; + + /// The map with is overlaid onto whatever storage is implied by the m_storageRoot in the trie. + std::map m_storageOverlay; + + /// The associated code for this account. The SHA3 of this should be equal to m_codeHash unless m_codeHash + /// equals c_contractConceptionCodeHash. + bytes m_codeCache; + + /// Value for m_codeHash when this account is having its code determined. + static const h256 c_contractConceptionCodeHash; +}; + +} +} + diff --git a/libethereum/AddressState.h b/libethereum/AddressState.h deleted file mode 100644 index 8b4505909..000000000 --- a/libethereum/AddressState.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - This file is part of cpp-ethereum. - - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . -*/ -/** @file AddressState.h - * @author Gav Wood - * @date 2014 - */ - -#pragma once - -#include -#include -#include -#include - -namespace dev -{ -namespace eth -{ - -// TODO: Document fully. - -class AddressState -{ -public: - enum NewAccountType { NormalCreation, ContractConception }; - - /// Construct a dead AddressState. - AddressState() {} - /// Construct an alive AddressState, with given endowment, for either a normal (non-contract) account or for a contract account in the - /// conception phase, where the code is not yet known. - AddressState(u256 _balance, NewAccountType _t): m_isAlive(true), m_balance(_balance), m_codeHash(_t == NormalCreation ? h256() : EmptySHA3) {} - /// Explicit constructor for wierd cases of construction of a normal account. - AddressState(u256 _nonce, u256 _balance): m_isAlive(true), m_nonce(_nonce), m_balance(_balance) {} - /// Explicit constructor for wierd cases of construction or a contract account. - AddressState(u256 _nonce, u256 _balance, h256 _contractRoot, h256 _codeHash): m_isAlive(true), m_nonce(_nonce), m_balance(_balance), m_storageRoot(_contractRoot), m_codeHash(_codeHash) {} - - void kill() { m_isAlive = false; m_storageOverlay.clear(); m_codeHash = EmptySHA3; m_storageRoot = EmptyTrie; m_balance = 0; m_nonce = 0; } - bool isAlive() const { return m_isAlive; } - - u256& balance() { return m_balance; } - u256 const& balance() const { return m_balance; } - void addBalance(bigint _i) { m_balance = (u256)((bigint)m_balance + _i); } - - u256& nonce() { return m_nonce; } - u256 const& nonce() const { return m_nonce; } - void incNonce() { m_nonce++; } - - h256 baseRoot() const { return m_storageRoot; } - std::map const& storage() const { return m_storageOverlay; } - void setStorage(u256 _p, u256 _v) { m_storageOverlay[_p] = _v; } - - bool isFreshCode() const { return !m_codeHash; } - bool codeBearing() const { return m_codeHash != EmptySHA3; } - bool codeCacheValid() const { return m_codeHash == EmptySHA3 || !m_codeHash || m_codeCache.size(); } - h256 codeHash() const { assert(m_codeHash); return m_codeHash; } - bytes const& code() const { assert(m_codeHash == EmptySHA3 || !m_codeHash || m_codeCache.size()); return m_codeCache; } - void setCode(bytesConstRef _code) { assert(!m_codeHash); m_codeCache = _code.toBytes(); } - void noteCode(bytesConstRef _code) { assert(sha3(_code) == m_codeHash); m_codeCache = _code.toBytes(); } - -private: - bool m_isAlive = false; - u256 m_nonce = 0; - u256 m_balance = 0; - - /// The base storage root. Used with the state DB to give a base to the storage. m_storageOverlay is overlaid on this and takes precedence for all values set. - h256 m_storageRoot = EmptyTrie; - - /// If 0 then we're in the limbo where we're running the initialisation code. We expect a setCode() at some point later. - /// If EmptySHA3, then m_code, which should be empty, is valid. - /// If anything else, then m_code is valid iff it's not empty, otherwise, State::ensureCached() needs to be called with the correct args. - h256 m_codeHash = EmptySHA3; - - // TODO: change to unordered_map. - std::map m_storageOverlay; - bytes m_codeCache; -}; - -} -} - diff --git a/libethereum/All.h b/libethereum/All.h index ba22640e7..11e0d55f3 100644 --- a/libethereum/All.h +++ b/libethereum/All.h @@ -1,6 +1,6 @@ #pragma once -#include "AddressState.h" +#include "Account.h" #include "BlockChain.h" #include "Client.h" #include "Defaults.h" diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 9672f722c..710f17214 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -52,9 +52,9 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, BlockChain const& _bc) return _out; } -std::map const& dev::eth::genesisState() +std::map const& dev::eth::genesisState() { - static std::map s_ret; + static std::map s_ret; if (s_ret.empty()) // Initialise. for (auto i: vector({ @@ -67,7 +67,7 @@ std::map const& dev::eth::genesisState() "6c386a4b26f73c802f34673f7248bb118f97424a", "e4157b34ea9615cfbde6b4fda419828124b70c78" })) - s_ret[Address(fromHex(i))] = AddressState(u256(1) << 200, AddressState::NormalCreation); + s_ret[Address(fromHex(i))] = Account(u256(1) << 200, Account::NormalCreation); return s_ret; } diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index 6c96082a5..30f5633c1 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -33,7 +33,7 @@ #include #include #include "BlockDetails.h" -#include "AddressState.h" +#include "Account.h" #include "BlockQueue.h" namespace ldb = leveldb; @@ -57,7 +57,7 @@ struct BlockChainChat: public LogChannel { static const char* name() { return "- struct BlockChainNote: public LogChannel { static const char* name() { return "=B="; } static const int verbosity = 4; }; // TODO: Move all this Genesis stuff into Genesis.h/.cpp -std::map const& genesisState(); +std::map const& genesisState(); ldb::Slice toSlice(h256 _h, unsigned _sub = 0); diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index b91871c40..a8df19be8 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -138,7 +138,7 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g m_newAddress = right160(sha3(rlpList(_sender, m_s.transactionsFrom(_sender) - 1))); // Set up new account... - m_s.m_cache[m_newAddress] = AddressState(0, m_s.balance(m_newAddress) + _endowment, EmptyTrie, h256()); + m_s.m_cache[m_newAddress] = Account(m_s.balance(m_newAddress) + _endowment, Account::ContractConception); // Execute _init. m_vm = VMFace::create(VMFace::JIT, _gas).release(); diff --git a/libethereum/ExtVM.h b/libethereum/ExtVM.h index 59b6eb2ab..cf80b2352 100644 --- a/libethereum/ExtVM.h +++ b/libethereum/ExtVM.h @@ -102,7 +102,7 @@ public: private: State& m_s; ///< A reference to the base state. - std::map m_origCache; ///< The cache of the address states (i.e. the externalities) as-was prior to the execution. + std::map m_origCache; ///< The cache of the address states (i.e. the externalities) as-was prior to the execution. Manifest* m_ms; }; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index f23f47398..b5a355b6b 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -226,7 +226,7 @@ Address State::nextActiveAddress(Address _a) const // TODO: repot struct CachedAddressState { - CachedAddressState(std::string const& _rlp, AddressState const* _s, OverlayDB const* _o): rS(_rlp), r(rS), s(_s), o(_o) {} + CachedAddressState(std::string const& _rlp, Account const* _s, OverlayDB const* _o): rS(_rlp), r(rS), s(_s), o(_o) {} bool exists() const { @@ -261,7 +261,7 @@ struct CachedAddressState ret[j.first] = RLP(j.second).toInt(); } if (s) - for (auto const& j: s->storage()) + for (auto const& j: s->storageOverlay()) if ((!ret.count(j.first) && j.second) || (ret.count(j.first) && ret.at(j.first) != j.second)) ret[j.first] = j.second; return ret; @@ -302,7 +302,7 @@ struct CachedAddressState std::string rS; RLP r; - AddressState const* s; + Account const* s; OverlayDB const* o; }; @@ -348,7 +348,7 @@ void State::ensureCached(Address _a, bool _requireCode, bool _forceCreate) const ensureCached(m_cache, _a, _requireCode, _forceCreate); } -void State::ensureCached(std::map& _cache, Address _a, bool _requireCode, bool _forceCreate) const +void State::ensureCached(std::map& _cache, Address _a, bool _requireCode, bool _forceCreate) const { auto it = _cache.find(_a); if (it == _cache.end()) @@ -358,11 +358,11 @@ void State::ensureCached(std::map& _cache, Address _a, bo if (stateBack.empty() && !_forceCreate) return; RLP state(stateBack); - AddressState s; + Account s; if (state.isNull()) - s = AddressState(0, AddressState::NormalCreation); + s = Account(0, Account::NormalCreation); else - s = AddressState(state[0].toInt(), state[1].toInt(), state[2].toHash(), state[3].toHash()); + s = Account(state[0].toInt(), state[1].toInt(), state[2].toHash(), state[3].toHash()); bool ok; tie(it, ok) = _cache.insert(make_pair(_a, s)); } @@ -967,7 +967,7 @@ void State::noteSending(Address _id) { cwarn << "Sending from non-existant account. How did it pay!?!"; // this is impossible. but we'll continue regardless... - m_cache[_id] = AddressState(1, 0); + m_cache[_id] = Account(1, 0); } else it->second.incNonce(); @@ -978,7 +978,7 @@ void State::addBalance(Address _id, u256 _amount) ensureCached(_id, false, false); auto it = m_cache.find(_id); if (it == m_cache.end()) - m_cache[_id] = AddressState(_amount, AddressState::NormalCreation); + m_cache[_id] = Account(_amount, Account::NormalCreation); else it->second.addBalance(_amount); } @@ -1013,8 +1013,8 @@ u256 State::storage(Address _id, u256 _memory) const return 0; // See if it's in the account's storage cache. - auto mit = it->second.storage().find(_memory); - if (mit != it->second.storage().end()) + auto mit = it->second.storageOverlay().find(_memory); + if (mit != it->second.storageOverlay().end()) return mit->second; // Not in the storage cache - go to the DB. @@ -1042,7 +1042,7 @@ map State::storage(Address _id) const } // Then merge cached storage over the top. - for (auto const& i: it->second.storage()) + for (auto const& i: it->second.storageOverlay()) if (i.second) ret[i.first] = i.second; else @@ -1059,7 +1059,7 @@ h256 State::storageRoot(Address _id) const RLP r(s); return r[2].toHash(); } - return h256(); + return EmptyTrie; } bytes const& State::code(Address _contract) const @@ -1270,7 +1270,7 @@ h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, Address newAddress = right160(sha3(rlpList(_sender, transactionsFrom(_sender) - 1))); // Set up new account... - m_cache[newAddress] = AddressState(balance(newAddress) + _endowment, AddressState::ContractConception); + m_cache[newAddress] = Account(balance(newAddress) + _endowment, Account::ContractConception); // Execute init code. auto vmObj = VMFace::create(getVMKind(), *_gas); @@ -1370,7 +1370,7 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, State const& _s) for (auto i: d) { auto it = _s.m_cache.find(i); - AddressState* cache = it != _s.m_cache.end() ? &it->second : nullptr; + Account* cache = it != _s.m_cache.end() ? &it->second : nullptr; string rlpString = dtr.count(i) ? trie.at(i) : ""; RLP r(rlpString); assert(cache || r); @@ -1398,7 +1398,7 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, State const& _s) mem[j.first] = RLP(j.second).toInt(), back.insert(j.first); } if (cache) - for (auto const& j: cache->storage()) + for (auto const& j: cache->storageOverlay()) { if ((!mem.count(j.first) && j.second) || (mem.count(j.first) && mem.at(j.first) != j.second)) mem[j.first] = j.second, delta.insert(j.first); diff --git a/libethereum/State.h b/libethereum/State.h index b7f6126b2..fece4601a 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -34,7 +34,7 @@ #include #include #include "TransactionQueue.h" -#include "AddressState.h" +#include "Account.h" #include "Transaction.h" #include "Executive.h" #include "AccountDiff.h" @@ -130,8 +130,10 @@ public: /// @returns the set containing all addresses currently in use in Ethereum. std::map addresses() const; + /// @returns the address b such that b > @a _a . Address nextActiveAddress(Address _a) const; + /// 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. @@ -306,7 +308,7 @@ private: void ensureCached(Address _a, bool _requireCode, bool _forceCreate) const; /// Retrieve all information about a given address into a cache. - void ensureCached(std::map& _cache, Address _a, bool _requireCode, bool _forceCreate) const; + void ensureCached(std::map& _cache, Address _a, bool _requireCode, bool _forceCreate) const; /// Commit all changes waiting in the address cache to the DB. void commit(); @@ -347,18 +349,18 @@ private: std::set m_transactionSet; ///< The set of transaction hashes that we've included in the state. OverlayDB m_lastTx; - mutable std::map m_cache; ///< Our address cache. This stores the states of each address that has (or at least might have) been changed. + mutable std::map m_cache; ///< Our address cache. This stores the states of each address that has (or at least might have) been changed. BlockInfo m_previousBlock; ///< The previous block's information. BlockInfo m_currentBlock; ///< The current block's information. bytes m_currentBytes; ///< The current block. - bytes m_currentTxs; - bytes m_currentUncles; + bytes m_currentTxs; ///< The RLP-encoded block of transactions. + bytes m_currentUncles; ///< The RLP-encoded block of uncles. Address m_ourAddress; ///< Our address (i.e. the address to which fees go). - ProofOfWork m_pow; + ProofOfWork m_pow; ///< The PoW mining class. u256 m_blockReward; @@ -374,7 +376,7 @@ private: std::ostream& operator<<(std::ostream& _out, State const& _s); template -void commit(std::map const& _cache, DB& _db, TrieDB& _state) +void commit(std::map const& _cache, DB& _db, TrieDB& _state) { for (auto const& i: _cache) if (!i.second.isAlive()) @@ -384,7 +386,7 @@ void commit(std::map const& _cache, DB& _db, TrieDB const& _cache, DB& _db, TrieDB storageDB(&_db, i.second.baseRoot()); - for (auto const& j: i.second.storage()) + for (auto const& j: i.second.storageOverlay()) if (j.second) storageDB.insert(j.first, rlp(j.second)); else diff --git a/test/vm.cpp b/test/vm.cpp index 102de7c4f..26b9abad3 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -471,7 +471,7 @@ h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _end } // Set up new account... - m_cache[_newAddress] = AddressState(0, balance(_newAddress) + _endowment, h256(), h256()); + m_cache[_newAddress] = Account(0, balance(_newAddress) + _endowment, h256(), h256()); // Execute init code. auto vmObj = VMFace::create(getVMKind(), *_gas);