Skip to content

Commit

Permalink
EVM runtime: implement LOG{0..4} opcodes by emitting actor events (FI…
Browse files Browse the repository at this point in the history
…P-0049) (#839)
  • Loading branch information
raulk authored Nov 15, 2022
1 parent e8d71b2 commit b1ba610
Show file tree
Hide file tree
Showing 26 changed files with 262 additions and 51 deletions.
30 changes: 17 additions & 13 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion actors/account/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ crate-type = ["cdylib", "lib"]
[dependencies]
fil_actors_runtime = { version = "10.0.0-alpha.1", path = "../../runtime" }
frc42_dispatch = "1.0.0"
fvm_shared = { version = "3.0.0-alpha.10", default-features = false }
fvm_shared = { version = "3.0.0-alpha.11", default-features = false }
serde = { version = "1.0.136", features = ["derive"] }
num-traits = "0.2.14"
num-derive = "0.3.3"
Expand Down
2 changes: 1 addition & 1 deletion actors/cron/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ crate-type = ["cdylib", "lib"]

[dependencies]
fil_actors_runtime = { version = "10.0.0-alpha.1", path = "../../runtime" }
fvm_shared = { version = "3.0.0-alpha.10", default-features = false }
fvm_shared = { version = "3.0.0-alpha.11", default-features = false }
num-traits = "0.2.14"
num-derive = "0.3.3"
log = "0.4.14"
Expand Down
2 changes: 1 addition & 1 deletion actors/datacap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fvm_actor_utils = "0.1.0"
fvm_ipld_blockstore = "0.1.1"
fvm_ipld_encoding = "0.3.0"
fvm_ipld_hamt = "0.6.1"
fvm_shared = { version = "3.0.0-alpha.10", default-features = false }
fvm_shared = { version = "3.0.0-alpha.11", default-features = false }
lazy_static = "1.4.0"
num-derive = "0.3.3"
num-traits = "0.2.14"
Expand Down
10 changes: 7 additions & 3 deletions actors/datacap/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,15 +390,19 @@ where
let res = self.rt.send(to, method, params.clone(), value.clone());

let rec = match res {
Ok(bytes) => {
Receipt { exit_code: ExitCode::OK, return_data: bytes, gas_used: fake_gas_used }
}
Ok(bytes) => Receipt {
exit_code: ExitCode::OK,
return_data: bytes,
gas_used: fake_gas_used,
events_root: None,
},
Err(ae) => {
info!("datacap messenger failed: {}", ae.msg());
Receipt {
exit_code: ae.exit_code(),
return_data: RawBytes::default(),
gas_used: fake_gas_used,
events_root: None,
}
}
};
Expand Down
2 changes: 1 addition & 1 deletion actors/eam/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ fvm_ipld_blockstore = "0.1.1"
fvm_ipld_encoding = "0.3.0"
multihash = { version = "0.16.1", default-features = false }
cid = "0.8.6"
fvm_shared = { version = "3.0.0-alpha.10", default-features = false }
fvm_shared = { version = "3.0.0-alpha.11", default-features = false }
num-traits = "0.2.15"
num-derive = "0.3.3"
hex-literal = "0.3.4"
Expand Down
4 changes: 2 additions & 2 deletions actors/embryo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ keywords = ["filecoin", "web3", "wasm"]
crate-type = ["cdylib", "lib"]

[dependencies]
fvm_sdk = { version = "3.0.0-alpha.10", optional = true }
fvm_shared = { version = "3.0.0-alpha.10", optional = true }
fvm_sdk = { version = "3.0.0-alpha.11", optional = true }
fvm_shared = { version = "3.0.0-alpha.11", optional = true }

[features]
fil-actor = ["fvm_sdk", "fvm_shared"]
2 changes: 1 addition & 1 deletion actors/evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ crate-type = ["cdylib", "lib"]

[dependencies]
fil_actors_runtime = { version = "10.0.0-alpha.1", path = "../../runtime" }
fvm_shared = { version = "3.0.0-alpha.10", default-features = false }
fvm_shared = { version = "3.0.0-alpha.11", default-features = false }
fvm_ipld_hamt = "0.6.1"
serde = { version = "1.0.136", features = ["derive"] }
serde_tuple = "0.5"
Expand Down
57 changes: 43 additions & 14 deletions actors/evm/src/interpreter/instructions/log.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,57 @@
use crate::interpreter::instructions::memory::get_memory_region;
use fvm_ipld_encoding::{to_vec, BytesSer, RawBytes};
use fvm_shared::event::{Entry, Flags};
use {
crate::interpreter::{ExecutionState, StatusCode, System},
fil_actors_runtime::runtime::Runtime,
};

#[cfg(debug_assertions)]
pub fn log(
_state: &mut ExecutionState,
_system: &System<impl Runtime>,
_num_topics: usize,
) -> Result<(), StatusCode> {
todo!("unimplemented");
}
/// The event key for the Ethereum log data.
const EVENT_DATA_KEY: &str = "data";

/// The event keys for the Ethereum log topics.
const EVENT_TOPIC_KEYS: &[&str] = &["topic1", "topic2", "topic3", "topic4"];

#[cfg(not(debug_assertions))]
#[inline]
pub fn log(
state: &mut ExecutionState,
_system: &System<impl Runtime>,
system: &System<impl Runtime>,
num_topics: usize,
) -> Result<(), StatusCode> {
// TODO: Right now, we just drop everything. But we implement this in production anyways so
// things work.
for _ in 0..num_topics {
state.stack.pop();
// Handle the data.
// Passing in a zero-sized memory region omits the data key entirely.
// LOG0 + a zero-sized memory region emits an event with no entries whatsoever. In this case,
// the FVM will record a hollow event carrying only the emitter actor ID.
let mem_index = state.stack.pop();
let size = state.stack.pop();
let region = get_memory_region(&mut state.memory, mem_index, size)
.map_err(|_| StatusCode::InvalidMemoryAccess)?;

// Extract the topics. Prefer to allocate an extra item than to incur in the cost of a
// decision based on the size of the data.
let mut entries: Vec<Entry> = Vec::with_capacity(num_topics + 1);
for key in EVENT_TOPIC_KEYS.iter().take(num_topics) {
let topic = state.stack.pop();
let entry = Entry {
flags: Flags::FLAG_INDEXED_VALUE,
key: (*key).to_owned(),
value: to_vec(&topic)?.into(), // U256 serializes as a byte string.
};
entries.push(entry);
}

// Skip adding the data if it's zero-sized.
if let Some(r) = region {
let data = state.memory[r.offset..r.offset + r.size.get()].to_vec();
let entry = Entry {
flags: Flags::FLAG_INDEXED_VALUE,
key: EVENT_DATA_KEY.to_owned(),
value: RawBytes::serialize(BytesSer(&data))?,
};
entries.push(entry);
}

system.rt.emit_event(&entries.into())?;

Ok(())
}
133 changes: 133 additions & 0 deletions actors/evm/tests/events.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
mod asm;

use fvm_ipld_encoding::{to_vec, RawBytes};
use fvm_shared::event::{ActorEvent, Entry, Flags};

mod util;

#[allow(dead_code)]
pub fn events_contract() -> Vec<u8> {
let init = r#"
"#;
let body = r#"
# method dispatch:
# - 0x00000000 -> log_zero_data
# - 0x00000001 -> log_zero_nodata
# - 0x00000002 -> log_four_data
%dispatch_begin()
%dispatch(0x00, log_zero_data)
%dispatch(0x01, log_zero_nodata)
%dispatch(0x02, log_four_data)
%dispatch_end()
#### log a zero topic event with data
log_zero_data:
jumpdest
push8 0x1122334455667788
push1 0x00
mstore
push1 0x08
push1 0x18 ## index 24 into memory as mstore writes a full word
log0
push1 0x00
push1 0x00
return
#### log a zero topic event with no data
log_zero_nodata:
jumpdest
push1 0x00
push1 0x00
log0
push1 0x00
push1 0x00
return
#### log a four topic event with data
log_four_data:
jumpdest
push8 0x1122334455667788
push1 0x00
mstore
push4 0x4444
push3 0x3333
push2 0x2222
push2 0x1111
push1 0x08
push1 0x18 ## index 24 into memory as mstore writes a full word
log4
push1 0x00
push1 0x00
return
"#;

asm::new_contract("events", init, body).unwrap()
}

#[test]
fn test_events() {
let contract = events_contract();

let mut rt = util::construct_and_verify(contract);

// log zero with data
let mut contract_params = vec![0u8; 32];
rt.expect_emitted_event(ActorEvent {
entries: vec![Entry {
flags: Flags::FLAG_INDEXED_VALUE,
key: "data".to_string(),
value: to_vec(&RawBytes::from(
[0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88].to_vec(),
))
.unwrap()
.into(),
}],
});
util::invoke_contract(&mut rt, &contract_params);

// log zero without data
contract_params[3] = 0x01;
rt.expect_emitted_event(ActorEvent { entries: vec![] });
util::invoke_contract(&mut rt, &contract_params);

// log four with data
contract_params[3] = 0x02;
rt.expect_emitted_event(ActorEvent {
entries: vec![
Entry {
flags: Flags::FLAG_INDEXED_VALUE,
key: "topic1".to_string(),
value: to_vec(&RawBytes::from([0x11, 0x11].to_vec())).unwrap().into(),
},
Entry {
flags: Flags::FLAG_INDEXED_VALUE,
key: "topic2".to_string(),
value: to_vec(&RawBytes::from([0x22, 0x22].to_vec())).unwrap().into(),
},
Entry {
flags: Flags::FLAG_INDEXED_VALUE,
key: "topic3".to_string(),
value: to_vec(&RawBytes::from([0x33, 0x33].to_vec())).unwrap().into(),
},
Entry {
flags: Flags::FLAG_INDEXED_VALUE,
key: "topic4".to_string(),
value: to_vec(&RawBytes::from([0x44, 0x44].to_vec())).unwrap().into(),
},
Entry {
flags: Flags::FLAG_INDEXED_VALUE,
key: "data".to_string(),
value: to_vec(&RawBytes::from(
[0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88].to_vec(),
))
.unwrap()
.into(),
},
],
});
util::invoke_contract(&mut rt, &contract_params);

rt.verify();
}
2 changes: 1 addition & 1 deletion actors/init/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ crate-type = ["cdylib", "lib"]

[dependencies]
fil_actors_runtime = { version = "10.0.0-alpha.1", path = "../../runtime" }
fvm_shared = { version = "3.0.0-alpha.10", default-features = false }
fvm_shared = { version = "3.0.0-alpha.11", default-features = false }
fvm_ipld_hamt = "0.6.1"
serde = { version = "1.0.136", features = ["derive"] }
num-traits = "0.2.14"
Expand Down
Loading

0 comments on commit b1ba610

Please sign in to comment.