Browse Source

Codegen for SIGNEXTEND [Delivers #81700414]

cl-refactor
artur-zawlocki 10 years ago
parent
commit
9fffec2206
  1. 6
      alethzero/MainWin.cpp
  2. 1
      evmcc/test/arith/arith_bnot.evm
  3. 14
      evmcc/test/arith/arith_bnot.lll
  4. 1
      evmcc/test/ext/store_delete.evm
  5. 9
      evmcc/test/ext/store_delete.lll
  6. 2
      libdevcore/Common.cpp
  7. 2
      libethcore/CommonEth.cpp
  8. 24
      libethereum/AddressState.h
  9. 2
      libethereum/BlockChain.cpp
  10. 2
      libethereum/Executive.cpp
  11. 22
      libethereum/State.cpp
  12. 8
      libethereum/State.h
  13. 18
      libevm/VM.h
  14. 42
      libevmjit/Compiler.cpp
  15. 14
      libevmjit/Ext.cpp
  16. 20
      libevmjit/GasMeter.cpp
  17. 10
      libevmjit/Type.cpp
  18. 2
      libevmjit/Type.h
  19. 2
      liblll/Assembly.cpp
  20. 2
      libsolidity/Parser.cpp
  21. 2
      test/solidityParser.cpp
  22. 39
      test/vm.cpp
  23. 29
      test/vm.h

6
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 << "<br/>Pre: <i>Nothing is before the Gensesis</i>";
for (auto const& i: block[1])
s << "<br/>" << sha3(i[0].data()).abridged() << ": <b>" << i[1].toHash<h256>() << "</b> [<b>" << i[2].toInt<u256>() << "</b> used]";
s << "<br/>" << sha3(i.data()).abridged();// << ": <b>" << i[1].toHash<h256>() << "</b> [<b>" << i[2].toInt<u256>() << "</b> used]";
s << "<br/>Post: <b>" << info.stateRoot << "</b>";
}
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 << "<h3>" << th << "</h3>";

1
evmcc/test/arith/arith_bnot.evm

@ -0,0 +1 @@
6201e2406000546000530960005460206000f2

14
evmcc/test/arith/arith_bnot.lll

@ -0,0 +1,14 @@
(asm
123456
0
MSTORE
0
MLOAD
BNOT
0
MSTORE
32
0
RETURN
)

1
evmcc/test/ext/store_delete.evm

@ -0,0 +1 @@
6104d26063576000606357

9
evmcc/test/ext/store_delete.lll

@ -0,0 +1,9 @@
(asm
1234
99
SSTORE
0
99
SSTORE
)

2
libdevcore/Common.cpp

@ -27,7 +27,7 @@ using namespace dev;
namespace dev
{
char const* Version = "0.7.7";
char const* Version = "0.7.8";
}

2
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<pair<u256, string>> g_units =

24
libethereum/AddressState.h

@ -23,6 +23,7 @@
#include <libdevcore/Common.h>
#include <libdevcore/RLP.h>
#include <libdevcrypto/TrieDB.h>
#include <libdevcrypto/SHA3.h>
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<u256, u256> m_storageOverlay;

2
libethereum/BlockChain.cpp

@ -67,7 +67,7 @@ std::map<Address, AddressState> 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;
}

2
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();

22
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<Address, AddressState>& _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<u256>(), state[1].toInt<u256>(), state[2].toHash<h256>(), state[3].toHash<h256>());
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<h256, OverlayDB> storageDB(const_cast<OverlayDB*>(&m_db), r[2].toHash<h256>()); // promise not to alter OverlayDB.
for (auto const& j: storageDB) { (void)j; }
if (!e && r[3].toHash<h256>() && m_db.lookup(r[3].toHash<h256>()).empty())
if (!e && r[3].toHash<h256>() != EmptySHA3 && m_db.lookup(r[3].toHash<h256>()).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<u256, u256> mem;

8
libethereum/State.h

@ -385,7 +385,10 @@ void commit(std::map<Address, AddressState> const& _cache, DB& _db, TrieDB<Addre
s << i.second.nonce() << i.second.balance();
if (i.second.storage().empty())
s.append(i.second.baseRoot(), false, true);
{
assert(i.second.baseRoot());
s.append(i.second.baseRoot());
}
else
{
TrieDB<h256, DB> storageDB(&_db, i.second.baseRoot());
@ -394,7 +397,8 @@ void commit(std::map<Address, AddressState> const& _cache, DB& _db, TrieDB<Addre
storageDB.insert(j.first, rlp(j.second));
else
storageDB.remove(j.first);
s.append(storageDB.root(), false, true);
assert(storageDB.root());
s.append(storageDB.root());
}
if (i.second.isFreshCode())

18
libevm/VM.h

@ -426,16 +426,18 @@ template <class Ext> 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<unsigned>();
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();

42
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;

14
libevmjit/Ext.cpp

@ -6,6 +6,7 @@
#include <llvm/IR/IntrinsicInst.h>
#include <libdevcrypto/SHA3.h>
#include <libevm/FeeStructure.h>
#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)

20
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<uint64_t>(c_sstoreResetGas); // FIXME: Check store gas
case Instruction::SLOAD:
return static_cast<uint64_t>(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<uint64_t>(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);
}

10
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<uint64_t*>(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*>(llvm::ConstantInt::get(Type::i256, n));
}
llvm::ConstantInt* Constant::get(ReturnCode _returnCode)
{
return llvm::ConstantInt::get(Type::MainReturn, static_cast<uint64_t>(_returnCode));

2
libevmjit/Type.h

@ -3,6 +3,7 @@
#include <llvm/IR/Type.h>
#include <llvm/IR/Constants.h>
#include <libdevcore/Common.h>
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);
};

2
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)

2
libsolidity/Parser.cpp

@ -266,9 +266,11 @@ ASTPointer<Statement> Parser::parseStatement()
// starting from here, all statements must be terminated by a semicolon
case Token::CONTINUE:
statement = ASTNodeFactory(*this).createNode<Continue>();
m_scanner->next();
break;
case Token::BREAK:
statement = ASTNodeFactory(*this).createNode<Break>();
m_scanner->next();
break;
case Token::RETURN:
{

2
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));

39
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<ExtVM>(), 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<eth::VMTraceChannel, false>(true) << o.str();
dev::LogOutputStream<eth::VMTraceChannel, false>(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<FakeExtVM>()).toVector();
output = vm->go(fev, fev.simpleTrace()).toVector();
}
catch (OutOfGas const&)
{

29
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<typename ExtVMType>
eth::OnOpFunc simpleTrace();
FakeState state() const { return m_s; }
std::map<Address, std::tuple<u256, u256, std::map<u256, u256>, bytes>> addresses;
@ -99,32 +97,5 @@ private:
eth::Manifest m_ms;
};
template<typename ExtVMType>
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<eth::VMTraceChannel, false>(true) << o.str();
dev::LogOutputStream<eth::VMTraceChannel, false>(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

Loading…
Cancel
Save