mirror of https://github.com/status-im/evmc.git
Merge pull request #206 from ethereum/rust-enum-aliases
rust: add enum aliases
This commit is contained in:
commit
f2aa41df66
|
@ -12,9 +12,13 @@ and this project adheres to [Semantic Versioning].
|
|||
- Added `MockedHost` C++ class (in form of header-only `evmc::mocked_host` library)
|
||||
which can be used to emulate Host behavior when testing VM implementations.
|
||||
[#456](https://github.com/ethereum/evmc/pull/456)
|
||||
- In the Rust bindings added more type aliases (`MessageKind`, `MessageFlags`, `StatusCode`,
|
||||
`StorageStatus`, `Revision`).
|
||||
[#206](https://github.com/ethereum/evmc/pull/206)
|
||||
|
||||
### Changed
|
||||
|
||||
- Require Rust 1.37.0 as a minimum.
|
||||
- In the Rust bindings mark read-only functions in `ExecutionContext` as non-mutating.
|
||||
[#444](https://github.com/ethereum/evmc/pull/444)
|
||||
- In the C++ `HostInterface` the logically read-only methods are marked with `const`.
|
||||
|
@ -22,7 +26,6 @@ and this project adheres to [Semantic Versioning].
|
|||
- Updated dependencies of the Rust bindings to latest stable versions.
|
||||
[#462](https://github.com/ethereum/evmc/pull/462)
|
||||
|
||||
|
||||
## [7.0.0] „Istanbul Ready” — 2019-11-11
|
||||
|
||||
This version of EVMC delivers compatibility with Istanbul EVM revision.
|
||||
|
|
|
@ -24,7 +24,7 @@ Please visit the [documentation].
|
|||
| **C** | C99, C11 | GCC 6+, clang 3.8+, MSVC 2015+
|
||||
| **C++** | C++11, C++14, C++17 | GCC 6+, clang 3.8+, MSVC 2015+
|
||||
| **Go** _(bindings)_ | 1.9 - 1.12 |
|
||||
| **Rust** _(bindings)_[¹](#n1) | 2018 edition | 1.31.0 and newer
|
||||
| **Rust** _(bindings)_[¹](#n1) | 2018 edition | 1.37.0 and newer
|
||||
|
||||
<b id="n1">1</b>. Rust support is limited and not complete yet, but it is mostly functional already. Breaking changes are possible at this stage.
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ pub trait EvmcVm {
|
|||
/// This is called for every incoming message.
|
||||
fn execute<'a>(
|
||||
&self,
|
||||
revision: ffi::evmc_revision,
|
||||
revision: Revision,
|
||||
code: &'a [u8],
|
||||
message: &'a ExecutionMessage,
|
||||
context: Option<&'a mut ExecutionContext<'a>>,
|
||||
|
@ -32,7 +32,7 @@ pub trait EvmcVm {
|
|||
/// EVMC result structure.
|
||||
#[derive(Debug)]
|
||||
pub struct ExecutionResult {
|
||||
status_code: ffi::evmc_status_code,
|
||||
status_code: StatusCode,
|
||||
gas_left: i64,
|
||||
output: Option<Vec<u8>>,
|
||||
create_address: Option<Address>,
|
||||
|
@ -41,7 +41,7 @@ pub struct ExecutionResult {
|
|||
/// EVMC execution message structure.
|
||||
#[derive(Debug)]
|
||||
pub struct ExecutionMessage {
|
||||
kind: ffi::evmc_call_kind,
|
||||
kind: MessageKind,
|
||||
flags: u32,
|
||||
depth: i32,
|
||||
gas: i64,
|
||||
|
@ -65,11 +65,7 @@ pub struct ExecutionContext<'a> {
|
|||
|
||||
impl ExecutionResult {
|
||||
/// Manually create a result.
|
||||
pub fn new(
|
||||
_status_code: ffi::evmc_status_code,
|
||||
_gas_left: i64,
|
||||
_output: Option<&[u8]>,
|
||||
) -> Self {
|
||||
pub fn new(_status_code: StatusCode, _gas_left: i64, _output: Option<&[u8]>) -> Self {
|
||||
ExecutionResult {
|
||||
status_code: _status_code,
|
||||
gas_left: _gas_left,
|
||||
|
@ -84,21 +80,21 @@ impl ExecutionResult {
|
|||
|
||||
/// Create failure result.
|
||||
pub fn failure() -> Self {
|
||||
ExecutionResult::new(ffi::evmc_status_code::EVMC_FAILURE, 0, None)
|
||||
ExecutionResult::new(StatusCode::EVMC_FAILURE, 0, None)
|
||||
}
|
||||
|
||||
/// Create a revert result.
|
||||
pub fn revert(_gas_left: i64, _output: Option<&[u8]>) -> Self {
|
||||
ExecutionResult::new(ffi::evmc_status_code::EVMC_REVERT, _gas_left, _output)
|
||||
ExecutionResult::new(StatusCode::EVMC_REVERT, _gas_left, _output)
|
||||
}
|
||||
|
||||
/// Create a successful result.
|
||||
pub fn success(_gas_left: i64, _output: Option<&[u8]>) -> Self {
|
||||
ExecutionResult::new(ffi::evmc_status_code::EVMC_SUCCESS, _gas_left, _output)
|
||||
ExecutionResult::new(StatusCode::EVMC_SUCCESS, _gas_left, _output)
|
||||
}
|
||||
|
||||
/// Read the status code.
|
||||
pub fn status_code(&self) -> ffi::evmc_status_code {
|
||||
pub fn status_code(&self) -> StatusCode {
|
||||
self.status_code
|
||||
}
|
||||
|
||||
|
@ -121,7 +117,7 @@ impl ExecutionResult {
|
|||
|
||||
impl ExecutionMessage {
|
||||
pub fn new(
|
||||
kind: ffi::evmc_call_kind,
|
||||
kind: MessageKind,
|
||||
flags: u32,
|
||||
depth: i32,
|
||||
gas: i64,
|
||||
|
@ -149,7 +145,7 @@ impl ExecutionMessage {
|
|||
}
|
||||
|
||||
/// Read the message kind.
|
||||
pub fn kind(&self) -> ffi::evmc_call_kind {
|
||||
pub fn kind(&self) -> MessageKind {
|
||||
self.kind
|
||||
}
|
||||
|
||||
|
@ -239,7 +235,7 @@ impl<'a> ExecutionContext<'a> {
|
|||
address: &Address,
|
||||
key: &Bytes32,
|
||||
value: &Bytes32,
|
||||
) -> ffi::evmc_storage_status {
|
||||
) -> StorageStatus {
|
||||
unsafe {
|
||||
assert!((*self.host).set_storage.is_some());
|
||||
(*self.host).set_storage.unwrap()(
|
||||
|
@ -501,9 +497,9 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn result_new() {
|
||||
let r = ExecutionResult::new(ffi::evmc_status_code::EVMC_FAILURE, 420, None);
|
||||
let r = ExecutionResult::new(StatusCode::EVMC_FAILURE, 420, None);
|
||||
|
||||
assert!(r.status_code() == ffi::evmc_status_code::EVMC_FAILURE);
|
||||
assert!(r.status_code() == StatusCode::EVMC_FAILURE);
|
||||
assert!(r.gas_left() == 420);
|
||||
assert!(r.output().is_none());
|
||||
assert!(r.create_address().is_none());
|
||||
|
@ -526,7 +522,7 @@ mod tests {
|
|||
#[test]
|
||||
fn result_from_ffi() {
|
||||
let f = ffi::evmc_result {
|
||||
status_code: ffi::evmc_status_code::EVMC_SUCCESS,
|
||||
status_code: StatusCode::EVMC_SUCCESS,
|
||||
gas_left: 1337,
|
||||
output_data: Box::into_raw(Box::new([0xde, 0xad, 0xbe, 0xef])) as *const u8,
|
||||
output_size: 4,
|
||||
|
@ -537,7 +533,7 @@ mod tests {
|
|||
|
||||
let r: ExecutionResult = f.into();
|
||||
|
||||
assert!(r.status_code() == ffi::evmc_status_code::EVMC_SUCCESS);
|
||||
assert!(r.status_code() == StatusCode::EVMC_SUCCESS);
|
||||
assert!(r.gas_left() == 1337);
|
||||
assert!(r.output().is_some());
|
||||
assert!(r.output().unwrap().len() == 4);
|
||||
|
@ -547,7 +543,7 @@ mod tests {
|
|||
#[test]
|
||||
fn result_into_heap_ffi() {
|
||||
let r = ExecutionResult::new(
|
||||
ffi::evmc_status_code::EVMC_FAILURE,
|
||||
StatusCode::EVMC_FAILURE,
|
||||
420,
|
||||
Some(&[0xc0, 0xff, 0xee, 0x71, 0x75]),
|
||||
);
|
||||
|
@ -555,7 +551,7 @@ mod tests {
|
|||
let f: *const ffi::evmc_result = r.into();
|
||||
assert!(!f.is_null());
|
||||
unsafe {
|
||||
assert!((*f).status_code == ffi::evmc_status_code::EVMC_FAILURE);
|
||||
assert!((*f).status_code == StatusCode::EVMC_FAILURE);
|
||||
assert!((*f).gas_left == 420);
|
||||
assert!(!(*f).output_data.is_null());
|
||||
assert!((*f).output_size == 5);
|
||||
|
@ -572,12 +568,12 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn result_into_heap_ffi_empty_data() {
|
||||
let r = ExecutionResult::new(ffi::evmc_status_code::EVMC_FAILURE, 420, None);
|
||||
let r = ExecutionResult::new(StatusCode::EVMC_FAILURE, 420, None);
|
||||
|
||||
let f: *const ffi::evmc_result = r.into();
|
||||
assert!(!f.is_null());
|
||||
unsafe {
|
||||
assert!((*f).status_code == ffi::evmc_status_code::EVMC_FAILURE);
|
||||
assert!((*f).status_code == StatusCode::EVMC_FAILURE);
|
||||
assert!((*f).gas_left == 420);
|
||||
assert!((*f).output_data.is_null());
|
||||
assert!((*f).output_size == 0);
|
||||
|
@ -591,14 +587,14 @@ mod tests {
|
|||
#[test]
|
||||
fn result_into_stack_ffi() {
|
||||
let r = ExecutionResult::new(
|
||||
ffi::evmc_status_code::EVMC_FAILURE,
|
||||
StatusCode::EVMC_FAILURE,
|
||||
420,
|
||||
Some(&[0xc0, 0xff, 0xee, 0x71, 0x75]),
|
||||
);
|
||||
|
||||
let f: ffi::evmc_result = r.into();
|
||||
unsafe {
|
||||
assert!(f.status_code == ffi::evmc_status_code::EVMC_FAILURE);
|
||||
assert!(f.status_code == StatusCode::EVMC_FAILURE);
|
||||
assert!(f.gas_left == 420);
|
||||
assert!(!f.output_data.is_null());
|
||||
assert!(f.output_size == 5);
|
||||
|
@ -615,11 +611,11 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn result_into_stack_ffi_empty_data() {
|
||||
let r = ExecutionResult::new(ffi::evmc_status_code::EVMC_FAILURE, 420, None);
|
||||
let r = ExecutionResult::new(StatusCode::EVMC_FAILURE, 420, None);
|
||||
|
||||
let f: ffi::evmc_result = r.into();
|
||||
unsafe {
|
||||
assert!(f.status_code == ffi::evmc_status_code::EVMC_FAILURE);
|
||||
assert!(f.status_code == StatusCode::EVMC_FAILURE);
|
||||
assert!(f.gas_left == 420);
|
||||
assert!(f.output_data.is_null());
|
||||
assert!(f.output_size == 0);
|
||||
|
@ -639,7 +635,7 @@ mod tests {
|
|||
let create2_salt = Bytes32 { bytes: [255u8; 32] };
|
||||
|
||||
let ret = ExecutionMessage::new(
|
||||
ffi::evmc_call_kind::EVMC_CALL,
|
||||
MessageKind::EVMC_CALL,
|
||||
44,
|
||||
66,
|
||||
4466,
|
||||
|
@ -650,7 +646,7 @@ mod tests {
|
|||
create2_salt,
|
||||
);
|
||||
|
||||
assert_eq!(ret.kind(), ffi::evmc_call_kind::EVMC_CALL);
|
||||
assert_eq!(ret.kind(), MessageKind::EVMC_CALL);
|
||||
assert_eq!(ret.flags(), 44);
|
||||
assert_eq!(ret.depth(), 66);
|
||||
assert_eq!(ret.gas(), 4466);
|
||||
|
@ -670,7 +666,7 @@ mod tests {
|
|||
let create2_salt = Bytes32 { bytes: [255u8; 32] };
|
||||
|
||||
let msg = ffi::evmc_message {
|
||||
kind: ffi::evmc_call_kind::EVMC_CALL,
|
||||
kind: MessageKind::EVMC_CALL,
|
||||
flags: 44,
|
||||
depth: 66,
|
||||
gas: 4466,
|
||||
|
@ -704,7 +700,7 @@ mod tests {
|
|||
let create2_salt = Bytes32 { bytes: [255u8; 32] };
|
||||
|
||||
let msg = ffi::evmc_message {
|
||||
kind: ffi::evmc_call_kind::EVMC_CALL,
|
||||
kind: MessageKind::EVMC_CALL,
|
||||
flags: 44,
|
||||
depth: 66,
|
||||
gas: 4466,
|
||||
|
@ -768,16 +764,16 @@ mod tests {
|
|||
|
||||
ffi::evmc_result {
|
||||
status_code: if success {
|
||||
ffi::evmc_status_code::EVMC_SUCCESS
|
||||
StatusCode::EVMC_SUCCESS
|
||||
} else {
|
||||
ffi::evmc_status_code::EVMC_INTERNAL_ERROR
|
||||
StatusCode::EVMC_INTERNAL_ERROR
|
||||
},
|
||||
gas_left: 2,
|
||||
// NOTE: we are passing the input pointer here, but for testing the lifetime is ok
|
||||
output_data: msg.input_data,
|
||||
output_size: msg.input_size,
|
||||
release: None,
|
||||
create_address: ffi::evmc_address::default(),
|
||||
create_address: Address::default(),
|
||||
padding: [0u8; 4],
|
||||
}
|
||||
}
|
||||
|
@ -832,36 +828,36 @@ mod tests {
|
|||
#[test]
|
||||
fn test_call_empty_data() {
|
||||
// This address is useless. Just a dummy parameter for the interface function.
|
||||
let test_addr = ffi::evmc_address { bytes: [0u8; 20] };
|
||||
let test_addr = Address::default();
|
||||
let host = get_dummy_host_interface();
|
||||
let host_context = std::ptr::null_mut();
|
||||
let mut exe_context = ExecutionContext::new(&host, host_context);
|
||||
|
||||
let message = ExecutionMessage::new(
|
||||
ffi::evmc_call_kind::EVMC_CALL,
|
||||
MessageKind::EVMC_CALL,
|
||||
0,
|
||||
0,
|
||||
6566,
|
||||
test_addr,
|
||||
test_addr,
|
||||
None,
|
||||
ffi::evmc_uint256be::default(),
|
||||
ffi::evmc_bytes32::default(),
|
||||
Uint256::default(),
|
||||
Bytes32::default(),
|
||||
);
|
||||
|
||||
let b = exe_context.call(&message);
|
||||
|
||||
assert_eq!(b.status_code(), ffi::evmc_status_code::EVMC_SUCCESS);
|
||||
assert_eq!(b.status_code(), StatusCode::EVMC_SUCCESS);
|
||||
assert_eq!(b.gas_left(), 2);
|
||||
assert!(b.output().is_none());
|
||||
assert!(b.create_address().is_some());
|
||||
assert_eq!(b.create_address().unwrap(), &ffi::evmc_address::default());
|
||||
assert_eq!(b.create_address().unwrap(), &Address::default());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_call_with_data() {
|
||||
// This address is useless. Just a dummy parameter for the interface function.
|
||||
let test_addr = ffi::evmc_address { bytes: [0u8; 20] };
|
||||
let test_addr = Address::default();
|
||||
let host = get_dummy_host_interface();
|
||||
let host_context = std::ptr::null_mut();
|
||||
let mut exe_context = ExecutionContext::new(&host, host_context);
|
||||
|
@ -869,24 +865,24 @@ mod tests {
|
|||
let data = vec![0xc0, 0xff, 0xfe];
|
||||
|
||||
let message = ExecutionMessage::new(
|
||||
ffi::evmc_call_kind::EVMC_CALL,
|
||||
MessageKind::EVMC_CALL,
|
||||
0,
|
||||
0,
|
||||
6566,
|
||||
test_addr,
|
||||
test_addr,
|
||||
Some(&data),
|
||||
ffi::evmc_uint256be::default(),
|
||||
ffi::evmc_bytes32::default(),
|
||||
Uint256::default(),
|
||||
Bytes32::default(),
|
||||
);
|
||||
|
||||
let b = exe_context.call(&message);
|
||||
|
||||
assert_eq!(b.status_code(), ffi::evmc_status_code::EVMC_SUCCESS);
|
||||
assert_eq!(b.status_code(), StatusCode::EVMC_SUCCESS);
|
||||
assert_eq!(b.gas_left(), 2);
|
||||
assert!(b.output().is_some());
|
||||
assert_eq!(b.output().unwrap(), &data);
|
||||
assert!(b.create_address().is_some());
|
||||
assert_eq!(b.create_address().unwrap(), &ffi::evmc_address::default());
|
||||
assert_eq!(b.create_address().unwrap(), &Address::default());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,21 @@ pub type Bytes32 = ffi::evmc_bytes32;
|
|||
/// EVMC big-endian 256-bit integer
|
||||
pub type Uint256 = ffi::evmc_uint256be;
|
||||
|
||||
/// EVMC call kind.
|
||||
pub type MessageKind = ffi::evmc_call_kind;
|
||||
|
||||
/// EVMC message (call) flags.
|
||||
pub type MessageFlags = ffi::evmc_flags;
|
||||
|
||||
/// EVMC status code.
|
||||
pub type StatusCode = ffi::evmc_status_code;
|
||||
|
||||
/// EVMC storage status.
|
||||
pub type StorageStatus = ffi::evmc_storage_status;
|
||||
|
||||
/// EVMC VM revision.
|
||||
pub type Revision = ffi::evmc_revision;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -34,4 +49,53 @@ mod tests {
|
|||
let b = Uint256::default();
|
||||
assert_eq!(a.clone(), b.clone());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn message_kind() {
|
||||
assert_eq!(MessageKind::EVMC_CALL, ffi::evmc_call_kind::EVMC_CALL);
|
||||
assert_eq!(
|
||||
MessageKind::EVMC_CALLCODE,
|
||||
ffi::evmc_call_kind::EVMC_CALLCODE
|
||||
);
|
||||
assert_eq!(
|
||||
MessageKind::EVMC_DELEGATECALL,
|
||||
ffi::evmc_call_kind::EVMC_DELEGATECALL
|
||||
);
|
||||
assert_eq!(MessageKind::EVMC_CREATE, ffi::evmc_call_kind::EVMC_CREATE);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn message_flags() {
|
||||
assert_eq!(MessageFlags::EVMC_STATIC, ffi::evmc_flags::EVMC_STATIC);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn status_code() {
|
||||
assert_eq!(
|
||||
StatusCode::EVMC_SUCCESS,
|
||||
ffi::evmc_status_code::EVMC_SUCCESS
|
||||
);
|
||||
assert_eq!(
|
||||
StatusCode::EVMC_FAILURE,
|
||||
ffi::evmc_status_code::EVMC_FAILURE
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn storage_status() {
|
||||
assert_eq!(
|
||||
StorageStatus::EVMC_STORAGE_UNCHANGED,
|
||||
ffi::evmc_storage_status::EVMC_STORAGE_UNCHANGED
|
||||
);
|
||||
assert_eq!(
|
||||
StorageStatus::EVMC_STORAGE_MODIFIED,
|
||||
ffi::evmc_storage_status::EVMC_STORAGE_MODIFIED
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn revision() {
|
||||
assert_eq!(Revision::EVMC_FRONTIER, ffi::evmc_revision::EVMC_FRONTIER);
|
||||
assert_eq!(Revision::EVMC_ISTANBUL, ffi::evmc_revision::EVMC_ISTANBUL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ impl EvmcVm for ExampleRustVM {
|
|||
|
||||
fn execute<'a>(
|
||||
&self,
|
||||
_revision: evmc_sys::evmc_revision,
|
||||
_revision: Revision,
|
||||
_code: &'a [u8],
|
||||
message: &'a ExecutionMessage,
|
||||
_context: Option<&'a mut ExecutionContext<'a>>,
|
||||
|
@ -26,7 +26,7 @@ impl EvmcVm for ExampleRustVM {
|
|||
}
|
||||
let _context = _context.unwrap();
|
||||
|
||||
if message.kind() != evmc_sys::evmc_call_kind::EVMC_CALL {
|
||||
if message.kind() != MessageKind::EVMC_CALL {
|
||||
return ExecutionResult::failure();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue