 |
Ethereum
PoC-8
The C++ Implementation of Ethereum
|
Go to the documentation of this file.
28 #include <json/json.h>
29 #include <boost/timer.hpp>
39 std::string dumpStackAndMemory(
LegacyVM const& _vm)
43 for (
auto i : _vm.
stack())
46 << ((_vm.
memory().size() > 1000) ?
" mem size greater than 1000 bytes " :
51 std::string dumpStorage(
ExtVM const& _ext)
56 o << showbase << hex << i.second.first <<
": " << i.second.second <<
"\n";
63 StandardTrace::StandardTrace():
64 m_trace(
Json::arrayValue)
93 ExtVM const& ext =
dynamic_cast<ExtVM const&
>(*voidExt);
94 auto vm =
dynamic_cast<LegacyVM const*
>(_vm);
96 Json::Value r(Json::objectValue);
98 Json::Value stack(Json::arrayValue);
102 for (
auto const& i : vm->stack())
107 bool newContext =
false;
110 if (m_lastInst.size() == ext.
depth)
113 assert(m_lastInst.size() == ext.
depth);
114 m_lastInst.push_back(inst);
117 else if (m_lastInst.size() == ext.
depth + 2)
119 m_lastInst.pop_back();
120 lastInst = m_lastInst.back();
122 else if (m_lastInst.size() == ext.
depth + 1)
125 lastInst = m_lastInst.back();
126 m_lastInst.back() = inst;
130 cwarn <<
"GAA!!! Tracing VM and more than one new/deleted stack frame between steps!";
131 cwarn <<
"Attmepting naive recovery...";
132 m_lastInst.resize(ext.
depth + 1);
135 Json::Value memJson(Json::arrayValue);
138 for (
unsigned i = 0; i < vm->memory().size(); i += 32)
141 memJson.append(
toHex(memRef));
143 r[
"memory"] = memJson;
148 Json::Value storage(Json::objectValue);
151 r[
"storage"] = storage;
161 r[
"memexpand"] =
toString(newMemSize);
168 return Json::StyledWriter().write(m_trace);
177 return std::accumulate(std::next(m_trace.begin()), m_trace.end(),
178 Json::FastWriter().write(m_trace[0]),
179 [](std::string a, Json::Value b) { return a + Json::FastWriter().write(b); });
183 m_s(_s.mutableState()),
184 m_envInfo(_s.info(), _bc.lastBlockHashes(), 0),
186 m_sealEngine(*_bc.sealEngine())
191 m_s(_s.mutableState()),
192 m_envInfo(_s.info(), _lh, 0),
194 m_sealEngine(*_s.sealEngine())
200 m_envInfo(_block.info(), _bc.lastBlockHashes(), _txIndex ? _block.receipt(_txIndex - 1).cumulativeGasUsed() : 0),
202 m_sealEngine(*_bc.sealEngine())
208 return m_t.
gas() - m_gas;
214 _parentContext += m_ext->sub;
241 LOG(m_execLogger) <<
"Invalid Signature";
245 if (m_t.
nonce() != nonceReq)
247 LOG(m_execLogger) <<
"Sender: " << m_t.
sender().
hex() <<
" Invalid Nonce: Require "
248 << nonceReq <<
" Got " << m_t.
nonce();
258 LOG(m_execLogger) <<
"Not enough cash: Require > " << totalCost <<
" = " << m_t.
gas()
265 m_gasCost = (
u256)gasCost;
274 LOG(m_detailsLogger) <<
"Paying " <<
formatBalance(m_gasCost) <<
" from sender for gas ("
278 assert(m_t.
gas() >= (
u256)m_baseGasRequired);
287 CallParameters params{_senderAddress, _receiveAddress, _receiveAddress, _value, _value, _gas, _data, {}};
288 return call(params, _gasPrice, _senderAddress);
329 size_t outputSize = output.size();
346 m_ext = make_shared<ExtVM>(m_s, m_envInfo, m_sealEngine, _p.
receiveAddress,
360 return createOpcode(_txSender, _endowment, _gasPrice, _gas, _init, _origin);
367 return executeCreate(_sender, _endowment, _gasPrice, _gas, _init, _origin);
373 return executeCreate(_sender, _endowment, _gasPrice, _gas, _init, _origin);
391 if (accountAlreadyExist)
393 LOG(m_detailsLogger) <<
"Address already used: " << m_newAddress;
408 m_s.
setNonce(m_newAddress, newNonce);
414 m_ext = make_shared<ExtVM>(m_s, m_envInfo, m_sealEngine, m_newAddress, _sender, _origin,
415 _endowment, _gasPrice,
bytesConstRef(), _init,
sha3(_init), m_depth,
true,
false);
422 Logger& traceLogger = m_vmTraceLogger;
426 ExtVM const& ext = *
static_cast<ExtVM const*
>(voidExt);
427 auto vm =
dynamic_cast<LegacyVM const*
>(_vm);
431 LOG(traceLogger) << dumpStackAndMemory(*vm);
432 LOG(traceLogger) << dumpStorage(ext);
433 LOG(traceLogger) <<
" < " << dec << ext.
depth <<
" : " << ext.
myAddress <<
" : #" << steps
434 <<
" : " << hex << setw(4) << setfill(
'0') <<
PC <<
" : "
436 << gasCost <<
" : " << newMemSize <<
"x32"
445 #if ETH_TIMED_EXECUTIONS
454 auto out = vm->exec(m_gas, *m_ext, _onOp);
460 if (out.size() > m_ext->evmSchedule().maxCodeSize)
462 else if (out.size() * m_ext->evmSchedule().createDataGas <= m_gas)
466 m_gas -= out.size() * m_ext->evmSchedule().createDataGas;
470 if (m_ext->evmSchedule().exceptionalFailedCodeDeposit)
480 m_res->
output = out.toVector();
481 m_s.
setCode(m_ext->myAddress, out.toVector());
484 m_output = vm->exec(m_gas, *m_ext, _onOp);
494 LOG(m_detailsLogger) <<
"Safe VM Exception. " << diagnostic_information(_e);
501 cerror <<
"Internal VM Error (EVMC status code: "
502 << *boost::get_error_info<errinfo_evmcStatusCode>(_e) <<
")";
509 cerror <<
"Unexpected exception in VM. There may be a bug in this implementation. "
510 << diagnostic_information(_e);
515 catch (std::exception
const& _e)
518 cerror <<
"Unexpected std::exception in VM. Not enough RAM? " << _e.what();
524 if (m_res && m_output)
528 #if ETH_TIMED_EXECUTIONS
529 cnote <<
"VM took:" <<
t.elapsed() <<
"; gas used: " << (sgas - m_endGas);
540 m_ext->sub.refunds += m_ext->evmSchedule().suicideRefundGas * m_ext->sub.suicides.size();
543 assert(m_ext->sub.refunds >= 0);
544 int64_t maxRefund = (
static_cast<int64_t
>(m_t.
gas()) -
static_cast<int64_t
>(m_gas)) / 2;
545 m_gas += min(maxRefund, m_ext->sub.refunds);
558 for (
auto a: m_ext->sub.suicides)
563 m_logs = m_ext->sub.logs;
570 m_res->
gasRefunded = m_ext ? m_ext->sub.refunds : 0;
std::function< void(uint64_t, uint64_t, Instruction, bigint, bigint, bigint, VMFace const *, ExtVMFace const *)> OnOpFunc
bool go(OnOpFunc const &_onOp=OnOpFunc())
std::string formatBalance(bigint const &_b)
User-friendly string representation of the amount _b in wei.
Address const MaxAddress
The last address.
Encodes a transaction, ready to be exported to or freshly imported from RLP.
void subBalance(Address const &_addr, u256 const &_value)
u256 gasForDeposit
Amount of gas remaining for the code deposit phase.
void toBigEndian(T _val, Out &o_out)
BlockHeader const & header() const
std::vector< mutable_value_type > toVector() const
void setNonce(Address const &_addr, u256 const &_newNonce)
Set the account nonce.
@ CREATE
create a new account with associated code
Address receiveAddress() const
void kill(Address _a)
Delete an account (used for processing suicides).
bool sha3(bytesConstRef _input, bytesRef o_output) noexcept
bytes const & code(Address const &_addr) const
@ DELEGATECALL
like CALLCODE but keeps caller's value and sender
State & createIntermediateState(State &o_s, Block const &_block, unsigned _txIndex, BlockChain const &_bc)
@ SSTORE
save word to storage
u256 experimentalForkBlock
Address const & author() const
static VMPtr create()
Creates a VM instance of the global kind (controlled by the –vm command line option).
bool create(Address const &_txSender, u256 const &_endowment, u256 const &_gasPrice, u256 const &_gas, bytesConstRef _code, Address const &_originAddress)
u256 getNonce(Address const &_addr) const
void incNonce(Address const &_id)
Increament the account nonce.
ChainOperationParams const & chainParams() const
std::string toString(std::chrono::time_point< T > const &_e, std::string const &_format="%F %T")
EVM Virtual Machine interface.
Interface and null implementation of the class for specifying VM externalities.
bool call(Address const &_receiveAddress, Address const &_txSender, u256 const &_txValue, u256 const &_gasPrice, bytesConstRef _txData, u256 const &_gas)
@ CALLCODE
message-call with another account's code only
bytes const & memory() const
void initialize(bytesConstRef _transaction)
Initializes the executive for evaluating a transaction. You must call finalize() at some point follow...
OnOpFunc simpleTrace()
Operation function for providing a simple trace of the VM execution.
void addBalance(Address const &_id, u256 const &_amount)
h160 right160(h256 const &_t)
Convert the given value into h160 (160-bit unsigned integer) using the right 20 bytes.
@ MLOAD
load word from memory
Base class for all exceptions.
void revert()
Revert all changes made to the state by this execution.
void clearStorage(Address const &_contract)
Clear the storage root hash of an account to the hash of the empty trie.
@ CALLDATACOPY
copy input data in current environment to memory
virtual void verifyTransaction(ImportRequirements::value _ir, TransactionBase const &_t, BlockHeader const &_header, u256 const &_startGasUsed) const
Additional verification for transactions in blocks.
Address myAddress
Address associated with executing code (a contract, or contract-to-be).
std::string toCompactHexPrefixed(u256 _val, unsigned _min=0)
std::string multilineTrace() const
boost::log::sources::severity_channel_logger<> Logger
u256 const & gasUsed() const
std::string styledJson() const
unsigned depth
Depth of the present call.
bool hasZeroSignature() const
virtual bigint costOfPrecompiled(Address const &_a, bytesConstRef _in, u256 const &) const
std::vector< byte > bytes
vector_ref< byte const > bytesConstRef
@ MSTORE
save word to memory
Implements the blockchain database. All data this gives is disk-backed. @threadsafe.
Externality interface for the Virtual Machine providing access to world state.
@ OutOfGasBase
Too little gas to pay for the base transaction cost.
virtual bool isPrecompiled(Address const &_a, u256 const &_blockNumber) const
int64_t baseGasRequired(EVMSchedule const &_es) const
bool addressHasCode(Address const &_address) const
Check if the address contains executable code.
@ CALL
message-call into an account
owning_bytes_ref && output()
char const *const name
The name of the instruction.
bool changesMemory(Instruction _inst)
Instruction
Virtual machine bytecode instruction.
boost::multiprecision::number< boost::multiprecision::cpp_int_backend<> > bigint
void transferBalance(Address const &_from, Address const &_to, u256 const &_value)
Transfers "the balance _value between two accounts.
virtual std::pair< bool, bytes > executePrecompiled(Address const &_a, bytesConstRef _in, u256 const &) const
u256 const & requireAccountStartNonce() const
Address const & sender() const
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void > > u256
bytes const & data() const
string memDump(bytes const &_bytes, unsigned _width, bool _html)
bool create2Opcode(Address const &_sender, u256 const &_endowment, u256 const &_gasPrice, u256 const &_gas, bytesConstRef _code, Address const &_originAddress, u256 const &_salt)
bool changesStorage(Instruction _inst)
void setCode(Address const &_address, bytes &&_code)
Sets the code of the account. Must only be called during / after contract creation.
unsigned depositSize
Amount of code of the creation's attempted deposit.
State const & state() const
boost::tuple< errinfo_required, errinfo_got > RequirementError
bytes rlpList()
Export a list of items in RLP format, returning a byte array.
u256 balance(Address const &_id) const
TransactionException toTransactionException(Exception const &_e)
h256 codeHash(Address const &_contract) const
@ CODECOPY
copy code running in current environment to memory
@ SHA3
compute SHA3-256 hash
Transaction const & t() const
InstructionInfo instructionInfo(Instruction _inst)
Information on all the instructions.
@ OutOfGas
Ran out of gas executing code of the transaction.
TransactionException excepted
@ MSTORE8
save byte to memory
void rollback(size_t _savepoint)
Revert all recent changes up to the given _savepoint savepoint.
virtual EVMSchedule const & evmSchedule(u256 const &_blockNumber) const =0
std::string toHex(Iterator _it, Iterator _end, std::string const &_prefix)
void accrueSubState(SubState &_parentContext)
Finalise an operation through accruing the substate into the parent context.
u256 storage(Address const &_contract, u256 const &_memory) const
bool createOpcode(Address const &_sender, u256 const &_endowment, u256 const &_gasPrice, u256 const &_gas, bytesConstRef _code, Address const &_originAddress)
Interface for getting a list of recent block hashes @threadsafe.
CodeDeposit codeDeposit
Failed if an attempted deposit failed due to lack of gas.
@ EXTCODECOPY
copy external code (from another contract)
Active model of a block within the block chain. Keeps track of all transactions, receipts and state f...
boost::error_info< struct tag_comment, std::string > errinfo_comment
Executive(State &_s, EnvInfo const &_envInfo, SealEngineFace const &_sealEngine, unsigned _level=0)
Simple constructor; executive will operate on given state, with the given environment info.
@ PC
get the program counter
void operator()(uint64_t _steps, uint64_t _PC, Instruction _inst, bigint _newMemSize, bigint _gasCost, bigint _gas, VMFace const *_vm, ExtVMFace const *_extVM)