diff --git a/exp/main.cpp b/exp/main.cpp index 6192ab96c..aee6e6efd 100644 --- a/exp/main.cpp +++ b/exp/main.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include using namespace std; @@ -79,11 +80,19 @@ int main() KeyPair u = KeyPair::create(); KeyPair cb = KeyPair::create(); OverlayDB db; - State s(cb.address(), db); + State s(cb.address(), db, BaseState::Empty); cnote << s.rootHash(); - s.addBalance(u.address(), 1000 * ether); + s.addBalance(u.address(), 1 * ether); + Address c = s.newContract(1000 * ether, compileLLL("(suicide (caller))")); s.commit(); cnote << s.rootHash(); + State before = s; + cnote << s; + Transaction t(0, 10000, 10000, c, bytes(), 0, u.secret()); + cnote << s.balance(c); + s.execute(t.rlp()); + cnote << before.diff(s); + cnote << s; } #endif diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp index bf973b565..6c08bb346 100644 --- a/libethcore/BlockInfo.cpp +++ b/libethcore/BlockInfo.cpp @@ -40,6 +40,25 @@ BlockInfo::BlockInfo(bytesConstRef _block, bool _checkNonce) populate(_block, _checkNonce); } +void BlockInfo::setEmpty() +{ + parentHash = h256(); + sha3Uncles = EmptyListSHA3; + coinbaseAddress = Address(); + stateRoot = EmptyTrie; + transactionsRoot = EmptyTrie; + receiptsRoot = EmptyTrie; + logBloom = LogBloom(); + difficulty = 0; + number = 0; + gasLimit = 0; + gasUsed = 0; + timestamp = 0; + extraData.clear(); + nonce = h256(); + hash = headerHash(WithNonce); +} + BlockInfo BlockInfo::fromHeader(bytesConstRef _block) { BlockInfo ret; diff --git a/libethcore/BlockInfo.h b/libethcore/BlockInfo.h index 18dd53ff3..99efc6a17 100644 --- a/libethcore/BlockInfo.h +++ b/libethcore/BlockInfo.h @@ -108,6 +108,8 @@ public: } bool operator!=(BlockInfo const& _cmp) const { return !operator==(_cmp); } + void setEmpty(); + void populateFromHeader(RLP const& _header, bool _checkNonce = true); void populate(bytesConstRef _block, bool _checkNonce = true); void populate(bytes const& _block, bool _checkNonce = true) { populate(&_block, _checkNonce); } diff --git a/libethereum/ExtVM.h b/libethereum/ExtVM.h index 9699a68ad..cfe40874f 100644 --- a/libethereum/ExtVM.h +++ b/libethereum/ExtVM.h @@ -73,6 +73,7 @@ public: virtual void suicide(Address _a) override final { m_s.addBalance(_a, m_s.balance(myAddress)); + m_s.subBalance(myAddress, m_s.balance(myAddress)); ExtVMFace::suicide(_a); } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 64210f20a..fd00761e1 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -63,7 +63,7 @@ OverlayDB State::openDB(std::string _path, bool _killExisting) return OverlayDB(db); } -State::State(Address _coinbaseAddress, OverlayDB const& _db): +State::State(Address _coinbaseAddress, OverlayDB const& _db, BaseState _bs): m_db(_db), m_state(&m_db), m_ourAddress(_coinbaseAddress), @@ -74,12 +74,19 @@ State::State(Address _coinbaseAddress, OverlayDB const& _db): paranoia("beginning of normal construction.", true); - dev::eth::commit(genesisState(), m_db, m_state); - m_db.commit(); + if (_bs == BaseState::Genesis) + { + dev::eth::commit(genesisState(), m_db, m_state); + m_db.commit(); - paranoia("after DB commit of normal construction.", true); + paranoia("after DB commit of normal construction.", true); + m_previousBlock = BlockChain::genesis(); + } + else + { + m_previousBlock.setEmpty(); + } - m_previousBlock = BlockChain::genesis(); resetCurrent(); assert(m_state.root() == m_previousBlock.stateRoot); @@ -857,6 +864,23 @@ void State::subBalance(Address _id, bigint _amount) it->second.addBalance(-_amount); } +Address State::newContract(u256 _balance, bytes const& _code) +{ + auto h = sha3(_code); + m_db.insert(h, &_code); + while (true) + { + Address ret = Address::random(); + ensureCached(ret, false, false); + auto it = m_cache.find(ret); + if (it == m_cache.end()) + { + m_cache[ret] = Account(0, _balance, EmptyTrie, h); + return ret; + } + } +} + u256 State::transactionsFrom(Address _id) const { ensureCached(_id, false, false); @@ -993,8 +1017,11 @@ u256 State::execute(bytesConstRef _rlp, bytes* o_output, bool _commit) ctrace << "Executing" << e.t() << "on" << h; ctrace << toHex(e.t().rlp()); #endif - +#if ETH_TRACE e.go(e.simpleTrace()); +#else + e.go(); +#endif e.finalize(); #if ETH_PARANOIA diff --git a/libethereum/State.h b/libethereum/State.h index b071e7674..763a67451 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -53,6 +53,8 @@ struct StateTrace: public LogChannel { static const char* name() { return "=S="; struct StateDetail: public LogChannel { static const char* name() { return "/S/"; } static const int verbosity = 14; }; struct StateSafeExceptions: public LogChannel { static const char* name() { return "(S)"; } static const int verbosity = 21; }; +enum class BaseState { Empty, Genesis }; + /** * @brief Model of the current state of the ledger. * Maintains current ledger (m_current) as a fast hash-map. This is hashed only when required (i.e. to create or verify a block). @@ -66,7 +68,7 @@ class State public: /// Construct state object. - State(Address _coinbaseAddress = Address(), OverlayDB const& _db = OverlayDB()); + State(Address _coinbaseAddress = Address(), OverlayDB const& _db = OverlayDB(), BaseState _bs = BaseState::Genesis); /// Construct state object from arbitrary point in blockchain. State(OverlayDB const& _db, BlockChain const& _bc, h256 _hash); @@ -183,6 +185,9 @@ public: /// Set the value of a storage position of an account. void setStorage(Address _contract, u256 _location, u256 _value) { m_cache[_contract].setStorage(_location, _value); } + /// Create a new contract. + Address newContract(u256 _balance, bytes const& _code); + /// Get the storage of an account. /// @note This is expensive. Don't use it unless you need to. /// @returns std::map if no account exists at that address.