Paweł Bylica
10 years ago
18 changed files with 192 additions and 238 deletions
@ -1,68 +0,0 @@ |
|||||
#pragma once |
|
||||
|
|
||||
#include <cstdint> |
|
||||
#include <functional> |
|
||||
|
|
||||
#ifdef _MSC_VER |
|
||||
#define EXPORT __declspec(dllexport) |
|
||||
#define _ALLOW_KEYWORD_MACROS |
|
||||
#define noexcept throw() |
|
||||
#else |
|
||||
#define EXPORT |
|
||||
#endif |
|
||||
|
|
||||
namespace dev |
|
||||
{ |
|
||||
namespace evmjit |
|
||||
{ |
|
||||
|
|
||||
using byte = uint8_t; |
|
||||
using bytes_ref = std::tuple<byte const*, size_t>; |
|
||||
using code_iterator = byte const*; |
|
||||
|
|
||||
struct h256 |
|
||||
{ |
|
||||
uint64_t words[4]; |
|
||||
}; |
|
||||
|
|
||||
inline bool operator==(h256 _h1, h256 _h2) |
|
||||
{ |
|
||||
return _h1.words[0] == _h2.words[0] && |
|
||||
_h1.words[1] == _h2.words[1] && |
|
||||
_h1.words[2] == _h2.words[2] && |
|
||||
_h1.words[3] == _h2.words[3]; |
|
||||
} |
|
||||
|
|
||||
/// Representation of 256-bit value binary compatible with LLVM i256
|
|
||||
struct i256 |
|
||||
{ |
|
||||
uint64_t a = 0; |
|
||||
uint64_t b = 0; |
|
||||
uint64_t c = 0; |
|
||||
uint64_t d = 0; |
|
||||
|
|
||||
i256() = default; |
|
||||
i256(h256 _h) |
|
||||
{ |
|
||||
a = _h.words[0]; |
|
||||
b = _h.words[1]; |
|
||||
c = _h.words[2]; |
|
||||
d = _h.words[3]; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
|
|
||||
namespace std |
|
||||
{ |
|
||||
template<> struct hash<dev::evmjit::h256> |
|
||||
{ |
|
||||
size_t operator()(dev::evmjit::h256 const& _h) const |
|
||||
{ |
|
||||
/// This implementation expects the argument to be a full 256-bit Keccak hash.
|
|
||||
/// It does nothing more than returning a slice of the input hash.
|
|
||||
return static_cast<size_t>(_h.words[0]); |
|
||||
}; |
|
||||
}; |
|
||||
} |
|
@ -1,33 +0,0 @@ |
|||||
#include "ExecutionContext.h" |
|
||||
#include <cassert> |
|
||||
|
|
||||
namespace dev |
|
||||
{ |
|
||||
namespace evmjit |
|
||||
{ |
|
||||
|
|
||||
extern "C" void ext_free(void* _data) noexcept; |
|
||||
|
|
||||
ExecutionContext::~ExecutionContext() |
|
||||
{ |
|
||||
if (m_memData) |
|
||||
ext_free(m_memData); // Use helper free to check memory leaks
|
|
||||
} |
|
||||
|
|
||||
bytes_ref ExecutionContext::getReturnData() const |
|
||||
{ |
|
||||
auto data = m_data->callData; |
|
||||
auto size = static_cast<size_t>(m_data->callDataSize); |
|
||||
|
|
||||
if (data < m_memData || data >= m_memData + m_memSize || size == 0) |
|
||||
{ |
|
||||
assert(size == 0); // data can be an invalid pointer only if size is 0
|
|
||||
m_data->callData = nullptr; |
|
||||
return {}; |
|
||||
} |
|
||||
|
|
||||
return bytes_ref{data, size}; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
@ -1,110 +0,0 @@ |
|||||
#pragma once |
|
||||
|
|
||||
#include "evmjit/DataTypes.h" |
|
||||
|
|
||||
namespace dev |
|
||||
{ |
|
||||
namespace evmjit |
|
||||
{ |
|
||||
|
|
||||
struct RuntimeData |
|
||||
{ |
|
||||
enum Index |
|
||||
{ |
|
||||
Gas, |
|
||||
GasPrice, |
|
||||
CallData, |
|
||||
CallDataSize, |
|
||||
Address, |
|
||||
Caller, |
|
||||
Origin, |
|
||||
CallValue, |
|
||||
CoinBase, |
|
||||
Difficulty, |
|
||||
GasLimit, |
|
||||
Number, |
|
||||
Timestamp, |
|
||||
Code, |
|
||||
CodeSize, |
|
||||
|
|
||||
SuicideDestAddress = Address, ///< Suicide balance destination address
|
|
||||
ReturnData = CallData, ///< Return data pointer (set only in case of RETURN)
|
|
||||
ReturnDataSize = CallDataSize, ///< Return data size (set only in case of RETURN)
|
|
||||
}; |
|
||||
|
|
||||
int64_t gas = 0; |
|
||||
int64_t gasPrice = 0; |
|
||||
byte const* callData = nullptr; |
|
||||
uint64_t callDataSize = 0; |
|
||||
i256 address; |
|
||||
i256 caller; |
|
||||
i256 origin; |
|
||||
i256 callValue; |
|
||||
i256 coinBase; |
|
||||
i256 difficulty; |
|
||||
i256 gasLimit; |
|
||||
uint64_t number = 0; |
|
||||
int64_t timestamp = 0; |
|
||||
byte const* code = nullptr; |
|
||||
uint64_t codeSize = 0; |
|
||||
h256 codeHash; |
|
||||
}; |
|
||||
|
|
||||
/// VM Environment (ExtVM) opaque type
|
|
||||
struct Env; |
|
||||
|
|
||||
enum class ReturnCode |
|
||||
{ |
|
||||
// Success codes
|
|
||||
Stop = 0, |
|
||||
Return = 1, |
|
||||
Suicide = 2, |
|
||||
|
|
||||
// Standard error codes
|
|
||||
OutOfGas = -1, |
|
||||
StackUnderflow = -2, |
|
||||
BadJumpDestination = -3, |
|
||||
BadInstruction = -4, |
|
||||
Rejected = -5, ///< Input data (code, gas, block info, etc.) does not meet JIT requirement and execution request has been rejected
|
|
||||
|
|
||||
// Internal error codes
|
|
||||
LLVMConfigError = -101, |
|
||||
LLVMCompileError = -102, |
|
||||
LLVMLinkError = -103, |
|
||||
|
|
||||
UnexpectedException = -111, |
|
||||
|
|
||||
LinkerWorkaround = -299, |
|
||||
}; |
|
||||
|
|
||||
class ExecutionContext |
|
||||
{ |
|
||||
public: |
|
||||
ExecutionContext() = default; |
|
||||
ExecutionContext(RuntimeData& _data, Env* _env) { init(_data, _env); } |
|
||||
ExecutionContext(ExecutionContext const&) = delete; |
|
||||
ExecutionContext& operator=(ExecutionContext const&) = delete; |
|
||||
EXPORT ~ExecutionContext(); |
|
||||
|
|
||||
void init(RuntimeData& _data, Env* _env) { m_data = &_data; m_env = _env; } |
|
||||
|
|
||||
byte const* code() const { return m_data->code; } |
|
||||
uint64_t codeSize() const { return m_data->codeSize; } |
|
||||
h256 const& codeHash() const { return m_data->codeHash; } |
|
||||
|
|
||||
bytes_ref getReturnData() const; |
|
||||
|
|
||||
private: |
|
||||
RuntimeData* m_data = nullptr; ///< Pointer to data. Expected by compiled contract.
|
|
||||
Env* m_env = nullptr; ///< Pointer to environment proxy. Expected by compiled contract.
|
|
||||
byte* m_memData = nullptr; |
|
||||
uint64_t m_memSize = 0; |
|
||||
uint64_t m_memCap = 0; |
|
||||
|
|
||||
public: |
|
||||
/// Reference to returned data (RETURN opcode used)
|
|
||||
bytes_ref returnData; |
|
||||
}; |
|
||||
|
|
||||
} |
|
||||
} |
|
Loading…
Reference in new issue