mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-13 22:21:05 +00:00
switch to the new storage API (#396)
This PR switches to the new `get_storage_or_zero` and `set_storage_or_clear` syscalls which are more tailored towards Solidity. Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
This commit is contained in:
@@ -2,9 +2,9 @@
|
|||||||
"Baseline": 914,
|
"Baseline": 914,
|
||||||
"Computation": 2295,
|
"Computation": 2295,
|
||||||
"DivisionArithmetics": 14510,
|
"DivisionArithmetics": 14510,
|
||||||
"ERC20": 17499,
|
"ERC20": 17482,
|
||||||
"Events": 1674,
|
"Events": 1674,
|
||||||
"FibonacciIterative": 1490,
|
"FibonacciIterative": 1490,
|
||||||
"Flipper": 2102,
|
"Flipper": 2086,
|
||||||
"SHA1": 8158
|
"SHA1": 8158
|
||||||
}
|
}
|
||||||
@@ -157,6 +157,10 @@ fn emit_load<'ctx>(
|
|||||||
key: BasicValueEnum<'ctx>,
|
key: BasicValueEnum<'ctx>,
|
||||||
transient: bool,
|
transient: bool,
|
||||||
) -> anyhow::Result<BasicValueEnum<'ctx>> {
|
) -> anyhow::Result<BasicValueEnum<'ctx>> {
|
||||||
|
let is_transient = context.xlen_type().const_int(transient as u64, false);
|
||||||
|
let key_pointer = context.build_alloca_at_entry(context.word_type(), "key_pointer");
|
||||||
|
let value_pointer = context.build_alloca_at_entry(context.word_type(), "value_pointer");
|
||||||
|
|
||||||
let mut key = context.build_load(
|
let mut key = context.build_load(
|
||||||
super::Pointer::new(
|
super::Pointer::new(
|
||||||
context.word_type(),
|
context.word_type(),
|
||||||
@@ -168,33 +172,17 @@ fn emit_load<'ctx>(
|
|||||||
if !transient {
|
if !transient {
|
||||||
key = context.build_byte_swap(key)?;
|
key = context.build_byte_swap(key)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let key_pointer = context.build_alloca_at_entry(context.word_type(), "key_pointer");
|
|
||||||
let value_pointer = context.build_alloca_at_entry(context.word_type(), "value_pointer");
|
|
||||||
let length_pointer = context.build_alloca_at_entry(context.xlen_type(), "length_pointer");
|
|
||||||
|
|
||||||
context.builder().build_store(key_pointer.value, key)?;
|
context.builder().build_store(key_pointer.value, key)?;
|
||||||
context.build_store(value_pointer, context.word_const(0))?;
|
|
||||||
context.build_store(
|
|
||||||
length_pointer,
|
|
||||||
context
|
|
||||||
.xlen_type()
|
|
||||||
.const_int(revive_common::BYTE_LENGTH_WORD as u64, false),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let is_transient = context.xlen_type().const_int(transient as u64, false);
|
|
||||||
|
|
||||||
let arguments = [
|
let arguments = [
|
||||||
is_transient.into(),
|
is_transient.into(),
|
||||||
key_pointer.to_int(context).into(),
|
key_pointer.to_int(context).into(),
|
||||||
context.xlen_type().const_all_ones().into(),
|
|
||||||
value_pointer.to_int(context).into(),
|
value_pointer.to_int(context).into(),
|
||||||
length_pointer.to_int(context).into(),
|
|
||||||
];
|
];
|
||||||
context.build_runtime_call(revive_runtime_api::polkavm_imports::GET_STORAGE, &arguments);
|
context.build_runtime_call(revive_runtime_api::polkavm_imports::GET_STORAGE, &arguments);
|
||||||
|
|
||||||
// We do not to check the return value: Solidity assumes infallible loads.
|
// We do not to check the return value: Solidity assumes infallible loads.
|
||||||
// If a key doesn't exist the "zero" value is returned (ensured by above write).
|
// If a key doesn't exist the syscall returns zero.
|
||||||
|
|
||||||
let value = context.build_load(value_pointer, "storage_value")?;
|
let value = context.build_load(value_pointer, "storage_value")?;
|
||||||
Ok(if transient {
|
Ok(if transient {
|
||||||
@@ -210,6 +198,10 @@ fn emit_store<'ctx>(
|
|||||||
value: BasicValueEnum<'ctx>,
|
value: BasicValueEnum<'ctx>,
|
||||||
transient: bool,
|
transient: bool,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
|
let is_transient = context.xlen_type().const_int(transient as u64, false);
|
||||||
|
let key_pointer = context.build_alloca_at_entry(context.word_type(), "key_pointer");
|
||||||
|
let value_pointer = context.build_alloca_at_entry(context.word_type(), "value_pointer");
|
||||||
|
|
||||||
let mut key = context.build_load(
|
let mut key = context.build_load(
|
||||||
super::Pointer::new(
|
super::Pointer::new(
|
||||||
context.word_type(),
|
context.word_type(),
|
||||||
@@ -224,27 +216,20 @@ fn emit_store<'ctx>(
|
|||||||
Default::default(),
|
Default::default(),
|
||||||
value.into_pointer_value(),
|
value.into_pointer_value(),
|
||||||
),
|
),
|
||||||
"key",
|
"value",
|
||||||
)?;
|
)?;
|
||||||
if !transient {
|
if !transient {
|
||||||
key = context.build_byte_swap(key)?;
|
key = context.build_byte_swap(key)?;
|
||||||
value = context.build_byte_swap(value)?;
|
value = context.build_byte_swap(value)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let key_pointer = context.build_alloca_at_entry(context.word_type(), "key_pointer");
|
|
||||||
let value_pointer = context.build_alloca_at_entry(context.word_type(), "value_pointer");
|
|
||||||
|
|
||||||
context.build_store(key_pointer, key)?;
|
context.build_store(key_pointer, key)?;
|
||||||
context.build_store(value_pointer, value)?;
|
context.build_store(value_pointer, value)?;
|
||||||
|
|
||||||
let is_transient = context.xlen_type().const_int(transient as u64, false);
|
|
||||||
|
|
||||||
let arguments = [
|
let arguments = [
|
||||||
is_transient.into(),
|
is_transient.into(),
|
||||||
key_pointer.to_int(context).into(),
|
key_pointer.to_int(context).into(),
|
||||||
context.xlen_type().const_all_ones().into(),
|
|
||||||
value_pointer.to_int(context).into(),
|
value_pointer.to_int(context).into(),
|
||||||
context.integer_const(crate::polkavm::XLEN, 32).into(),
|
|
||||||
];
|
];
|
||||||
context.build_runtime_call(revive_runtime_api::polkavm_imports::SET_STORAGE, &arguments);
|
context.build_runtime_call(revive_runtime_api::polkavm_imports::SET_STORAGE, &arguments);
|
||||||
|
|
||||||
|
|||||||
@@ -510,13 +510,10 @@ impl Specs {
|
|||||||
expected,
|
expected,
|
||||||
} => {
|
} => {
|
||||||
let address = contract.to_eth_addr(&results);
|
let address = contract.to_eth_addr(&results);
|
||||||
let Ok(value) = Contracts::get_storage(address, key) else {
|
let value = Contracts::get_storage(address, key)
|
||||||
panic!("error reading storage for address {address}");
|
.unwrap_or_else(|error| panic!("at {address}: {error:?}"))
|
||||||
};
|
.unwrap_or_else(|| vec![0; 32]);
|
||||||
let Some(value) = value else {
|
assert_eq!(value, expected, "at {address} key 0x{}", hex::encode(key));
|
||||||
panic!("no value at {address} key 0x{}", hex::encode(key));
|
|
||||||
};
|
|
||||||
assert_eq!(value, expected, "at key 0x{}", hex::encode(key));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ POLKAVM_IMPORT(uint64_t, gas_price);
|
|||||||
|
|
||||||
POLKAVM_IMPORT(void, get_immutable_data, uint32_t, uint32_t);
|
POLKAVM_IMPORT(void, get_immutable_data, uint32_t, uint32_t);
|
||||||
|
|
||||||
POLKAVM_IMPORT(uint64_t, get_storage, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)
|
POLKAVM_IMPORT(uint64_t, get_storage_or_zero, uint32_t, uint32_t, uint32_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(void, hash_keccak_256, uint32_t, uint32_t, uint32_t)
|
POLKAVM_IMPORT(void, hash_keccak_256, uint32_t, uint32_t, uint32_t)
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ POLKAVM_IMPORT(uint64_t, return_data_size)
|
|||||||
|
|
||||||
POLKAVM_IMPORT(void, set_immutable_data, uint32_t, uint32_t);
|
POLKAVM_IMPORT(void, set_immutable_data, uint32_t, uint32_t);
|
||||||
|
|
||||||
POLKAVM_IMPORT(uint64_t, set_storage, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)
|
POLKAVM_IMPORT(uint64_t, set_storage_or_clear, uint32_t, uint32_t, uint32_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(void, value_transferred, uint32_t)
|
POLKAVM_IMPORT(void, value_transferred, uint32_t)
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ pub static GAS_PRICE: &str = "gas_price";
|
|||||||
|
|
||||||
pub static GET_IMMUTABLE_DATA: &str = "get_immutable_data";
|
pub static GET_IMMUTABLE_DATA: &str = "get_immutable_data";
|
||||||
|
|
||||||
pub static GET_STORAGE: &str = "get_storage";
|
pub static GET_STORAGE: &str = "get_storage_or_zero";
|
||||||
|
|
||||||
pub static HASH_KECCAK_256: &str = "hash_keccak_256";
|
pub static HASH_KECCAK_256: &str = "hash_keccak_256";
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ pub static RETURNDATASIZE: &str = "return_data_size";
|
|||||||
|
|
||||||
pub static SET_IMMUTABLE_DATA: &str = "set_immutable_data";
|
pub static SET_IMMUTABLE_DATA: &str = "set_immutable_data";
|
||||||
|
|
||||||
pub static SET_STORAGE: &str = "set_storage";
|
pub static SET_STORAGE: &str = "set_storage_or_clear";
|
||||||
|
|
||||||
pub static VALUE_TRANSFERRED: &str = "value_transferred";
|
pub static VALUE_TRANSFERRED: &str = "value_transferred";
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user