diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 4da7026fe..2853536b9 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -974,7 +974,7 @@ void Main::refreshBlockChain() auto b = bc.block(h); for (auto const& i: RLP(b)[1]) { - Transaction t(i[0].data()); + Transaction t(i.data()); if (bm || transactionMatch(filter, t)) { QString s = t.receiveAddress ? @@ -1235,13 +1235,13 @@ void Main::on_blocks_currentItemChanged() else s << "
Pre: Nothing is before the Gensesis"; for (auto const& i: block[1]) - s << "
" << sha3(i[0].data()).abridged() << ": " << i[1].toHash() << " [" << i[2].toInt() << " used]"; + s << "
" << sha3(i.data()).abridged();// << ": " << i[1].toHash() << " [" << i[2].toInt() << " used]"; s << "
Post: " << info.stateRoot << ""; } else { unsigned txi = item->data(Qt::UserRole + 1).toInt(); - Transaction tx(block[1][txi][0].data()); + Transaction tx(block[1][txi].data()); auto ss = tx.safeSender(); h256 th = sha3(rlpList(ss, tx.nonce)); s << "

" << th << "

"; diff --git a/evmcc/test/arith/arith_bnot.evm b/evmcc/test/arith/arith_bnot.evm new file mode 100644 index 000000000..4cfaf8f55 --- /dev/null +++ b/evmcc/test/arith/arith_bnot.evm @@ -0,0 +1 @@ +6201e2406000546000530960005460206000f2 diff --git a/evmcc/test/arith/arith_bnot.lll b/evmcc/test/arith/arith_bnot.lll new file mode 100644 index 000000000..a83b05a9a --- /dev/null +++ b/evmcc/test/arith/arith_bnot.lll @@ -0,0 +1,14 @@ + +(asm +123456 +0 +MSTORE +0 +MLOAD +BNOT +0 +MSTORE +32 +0 +RETURN +) \ No newline at end of file diff --git a/evmcc/test/ext/store_delete.evm b/evmcc/test/ext/store_delete.evm new file mode 100644 index 000000000..d6acae03d --- /dev/null +++ b/evmcc/test/ext/store_delete.evm @@ -0,0 +1 @@ +6104d26063576000606357 diff --git a/evmcc/test/ext/store_delete.lll b/evmcc/test/ext/store_delete.lll new file mode 100644 index 000000000..3d8f0f23a --- /dev/null +++ b/evmcc/test/ext/store_delete.lll @@ -0,0 +1,9 @@ + +(asm +1234 +99 +SSTORE +0 +99 +SSTORE +) \ No newline at end of file diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index a32125354..9d2ae55d7 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -27,7 +27,7 @@ using namespace dev; namespace dev { -char const* Version = "0.7.7"; +char const* Version = "0.7.8"; } diff --git a/libethcore/CommonEth.cpp b/libethcore/CommonEth.cpp index 44ebe19c5..e7223d896 100644 --- a/libethcore/CommonEth.cpp +++ b/libethcore/CommonEth.cpp @@ -34,7 +34,7 @@ namespace dev namespace eth { -const unsigned c_protocolVersion = 37; +const unsigned c_protocolVersion = 38; const unsigned c_databaseVersion = 3; static const vector> g_units = diff --git a/libethereum/AddressState.h b/libethereum/AddressState.h index 668e9225f..8b4505909 100644 --- a/libethereum/AddressState.h +++ b/libethereum/AddressState.h @@ -23,6 +23,7 @@ #include #include +#include #include namespace dev @@ -35,10 +36,19 @@ namespace eth class AddressState { public: - AddressState(): m_isAlive(false), m_nonce(0), m_balance(0) {} + 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 = h256(); m_balance = 0; m_nonce = 0; } + 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; } @@ -62,17 +72,17 @@ public: void noteCode(bytesConstRef _code) { assert(sha3(_code) == m_codeHash); m_codeCache = _code.toBytes(); } private: - bool m_isAlive; - u256 m_nonce; - u256 m_balance; + 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; + 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; + h256 m_codeHash = EmptySHA3; // TODO: change to unordered_map. std::map m_storageOverlay; diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index a9bdbf247..9672f722c 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -67,7 +67,7 @@ std::map const& dev::eth::genesisState() "6c386a4b26f73c802f34673f7248bb118f97424a", "e4157b34ea9615cfbde6b4fda419828124b70c78" })) - s_ret[Address(fromHex(i))] = AddressState(0, u256(1) << 200, h256(), EmptySHA3); + s_ret[Address(fromHex(i))] = AddressState(u256(1) << 200, AddressState::NormalCreation); return s_ret; } diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 404cf5596..b91871c40 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, h256(), h256()); + m_s.m_cache[m_newAddress] = AddressState(0, m_s.balance(m_newAddress) + _endowment, EmptyTrie, h256()); // Execute _init. m_vm = VMFace::create(VMFace::JIT, _gas).release(); diff --git a/libethereum/State.cpp b/libethereum/State.cpp index f07f2f093..f23f47398 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -326,6 +326,9 @@ StateDiff State::diff(State const& _c) const for (auto i: _c.m_cache) ads.insert(i.first); + cnote << *this; + cnote << _c; + for (auto i: ads) { auto it = m_cache.find(i); @@ -357,7 +360,7 @@ void State::ensureCached(std::map& _cache, Address _a, bo RLP state(stateBack); AddressState s; if (state.isNull()) - s = AddressState(0, 0, EmptyTrie, EmptySHA3); + s = AddressState(0, AddressState::NormalCreation); else s = AddressState(state[0].toInt(), state[1].toInt(), state[2].toHash(), state[3].toHash()); bool ok; @@ -624,8 +627,6 @@ u256 State::enact(bytesConstRef _block, BlockChain const* _bc, bool _checkNonce) RLPStream k; k << i; - RLPStream txrlp; - m_transactions[i].streamRLP(txrlp); transactionsTrie.insert(&k.out(), tr.data()); // cnote << m_state.root() << m_state; @@ -962,8 +963,12 @@ void State::noteSending(Address _id) { ensureCached(_id, false, false); auto it = m_cache.find(_id); - if (it == m_cache.end()) - m_cache[_id] = AddressState(1, 0, h256(), EmptySHA3); + if (asserts(it != m_cache.end())) + { + cwarn << "Sending from non-existant account. How did it pay!?!"; + // this is impossible. but we'll continue regardless... + m_cache[_id] = AddressState(1, 0); + } else it->second.incNonce(); } @@ -973,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(0, _amount, h256(), EmptySHA3); + m_cache[_id] = AddressState(_amount, AddressState::NormalCreation); else it->second.addBalance(_amount); } @@ -1086,7 +1091,7 @@ bool State::isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const RLP r(i.second); TrieDB storageDB(const_cast(&m_db), r[2].toHash()); // promise not to alter OverlayDB. for (auto const& j: storageDB) { (void)j; } - if (!e && r[3].toHash() && m_db.lookup(r[3].toHash()).empty()) + if (!e && r[3].toHash() != EmptySHA3 && m_db.lookup(r[3].toHash()).empty()) return false; } } @@ -1265,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(0, balance(newAddress) + _endowment, h256(), h256()); + m_cache[newAddress] = AddressState(balance(newAddress) + _endowment, AddressState::ContractConception); // Execute init code. auto vmObj = VMFace::create(getVMKind(), *_gas); @@ -1380,7 +1385,6 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, State const& _s) stringstream contout; - /// For POC6, 3rd value of account is code and will be empty if code is not present. if ((cache && cache->codeBearing()) || (!cache && r && !r[3].isEmpty())) { std::map mem; diff --git a/libethereum/State.h b/libethereum/State.h index 261d96a49..b7f6126b2 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -385,7 +385,10 @@ void commit(std::map const& _cache, DB& _db, TrieDB storageDB(&_db, i.second.baseRoot()); @@ -394,7 +397,8 @@ void commit(std::map const& _cache, DB& _db, TrieDB dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con m_stack.pop_back(); break; case Instruction::SIGNEXTEND: - { - unsigned k = m_stack.back().convert_to(); + if (m_stack.back() < 31) + { + unsigned const testBit(m_stack.back() * 8 + 7); + u256& number = m_stack[m_stack.size() - 2]; + u256 mask = ((u256(1) << testBit) - 1); + if (boost::multiprecision::bit_test(number, testBit)) + number |= ~mask; + else + number &= mask; + } m_stack.pop_back(); - auto& b = m_stack.back(); - if (k <= 31) - if ((b >> (k * 8)) & 0x80) - for (unsigned i = 31; i > k; --i) - b |= (u256(0xff) << i); break; - } case Instruction::SHA3: { unsigned inOff = (unsigned)m_stack.back(); diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index ea74d1051..d7a87b508 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -374,10 +374,9 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::BNOT: { - auto top = stack.pop(); - auto allones = llvm::ConstantInt::get(Type::i256, llvm::APInt::getAllOnesValue(256)); - auto res = m_builder.CreateXor(top, allones); - stack.push(res); + auto value = stack.pop(); + auto ret = m_builder.CreateXor(value, llvm::APInt(256, -1, true), "bnot"); + stack.push(ret); break; } @@ -507,28 +506,29 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::SIGNEXTEND: { - auto k = stack.pop(); - auto b = stack.pop(); - auto k32 = m_builder.CreateTrunc(k, m_builder.getIntNTy(5), "k_32"); - auto k32ext = m_builder.CreateZExt(k32, Type::i256); - auto k32x8 = m_builder.CreateMul(k32ext, Constant::get(8), "kx8"); + auto idx = stack.pop(); + auto word = stack.pop(); + + auto k32_ = m_builder.CreateTrunc(idx, m_builder.getIntNTy(5), "k_32"); + auto k32 = m_builder.CreateZExt(k32_, Type::i256); + auto k32x8 = m_builder.CreateMul(k32, Constant::get(8), "kx8"); // test for b >> (k * 8 + 7) - auto val = m_builder.CreateAdd(k32x8, llvm::ConstantInt::get(Type::i256, 7)); - auto tmp = m_builder.CreateAShr(b, val); - auto bitset = m_builder.CreateTrunc(tmp, m_builder.getInt1Ty()); + auto bitpos = m_builder.CreateAdd(k32x8, Constant::get(7), "bitpos"); + auto bitval = m_builder.CreateLShr(word, bitpos, "bitval"); + auto bittest = m_builder.CreateTrunc(bitval, m_builder.getInt1Ty(), "bittest"); - // shift left by (31 - k) * 8 = (248 - k*8), then do arithmetic shr by the same amount. - auto shiftSize = m_builder.CreateSub(llvm::ConstantInt::get(Type::i256, 31 * 8), k32x8); - auto bshl = m_builder.CreateShl(b, shiftSize); - auto bshr = m_builder.CreateAShr(bshl, shiftSize); + auto mask_ = m_builder.CreateShl(Constant::get(1), bitpos); + auto mask = m_builder.CreateSub(mask_, Constant::get(1), "mask"); - // bshr is our final value if 0 <= k <= 30 and bitset is true, - // otherwise we push back b unchanged - auto kInRange = m_builder.CreateICmpULE(k, llvm::ConstantInt::get(Type::i256, 30)); - auto cond = m_builder.CreateAnd(kInRange, bitset); + auto negmask = m_builder.CreateXor(mask, llvm::ConstantInt::getAllOnesValue(Type::i256), "negmask"); + auto val1 = m_builder.CreateOr(word, negmask); + auto val0 = m_builder.CreateAnd(word, mask); - auto result = m_builder.CreateSelect(cond, bshr, b); + auto kInRange = m_builder.CreateICmpULE(idx, llvm::ConstantInt::get(Type::i256, 30)); + auto result = m_builder.CreateSelect(kInRange, + m_builder.CreateSelect(bittest, val1, val0), + word); stack.push(result); break; diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 9484d9b26..0fe795a1f 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -6,6 +6,7 @@ #include #include +#include #include "Runtime.h" #include "Type.h" @@ -24,12 +25,6 @@ inline u256 fromAddress(Address _a) return (u160)_a; } -struct ExtData -{ - const byte* calldata; - const byte* code; -}; - Ext::Ext(RuntimeManager& _runtimeManager): RuntimeHelper(_runtimeManager), m_data() @@ -184,7 +179,12 @@ extern "C" { auto index = llvm2eth(*_index); auto value = llvm2eth(*_value); - _rt->getExt().setStore(index, value); // Interface uses native endianness + auto& ext = _rt->getExt(); + + if (value == 0 && ext.store(index) != 0) // If delete + ext.sub.refunds += c_sstoreRefundGas; // Increase refund counter + + ext.setStore(index, value); // Interface uses native endianness } EXPORT void ext_calldataload(Runtime* _rt, i256* _index, i256* _value) diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index 82b587dd8..5f6f81e72 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -28,11 +28,9 @@ uint64_t getStepCost(Instruction inst) // TODO: Add this function to FeeSructure { case Instruction::STOP: case Instruction::SUICIDE: + case Instruction::SSTORE: // Handle cost of SSTORE separately in GasMeter::countSStore() return 0; - case Instruction::SSTORE: - return static_cast(c_sstoreResetGas); // FIXME: Check store gas - case Instruction::SLOAD: return static_cast(c_sloadGas); @@ -118,8 +116,7 @@ void GasMeter::count(Instruction _inst) m_checkCall = m_builder.CreateCall(m_gasCheckFunc, llvm::UndefValue::get(Type::i256)); } - if (_inst != Instruction::SSTORE) // Handle cost of SSTORE separately in countSStore() - m_blockCost += getStepCost(_inst); + m_blockCost += getStepCost(_inst); if (isCostBlockEnd(_inst)) commitCostBlock(); @@ -129,20 +126,15 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu { assert(!m_checkCall); // Everything should've been commited before - static const auto sstoreCost = static_cast(c_sstoreResetGas); // FIXME: Check store gas - - // [ADD] if oldValue == 0 and newValue != 0 => 2*cost - // [DEL] if oldValue != 0 and newValue == 0 => 0 - auto oldValue = _ext.store(_index); auto oldValueIsZero = m_builder.CreateICmpEQ(oldValue, Constant::get(0), "oldValueIsZero"); auto newValueIsZero = m_builder.CreateICmpEQ(_newValue, Constant::get(0), "newValueIsZero"); auto oldValueIsntZero = m_builder.CreateICmpNE(oldValue, Constant::get(0), "oldValueIsntZero"); auto newValueIsntZero = m_builder.CreateICmpNE(_newValue, Constant::get(0), "newValueIsntZero"); - auto isAdd = m_builder.CreateAnd(oldValueIsZero, newValueIsntZero, "isAdd"); - auto isDel = m_builder.CreateAnd(oldValueIsntZero, newValueIsZero, "isDel"); - auto cost = m_builder.CreateSelect(isAdd, Constant::get(2 * sstoreCost), Constant::get(sstoreCost), "cost"); - cost = m_builder.CreateSelect(isDel, Constant::get(0), cost, "cost"); + auto isInsert = m_builder.CreateAnd(oldValueIsZero, newValueIsntZero, "isInsert"); + auto isDelete = m_builder.CreateAnd(oldValueIsntZero, newValueIsZero, "isDelete"); + auto cost = m_builder.CreateSelect(isInsert, Constant::get(c_sstoreSetGas), Constant::get(c_sstoreResetGas), "cost"); + cost = m_builder.CreateSelect(isDelete, Constant::get(0), cost, "cost"); createCall(m_gasCheckFunc, cost); } diff --git a/libevmjit/Type.cpp b/libevmjit/Type.cpp index 5021473ff..447da6a4b 100644 --- a/libevmjit/Type.cpp +++ b/libevmjit/Type.cpp @@ -41,6 +41,16 @@ llvm::ConstantInt* Constant::get(uint64_t _n) return llvm::ConstantInt::get(Type::i256, _n); } +llvm::ConstantInt* Constant::get(u256 _n) +{ + auto& backend = _n.backend(); + auto words = reinterpret_cast(backend.limbs()); + auto nWords = backend.limb_bits == 64 ? backend.size() : (backend.size() + 1) / 2; + llvm::APInt n(256, nWords, words); + assert(n.toString(10, false) == _n.str()); + return static_cast(llvm::ConstantInt::get(Type::i256, n)); +} + llvm::ConstantInt* Constant::get(ReturnCode _returnCode) { return llvm::ConstantInt::get(Type::MainReturn, static_cast(_returnCode)); diff --git a/libevmjit/Type.h b/libevmjit/Type.h index b432f0813..c80e46777 100644 --- a/libevmjit/Type.h +++ b/libevmjit/Type.h @@ -3,6 +3,7 @@ #include #include +#include namespace dev { @@ -51,6 +52,7 @@ struct Constant { /// Returns word-size constant static llvm::ConstantInt* get(uint64_t _n); + static llvm::ConstantInt* get(u256 _n); static llvm::ConstantInt* get(ReturnCode _returnCode); }; diff --git a/liblll/Assembly.cpp b/liblll/Assembly.cpp index 5b10138d1..7ad84682f 100644 --- a/liblll/Assembly.cpp +++ b/liblll/Assembly.cpp @@ -54,6 +54,7 @@ unsigned Assembly::bytesRequired() const switch (i.m_type) { case Operation: + case Tag: // 1 byte for the JUMPDEST ret++; break; case PushString: @@ -69,7 +70,6 @@ unsigned Assembly::bytesRequired() const case PushData: case PushSub: ret += 1 + br; - case Tag:; default:; } if (dev::bytesRequired(ret) <= br) diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index 1ea413ee9..44f0a54ad 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -266,9 +266,11 @@ ASTPointer Parser::parseStatement() // starting from here, all statements must be terminated by a semicolon case Token::CONTINUE: statement = ASTNodeFactory(*this).createNode(); + m_scanner->next(); break; case Token::BREAK: statement = ASTNodeFactory(*this).createNode(); + m_scanner->next(); break; case Token::RETURN: { diff --git a/test/solidityParser.cpp b/test/solidityParser.cpp index 025cd74d1..701a6e76c 100644 --- a/test/solidityParser.cpp +++ b/test/solidityParser.cpp @@ -185,7 +185,7 @@ BOOST_AUTO_TEST_CASE(while_loop) { char const* text = "contract test {\n" " function fun(uint256 a) {\n" - " uint256 x = (1 + 4).member(++67) || true;\n" + " while (true) { uint256 x = 1; break; continue; } x = 9;\n" " }\n" "}\n"; BOOST_CHECK_NO_THROW(parseText(text)); diff --git a/test/vm.cpp b/test/vm.cpp index 56fe104ee..102de7c4f 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -130,7 +130,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, m_ms.internal.resize(m_ms.internal.size() + 1); - auto ret = m_s.call(_receiveAddress,_codeAddressOverride ? _codeAddressOverride : _receiveAddress, _myAddressOverride ? _myAddressOverride : myAddress, _value, gasPrice, _data, _gas, _out, origin, &sub, &(m_ms.internal.back()), simpleTrace(), 1); + auto ret = m_s.call(_receiveAddress,_codeAddressOverride ? _codeAddressOverride : _receiveAddress, _myAddressOverride ? _myAddressOverride : myAddress, _value, gasPrice, _data, _gas, _out, origin, &sub, &(m_ms.internal.back()), Executive::simpleTrace(), 1); if (!m_ms.internal.back().from) m_ms.internal.pop_back(); @@ -421,6 +421,39 @@ void FakeExtVM::importCallCreates(mArray& _callcreates) } } +eth::OnOpFunc FakeExtVM::simpleTrace() +{ + return [](uint64_t steps, eth::Instruction inst, bigint newMemSize, bigint gasCost, void* voidVM, void const* voidExt) + { + FakeExtVM const& ext = *(FakeExtVM const*)voidExt; + eth::VM& vm = *(eth::VM*)voidVM; + + std::ostringstream o; + o << std::endl << " STACK" << std::endl; + for (auto i: vm.stack()) + o << (h256)i << std::endl; + o << " MEMORY" << std::endl << memDump(vm.memory()); + o << " STORAGE" << std::endl; + + for (auto const& i: ext.state().storage(ext.myAddress)) + o << std::showbase << std::hex << i.first << ": " << i.second << std::endl; + + for (auto const& i: std::get<2>(ext.addresses.find(ext.myAddress)->second)) + o << std::showbase << std::hex << i.first << ": " << i.second << std::endl; + + dev::LogOutputStream(true) << o.str(); + dev::LogOutputStream(false) << " | " << std::dec << ext.depth << " | " << ext.myAddress << " | #" << steps << " | " << std::hex << std::setw(4) << std::setfill('0') << vm.curPC() << " : " << instructionInfo(inst).name << " | " << std::dec << vm.gas() << " | -" << std::dec << gasCost << " | " << newMemSize << "x32" << " ]"; + + if (eth::VMTraceChannel::verbosity <= g_logVerbosity) + { + std::ofstream f; + f.open("./vmtrace.log", std::ofstream::app); + f << o.str(); + f << " | " << std::dec << ext.depth << " | " << ext.myAddress << " | #" << steps << " | " << std::hex << std::setw(4) << std::setfill('0') << vm.curPC() << " : " << instructionInfo(inst).name << " | " << std::dec << vm.gas() << " | -" << std::dec << gasCost << " | " << newMemSize << "x32"; + } + }; +} + // THIS IS BROKEN AND NEEDS TO BE REMOVED. h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _origin, SubState* o_sub, Manifest* o_ms, OnOpFunc const& _onOp, unsigned _level) { @@ -520,7 +553,7 @@ void doTests(json_spirit::mValue& v, bool _fillin) fev.thisTxCode = get<3>(fev.addresses.at(fev.myAddress)); fev.code = &fev.thisTxCode; } - + auto vm = VMFace::create(fev.getVMKind(), fev.gas); bytes output; auto outOfGas = false; @@ -528,7 +561,7 @@ void doTests(json_spirit::mValue& v, bool _fillin) auto startTime = std::chrono::high_resolution_clock::now(); try { - output = vm->go(fev, fev.simpleTrace()).toVector(); + output = vm->go(fev, fev.simpleTrace()).toVector(); } catch (OutOfGas const&) { diff --git a/test/vm.h b/test/vm.h index e51fe3f89..b3397b2c6 100644 --- a/test/vm.h +++ b/test/vm.h @@ -83,9 +83,7 @@ public: void setVMKind(eth::VMFace::Kind _kind) { m_s.setVMKind(_kind); } eth::VMFace::Kind getVMKind() const { return m_s.getVMKind(); } - template eth::OnOpFunc simpleTrace(); - FakeState state() const { return m_s; } std::map, bytes>> addresses; @@ -99,32 +97,5 @@ private: eth::Manifest m_ms; }; -template -eth::OnOpFunc FakeExtVM::simpleTrace() -{ - return [](uint64_t steps, eth::Instruction inst, bigint newMemSize, bigint gasCost, void* voidVM, void const* voidExt) - { - ExtVMType const& ext = *(ExtVMType const*)voidExt; - eth::VM& vm = *(eth::VM*)voidVM; - - std::ostringstream o; - o << std::endl << " STACK" << std::endl; - for (auto i: vm.stack()) - o << (h256)i << std::endl; - o << " MEMORY" << std::endl << memDump(vm.memory()); - o << " STORAGE" << std::endl; - for (auto const& i: ext.state().storage(ext.myAddress)) - o << std::showbase << std::hex << i.first << ": " << i.second << std::endl; - dev::LogOutputStream(true) << o.str(); - dev::LogOutputStream(false) << " | " << std::dec << ext.depth << " | " << ext.myAddress << " | #" << steps << " | " << std::hex << std::setw(4) << std::setfill('0') << vm.curPC() << " : " << instructionInfo(inst).name << " | " << std::dec << vm.gas() << " | -" << std::dec << gasCost << " | " << newMemSize << "x32" << " ]"; - if (eth::VMTraceChannel::verbosity <= g_logVerbosity) - { - std::ofstream f; - f.open("./vmtrace.log", std::ofstream::app); - f << o.str(); - f << " | " << std::dec << ext.depth << " | " << ext.myAddress << " | #" << steps << " | " << std::hex << std::setw(4) << std::setfill('0') << vm.curPC() << " : " << instructionInfo(inst).name << " | " << std::dec << vm.gas() << " | -" << std::dec << gasCost << " | " << newMemSize << "x32"; - } - }; -} } } // Namespace Close