Skip to content
This repository has been archived by the owner on Nov 26, 2024. It is now read-only.

Commit

Permalink
add transient get/set bytes32 hostios
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuacolvin0 committed Dec 14, 2023
1 parent 745a078 commit 185d5bd
Show file tree
Hide file tree
Showing 38 changed files with 5,429 additions and 73 deletions.
72 changes: 48 additions & 24 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -122,30 +122,38 @@ get_stylus_test_rust = $(wildcard $(stylus_test_dir)/$(1)/*.toml $(stylus_test_d
get_stylus_test_c = $(wildcard $(c_sdk)/examples/$(1)/*.c $(c_sdk)/examples/$(1)/*.h) $(stylus_lang_c)
stylus_test_bfs = $(wildcard $(stylus_test_dir)/bf/*.b)

stylus_test_keccak_wasm = $(call get_stylus_test_wasm,keccak)
stylus_test_keccak_src = $(call get_stylus_test_rust,keccak)
stylus_test_keccak-100_wasm = $(call get_stylus_test_wasm,keccak-100)
stylus_test_keccak-100_src = $(call get_stylus_test_rust,keccak-100)
stylus_test_fallible_wasm = $(call get_stylus_test_wasm,fallible)
stylus_test_fallible_src = $(call get_stylus_test_rust,fallible)
stylus_test_storage_wasm = $(call get_stylus_test_wasm,storage)
stylus_test_storage_src = $(call get_stylus_test_rust,storage)
stylus_test_multicall_wasm = $(call get_stylus_test_wasm,multicall)
stylus_test_multicall_src = $(call get_stylus_test_rust,multicall)
stylus_test_log_wasm = $(call get_stylus_test_wasm,log)
stylus_test_log_src = $(call get_stylus_test_rust,log)
stylus_test_create_wasm = $(call get_stylus_test_wasm,create)
stylus_test_create_src = $(call get_stylus_test_rust,create)
stylus_test_evm-data_wasm = $(call get_stylus_test_wasm,evm-data)
stylus_test_evm-data_src = $(call get_stylus_test_rust,evm-data)
stylus_test_sdk-storage_wasm = $(call get_stylus_test_wasm,sdk-storage)
stylus_test_sdk-storage_src = $(call get_stylus_test_rust,sdk-storage)
stylus_test_erc20_wasm = $(call get_stylus_test_wasm,erc20)
stylus_test_erc20_src = $(call get_stylus_test_rust,erc20)
stylus_test_read-return-data_wasm = $(call get_stylus_test_wasm,read-return-data)
stylus_test_read-return-data_src = $(call get_stylus_test_rust,read-return-data)

stylus_test_wasms = $(stylus_test_keccak_wasm) $(stylus_test_keccak-100_wasm) $(stylus_test_fallible_wasm) $(stylus_test_storage_wasm) $(stylus_test_multicall_wasm) $(stylus_test_log_wasm) $(stylus_test_create_wasm) $(stylus_test_sdk-storage_wasm) $(stylus_test_erc20_wasm) $(stylus_test_read-return-data_wasm) $(stylus_test_evm-data_wasm) $(stylus_test_bfs:.b=.wasm)
stylus_test_keccak_wasm = $(call get_stylus_test_wasm,keccak)
stylus_test_keccak_src = $(call get_stylus_test_rust,keccak)
stylus_test_keccak-100_wasm = $(call get_stylus_test_wasm,keccak-100)
stylus_test_keccak-100_src = $(call get_stylus_test_rust,keccak-100)
stylus_test_fallible_wasm = $(call get_stylus_test_wasm,fallible)
stylus_test_fallible_src = $(call get_stylus_test_rust,fallible)
stylus_test_storage_wasm = $(call get_stylus_test_wasm,storage)
stylus_test_storage_src = $(call get_stylus_test_rust,storage)
stylus_test_multicall_wasm = $(call get_stylus_test_wasm,multicall)
stylus_test_multicall_src = $(call get_stylus_test_rust,multicall)
stylus_test_log_wasm = $(call get_stylus_test_wasm,log)
stylus_test_log_src = $(call get_stylus_test_rust,log)
stylus_test_create_wasm = $(call get_stylus_test_wasm,create)
stylus_test_create_src = $(call get_stylus_test_rust,create)
stylus_test_evm-data_wasm = $(call get_stylus_test_wasm,evm-data)
stylus_test_evm-data_src = $(call get_stylus_test_rust,evm-data)
stylus_test_sdk-storage_wasm = $(call get_stylus_test_wasm,sdk-storage)
stylus_test_sdk-storage_src = $(call get_stylus_test_rust,sdk-storage)
stylus_test_erc20_wasm = $(call get_stylus_test_wasm,erc20)
stylus_test_erc20_src = $(call get_stylus_test_rust,erc20)
stylus_test_read-return-data_wasm = $(call get_stylus_test_wasm,read-return-data)
stylus_test_read-return-data_src = $(call get_stylus_test_rust,read-return-data)
stylus_test_transient-enter_wasm = $(call get_stylus_test_wasm,transient-enter)
stylus_test_transient-enter_src = $(call get_stylus_test_rust,transient-enter)
stylus_test_transient-reenter_wasm = $(call get_stylus_test_wasm,transient-reenter)
stylus_test_transient-reenter_src = $(call get_stylus_test_rust,transient-reenter)
stylus_test_transient-delegate-enter_wasm = $(call get_stylus_test_wasm,transient-delegate-enter)
stylus_test_transient-delegate-enter_src = $(call get_stylus_test_rust,transient-delegate-enter)
stylus_test_transient-delegate-reenter_wasm = $(call get_stylus_test_wasm,transient-delegate-reenter)
stylus_test_transient-delegate-reenter_src = $(call get_stylus_test_rust,transient-delegate-reenter)

stylus_test_wasms = $(stylus_test_keccak_wasm) $(stylus_test_keccak-100_wasm) $(stylus_test_fallible_wasm) $(stylus_test_storage_wasm) $(stylus_test_multicall_wasm) $(stylus_test_log_wasm) $(stylus_test_create_wasm) $(stylus_test_sdk-storage_wasm) $(stylus_test_erc20_wasm) $(stylus_test_read-return-data_wasm) $(stylus_test_evm-data_wasm) $(stylus_test_bfs:.b=.wasm) $(stylus_test_transient-enter_wasm) $(stylus_test_transient-reenter_wasm) $(stylus_test_transient-delegate-enter_wasm) $(stylus_test_transient-delegate-reenter_wasm)
stylus_benchmarks = $(wildcard $(stylus_dir)/*.toml $(stylus_dir)/src/*.rs) $(stylus_test_wasms)

# user targets
Expand Down Expand Up @@ -418,6 +426,22 @@ $(stylus_test_read-return-data_wasm): $(stylus_test_read-return-data_src)
$(cargo_nightly) --manifest-path $< --release --config $(stylus_cargo)
@touch -c $@ # cargo might decide to not rebuild the binary

$(stylus_test_transient-enter_wasm): $(stylus_test_transient-enter_src)
$(cargo_nightly) --manifest-path $< --release --config $(stylus_cargo)
@touch -c $@ # cargo might decide to not rebuild the binary

$(stylus_test_transient-reenter_wasm): $(stylus_test_transient-reenter_src)
$(cargo_nightly) --manifest-path $< --release --config $(stylus_cargo)
@touch -c $@ # cargo might decide to not rebuild the binary

$(stylus_test_transient-delegate-enter_wasm): $(stylus_test_transient-delegate-enter_src)
$(cargo_nightly) --manifest-path $< --release --config $(stylus_cargo)
@touch -c $@ # cargo might decide to not rebuild the binary

$(stylus_test_transient-delegate-reenter_wasm): $(stylus_test_transient-delegate-reenter_src)
$(cargo_nightly) --manifest-path $< --release --config $(stylus_cargo)
@touch -c $@ # cargo might decide to not rebuild the binary

$(stylus_test_sdk-storage_wasm): $(stylus_test_sdk-storage_src)
$(cargo_nightly) --manifest-path $< --release --config $(stylus_cargo)
@touch -c $@ # cargo might decide to not rebuild the binary
Expand Down
13 changes: 13 additions & 0 deletions arbitrator/arbutil/src/evm/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ impl From<u8> for EvmApiStatus {
pub enum EvmApiMethod {
GetBytes32,
SetBytes32,
TransientGetBytes32,
TransientSetBytes32,
ContractCall,
DelegateCall,
StaticCall,
Expand All @@ -57,6 +59,17 @@ pub trait EvmApi: Send + 'static {
/// Analogous to `vm.SSTORE`.
fn set_bytes32(&mut self, key: Bytes32, value: Bytes32) -> Result<u64>;

/// Reads the 32-byte value in the EVM state trie at offset `key`.
/// Storage is discarded after every transaction
/// Returns the value.
/// Analogous to `vm.TLOAD`.
fn transient_get_bytes32(&mut self, key: Bytes32) -> Bytes32;

/// Stores the given value at the given key in the EVM state trie.
/// Storage is discarded after every transaction
/// Analogous to `vm.TSTORE`.
fn transient_set_bytes32(&mut self, key: Bytes32, value: Bytes32) -> Result<()>;

/// Calls the contract at the given address.
/// Returns the EVM return data's length, the gas cost, and whether the call succeeded.
/// Analogous to `vm.CALL`.
Expand Down
14 changes: 14 additions & 0 deletions arbitrator/arbutil/src/evm/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,20 @@ impl<T: JsCallIntoGo> EvmApi for JsEvmApi<T> {
}
}

fn transient_get_bytes32(&mut self, key: Bytes32) -> Bytes32 {
let [value] = call!(self, 1, TransientGetBytes32, key);
value.assert_bytes32()
}

fn transient_set_bytes32(&mut self, key: Bytes32, value: Bytes32) -> Result<()> {
let [out] = call!(self, 1, TransientSetBytes32, key, value);
match out {
ApiValueKind::Nil => Ok(()),
ApiValueKind::String(err) => bail!(err),
_ => unreachable!(),
}
}

fn contract_call(
&mut self,
contract: Bytes20,
Expand Down
3 changes: 3 additions & 0 deletions arbitrator/arbutil/src/evm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ pub mod user;
// params.SstoreSentryGasEIP2200
pub const SSTORE_SENTRY_GAS: u64 = 2300;

// params.WarmStorageReadCostEIP2929
pub const TRANSIENT_BYTES32_GAS: u64 = 100;

// params.LogGas and params.LogDataGas
pub const LOG_TOPIC_GAS: u64 = 375;
pub const LOG_DATA_GAS: u64 = 8;
Expand Down
2 changes: 1 addition & 1 deletion arbitrator/langs/c
Submodule c updated 2 files
+22 −2 include/hostio.h
+22 −1 include/storage.h
22 changes: 22 additions & 0 deletions arbitrator/stylus/src/evm_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ pub struct GoEvmApi {
gas_cost: *mut u64,
error: *mut RustBytes,
) -> EvmApiStatus,
pub transient_get_bytes32: unsafe extern "C" fn(id: usize, key: Bytes32) -> Bytes32, // value
pub transient_set_bytes32: unsafe extern "C" fn(
id: usize,
key: Bytes32,
value: Bytes32,
error: *mut RustBytes,
) -> EvmApiStatus,
pub contract_call: unsafe extern "C" fn(
id: usize,
contract: Bytes20,
Expand Down Expand Up @@ -117,6 +124,21 @@ impl EvmApi for GoEvmApi {
}
}

fn transient_get_bytes32(&mut self, key: Bytes32) -> Bytes32 {
let value = call!(self, transient_get_bytes32, key);
value
}

fn transient_set_bytes32(&mut self, key: Bytes32, value: Bytes32) -> Result<()> {
let mut error = RustBytes::new(vec![]);
let api_status = call!(self, transient_set_bytes32, key, value, ptr!(error));
let error = into_vec!(error); // done here to always drop
match api_status {
EvmApiStatus::Success => Ok(()),
EvmApiStatus::Failure => Err(error!(error)),
}
}

fn contract_call(
&mut self,
contract: Bytes20,
Expand Down
16 changes: 16 additions & 0 deletions arbitrator/stylus/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,22 @@ pub(crate) fn storage_store_bytes32<E: EvmApi>(
hostio!(env, storage_store_bytes32(key, value))
}

pub(crate) fn storage_transient_load_bytes32<E: EvmApi>(
mut env: WasmEnvMut<E>,
key: u32,
dest: u32,
) -> MaybeEscape {
hostio!(env, storage_transient_load_bytes32(key, dest))
}

pub(crate) fn storage_transient_store_bytes32<E: EvmApi>(
mut env: WasmEnvMut<E>,
key: u32,
value: u32,
) -> MaybeEscape {
hostio!(env, storage_transient_store_bytes32(key, value))
}

pub(crate) fn call_contract<E: EvmApi>(
mut env: WasmEnvMut<E>,
contract: u32,
Expand Down
4 changes: 4 additions & 0 deletions arbitrator/stylus/src/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ impl<E: EvmApi> NativeInstance<E> {
"write_result" => func!(host::write_result),
"storage_load_bytes32" => func!(host::storage_load_bytes32),
"storage_store_bytes32" => func!(host::storage_store_bytes32),
"storage_transient_load_bytes32" => func!(host::storage_transient_load_bytes32),
"storage_transient_store_bytes32" => func!(host::storage_transient_store_bytes32),
"call_contract" => func!(host::call_contract),
"delegate_call_contract" => func!(host::delegate_call_contract),
"static_call_contract" => func!(host::static_call_contract),
Expand Down Expand Up @@ -332,6 +334,8 @@ pub fn module(wasm: &[u8], compile: CompileConfig) -> Result<Vec<u8>> {
"write_result" => stub!(|_: u32, _: u32|),
"storage_load_bytes32" => stub!(|_: u32, _: u32|),
"storage_store_bytes32" => stub!(|_: u32, _: u32|),
"storage_transient_load_bytes32" => stub!(|_: u32, _: u32|),
"storage_transient_store_bytes32" => stub!(|_: u32, _: u32|),
"call_contract" => stub!(u8 <- |_: u32, _: u32, _: u32, _: u32, _: u64, _: u32|),
"delegate_call_contract" => stub!(u8 <- |_: u32, _: u32, _: u32, _: u64, _: u32|),
"static_call_contract" => stub!(u8 <- |_: u32, _: u32, _: u32, _: u64, _: u32|),
Expand Down
18 changes: 18 additions & 0 deletions arbitrator/stylus/src/test/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use super::TestInstance;
pub(crate) struct TestEvmApi {
contracts: Arc<Mutex<HashMap<Bytes20, Vec<u8>>>>,
storage: Arc<Mutex<HashMap<Bytes20, HashMap<Bytes32, Bytes32>>>>,
transient_storage: Arc<Mutex<HashMap<Bytes20, HashMap<Bytes32, Bytes32>>>>,
program: Bytes20,
write_result: Arc<Mutex<Vec<u8>>>,
compile: CompileConfig,
Expand All @@ -33,9 +34,12 @@ impl TestEvmApi {
let mut storage = HashMap::new();
storage.insert(program, HashMap::new());

let mut transient_storage = HashMap::new();

let api = TestEvmApi {
contracts: Arc::new(Mutex::new(HashMap::new())),
storage: Arc::new(Mutex::new(storage)),
transient_storage: Arc::new(Mutex::new(transient_storage)),
program,
write_result: Arc::new(Mutex::new(vec![])),
compile,
Expand Down Expand Up @@ -77,6 +81,20 @@ impl EvmApi for TestEvmApi {
Ok(22100) // pretend worst case
}

fn transient_get_bytes32(&mut self, key: Bytes32) -> Bytes32 {
let transient_storage = &mut self.transient_storage.lock();
let transient_storage = transient_storage.get_mut(&self.program).unwrap();
let value = transient_storage.get(&key).cloned().unwrap_or_default();
value
}

fn transient_set_bytes32(&mut self, key: Bytes32, value: Bytes32) -> Result<()> {
let transient_storage = &mut self.transient_storage.lock();
let transient_storage = transient_storage.get_mut(&self.program).unwrap();
transient_storage.insert(key, value);
Ok(())
}

/// Simulates a contract call.
/// Note: this call function is for testing purposes only and deviates from onchain behavior.
fn contract_call(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
target = "wasm32-unknown-unknown"
Loading

0 comments on commit 185d5bd

Please sign in to comment.