Allow arbitrary call data size (#135)

Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
This commit is contained in:
Cyrill Leutwiler
2024-12-18 14:04:46 +01:00
committed by GitHub
parent afe44ad21b
commit 909de515c4
10 changed files with 999 additions and 1619 deletions
Generated
+925 -1515
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -52,7 +52,7 @@ rayon = "1.8"
clap = { version = "4", default-features = false, features = ["derive"] } clap = { version = "4", default-features = false, features = ["derive"] }
rand = "0.8" rand = "0.8"
polkavm-common = "0.17" polkavm-common = "0.17"
polkavm-linker = "0.17" polkavm-linker = "0.17.1"
polkavm-disassembler = "0.17" polkavm-disassembler = "0.17"
polkavm = "0.17" polkavm = "0.17"
alloy-primitives = { version = "0.8", features = ["serde"] } alloy-primitives = { version = "0.8", features = ["serde"] }
@@ -68,7 +68,7 @@ git2 = "0.19.0"
# polkadot-sdk and friends # polkadot-sdk and friends
codec = { version = "3.6.12", default-features = false, package = "parity-scale-codec" } codec = { version = "3.6.12", default-features = false, package = "parity-scale-codec" }
scale-info = { version = "2.11.1", default-features = false } scale-info = { version = "2.11.1", default-features = false }
polkadot-sdk = { git = "https://github.com/paritytech/polkadot-sdk", rev = "447902eff4a574e66894ad60cb41999b05bf5e84" } polkadot-sdk = { git = "https://github.com/paritytech/polkadot-sdk", rev = "4a0e3f624f42816cb4ca687d3ff9bba8e1a6bf19" }
# llvm # llvm
[workspace.dependencies.inkwell] [workspace.dependencies.inkwell]
+8 -8
View File
@@ -1,10 +1,10 @@
{ {
"Baseline": 1073, "Baseline": 1126,
"Computation": 2469, "Computation": 2405,
"DivisionArithmetics": 15041, "DivisionArithmetics": 14486,
"ERC20": 23282, "ERC20": 22755,
"Events": 1615, "Events": 1620,
"FibonacciIterative": 1676, "FibonacciIterative": 1670,
"Flipper": 2378, "Flipper": 2005,
"SHA1": 17076 "SHA1": 16832
} }
@@ -9,9 +9,6 @@ pub static XLEN: usize = revive_common::BIT_LENGTH_X32;
/// The heap memory pointer pointer global variable name. /// The heap memory pointer pointer global variable name.
pub static GLOBAL_HEAP_MEMORY_POINTER: &str = "memory_pointer"; pub static GLOBAL_HEAP_MEMORY_POINTER: &str = "memory_pointer";
/// The calldata pointer global variable name.
pub static GLOBAL_CALLDATA_POINTER: &str = "ptr_calldata";
/// The calldata size global variable name. /// The calldata size global variable name.
pub static GLOBAL_CALLDATA_SIZE: &str = "calldatasize"; pub static GLOBAL_CALLDATA_SIZE: &str = "calldatasize";
@@ -18,23 +18,12 @@ impl Entry {
/// The call flags argument index. /// The call flags argument index.
pub const ARGUMENT_INDEX_CALL_FLAGS: usize = 0; pub const ARGUMENT_INDEX_CALL_FLAGS: usize = 0;
/// Reserve 1kb for calldata.
pub const MAX_CALLDATA_SIZE: usize = 1024;
/// Initializes the global variables. /// Initializes the global variables.
/// The pointers are not initialized, because it's not possible to create a null pointer. /// The pointers are not initialized, because it's not possible to create a null pointer.
pub fn initialize_globals<D>(context: &mut Context<D>) -> anyhow::Result<()> pub fn initialize_globals<D>(context: &mut Context<D>) -> anyhow::Result<()>
where where
D: Dependency + Clone, D: Dependency + Clone,
{ {
let calldata_type = context.array_type(context.byte_type(), Self::MAX_CALLDATA_SIZE);
context.set_global(
crate::polkavm::GLOBAL_CALLDATA_POINTER,
calldata_type,
AddressSpace::Stack,
calldata_type.get_undef(),
);
context.set_global( context.set_global(
crate::polkavm::GLOBAL_HEAP_MEMORY_POINTER, crate::polkavm::GLOBAL_HEAP_MEMORY_POINTER,
context.llvm().ptr_type(AddressSpace::Heap.into()), context.llvm().ptr_type(AddressSpace::Heap.into()),
@@ -53,9 +42,9 @@ impl Entry {
context.set_global( context.set_global(
crate::polkavm::GLOBAL_CALLDATA_SIZE, crate::polkavm::GLOBAL_CALLDATA_SIZE,
context.word_type(), context.xlen_type(),
AddressSpace::Stack, AddressSpace::Stack,
context.word_undef(), context.xlen_type().get_undef(),
); );
context.set_global( context.set_global(
@@ -68,54 +57,30 @@ impl Entry {
Ok(()) Ok(())
} }
/// Load the calldata via seal `input` and initialize the calldata end /// Populate the calldata size global value.
/// and calldata size globals. pub fn load_calldata_size<D>(context: &mut Context<D>) -> anyhow::Result<()>
pub fn load_calldata<D>(context: &mut Context<D>) -> anyhow::Result<()>
where where
D: Dependency + Clone, D: Dependency + Clone,
{ {
let input_pointer = context let call_data_size_pointer = context
.get_global(crate::polkavm::GLOBAL_CALLDATA_POINTER)? .get_global(crate::polkavm::GLOBAL_CALLDATA_SIZE)?
.value .value
.as_pointer_value(); .as_pointer_value();
let input_pointer_casted = context.builder.build_ptr_to_int( let call_data_size_pointer_arg =
input_pointer, context.build_alloca_at_entry(context.word_type(), "call_data_size_pointer_arg");
context.xlen_type(),
"input_pointer_casted",
)?;
let length_pointer = context.build_alloca_at_entry(context.xlen_type(), "len_ptr");
let length_pointer_casted = context.builder.build_ptr_to_int(
length_pointer.value,
context.xlen_type(),
"length_pointer_casted",
)?;
context.build_store(
length_pointer,
context.integer_const(crate::polkavm::XLEN, Self::MAX_CALLDATA_SIZE as u64),
)?;
context.build_runtime_call( context.build_runtime_call(
revive_runtime_api::polkavm_imports::INPUT, revive_runtime_api::polkavm_imports::CALL_DATA_SIZE,
&[input_pointer_casted.into(), length_pointer_casted.into()], &[call_data_size_pointer_arg.to_int(context).into()],
); );
let value = context.build_load(call_data_size_pointer_arg, "call_data_size_load")?;
// Store the calldata size let value_truncated = context.builder().build_int_truncate(
let calldata_size = context value.into_int_value(),
.build_load(length_pointer, "input_size")? context.xlen_type(),
.into_int_value(); "call_data_size_truncated",
let calldata_size_casted = context.builder().build_int_z_extend(
calldata_size,
context.word_type(),
"zext_input_len",
)?; )?;
context.set_global( context
crate::polkavm::GLOBAL_CALLDATA_SIZE, .builder()
context.word_type(), .build_store(call_data_size_pointer, value_truncated)?;
AddressSpace::Stack,
calldata_size_casted,
);
Ok(()) Ok(())
} }
@@ -220,7 +185,7 @@ where
context.set_basic_block(context.current_function().borrow().entry_block()); context.set_basic_block(context.current_function().borrow().entry_block());
Self::initialize_globals(context)?; Self::initialize_globals(context)?;
Self::load_calldata(context)?; Self::load_calldata_size(context)?;
Self::leave_entry(context)?; Self::leave_entry(context)?;
context.build_unconditional_branch(context.current_function().borrow().return_block()); context.build_unconditional_branch(context.current_function().borrow().return_block());
+27 -29
View File
@@ -1,10 +1,7 @@
//! Translates the calldata instructions. //! Translates the calldata instructions.
use crate::polkavm::context::address_space::AddressSpace;
use crate::polkavm::context::pointer::Pointer;
use crate::polkavm::context::Context; use crate::polkavm::context::Context;
use crate::polkavm::Dependency; use crate::polkavm::Dependency;
use inkwell::types::BasicType;
/// Translates the calldata load. /// Translates the calldata load.
pub fn load<'ctx, D>( pub fn load<'ctx, D>(
@@ -14,19 +11,15 @@ pub fn load<'ctx, D>(
where where
D: Dependency + Clone, D: Dependency + Clone,
{ {
let calldata_pointer = context let output_pointer = context.build_alloca_at_entry(context.word_type(), "call_data_output");
.get_global(crate::polkavm::GLOBAL_CALLDATA_POINTER)? let offset = context.safe_truncate_int_to_xlen(offset)?;
.value
.as_pointer_value(); context.build_runtime_call(
let offset = context.build_gep( revive_runtime_api::polkavm_imports::CALL_DATA_LOAD,
Pointer::new(context.byte_type(), AddressSpace::Stack, calldata_pointer), &[output_pointer.to_int(context).into(), offset.into()],
&[offset],
context.word_type().as_basic_type_enum(),
"calldata_pointer_with_offset",
); );
context
.build_load(offset, "calldata_value") context.build_load(output_pointer, "call_data_load_value")
.and_then(|value| context.build_byte_swap(value))
} }
/// Translates the calldata size. /// Translates the calldata size.
@@ -37,8 +30,14 @@ where
D: Dependency + Clone, D: Dependency + Clone,
{ {
let value = context.get_global_value(crate::polkavm::GLOBAL_CALLDATA_SIZE)?; let value = context.get_global_value(crate::polkavm::GLOBAL_CALLDATA_SIZE)?;
Ok(context
Ok(value) .builder()
.build_int_z_extend(
value.into_int_value(),
context.word_type(),
"call_data_size_value",
)?
.into())
} }
/// Translates the calldata copy. /// Translates the calldata copy.
@@ -51,20 +50,19 @@ pub fn copy<'ctx, D>(
where where
D: Dependency + Clone, D: Dependency + Clone,
{ {
let offset = context.safe_truncate_int_to_xlen(destination_offset)?; let source_offset = context.safe_truncate_int_to_xlen(source_offset)?;
let size = context.safe_truncate_int_to_xlen(size)?; let size = context.safe_truncate_int_to_xlen(size)?;
let destination = context.build_heap_gep(offset, size)?; let destination_offset = context.safe_truncate_int_to_xlen(destination_offset)?;
let output_pointer = context.build_heap_gep(destination_offset, size)?;
let calldata_pointer = context context.build_runtime_call(
.get_global(crate::polkavm::GLOBAL_CALLDATA_POINTER)? revive_runtime_api::polkavm_imports::CALL_DATA_COPY,
.value &[
.as_pointer_value(); output_pointer.to_int(context).into(),
let source = context.build_gep( size.into(),
Pointer::new(context.byte_type(), AddressSpace::Stack, calldata_pointer), source_offset.into(),
&[context.safe_truncate_int_to_xlen(source_offset)?], ],
context.byte_type(),
"calldata_pointer_with_offset",
); );
context.build_memcpy(destination, source, size, "calldata_copy_memcpy_from_child") Ok(())
} }
Binary file not shown.
+2 -2
View File
@@ -421,7 +421,7 @@ impl Specs {
origin, origin,
value, value,
gas_limit.unwrap_or(GAS_LIMIT), gas_limit.unwrap_or(GAS_LIMIT),
storage_deposit_limit.unwrap_or(DEPOSIT_LIMIT), storage_deposit_limit.unwrap_or(DEPOSIT_LIMIT).into(),
code, code,
data, data,
salt.0, salt.0,
@@ -461,7 +461,7 @@ impl Specs {
dest.to_eth_addr(&results), dest.to_eth_addr(&results),
value, value,
gas_limit.unwrap_or(GAS_LIMIT), gas_limit.unwrap_or(GAS_LIMIT),
storage_deposit_limit.unwrap_or(DEPOSIT_LIMIT), storage_deposit_limit.unwrap_or(DEPOSIT_LIMIT).into(),
data, data,
DebugInfo::Skip, DebugInfo::Skip,
CollectEvents::Skip, CollectEvents::Skip,
+6 -2
View File
@@ -76,6 +76,12 @@ POLKAVM_IMPORT(void, block_number, uint32_t)
POLKAVM_IMPORT(uint64_t, call, uint32_t) POLKAVM_IMPORT(uint64_t, call, uint32_t)
POLKAVM_IMPORT(uint64_t, call_data_copy, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(uint64_t, call_data_load, uint32_t, uint32_t)
POLKAVM_IMPORT(uint64_t, call_data_size, uint32_t)
POLKAVM_IMPORT(uint64_t, delegate_call, uint32_t) POLKAVM_IMPORT(uint64_t, delegate_call, uint32_t)
POLKAVM_IMPORT(void, caller, uint32_t) POLKAVM_IMPORT(void, caller, uint32_t)
@@ -94,8 +100,6 @@ POLKAVM_IMPORT(uint64_t, get_storage, uint32_t, uint32_t, uint32_t, uint32_t, ui
POLKAVM_IMPORT(void, hash_keccak_256, uint32_t, uint32_t, uint32_t) POLKAVM_IMPORT(void, hash_keccak_256, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(void, input, uint32_t, uint32_t)
POLKAVM_IMPORT(uint64_t, instantiate, uint32_t) POLKAVM_IMPORT(uint64_t, instantiate, uint32_t)
POLKAVM_IMPORT(void, now, uint32_t) POLKAVM_IMPORT(void, now, uint32_t)
+10 -4
View File
@@ -26,6 +26,12 @@ pub static BLOCK_NUMBER: &str = "block_number";
pub static CALL: &str = "call"; pub static CALL: &str = "call";
pub static CALL_DATA_COPY: &str = "call_data_copy";
pub static CALL_DATA_LOAD: &str = "call_data_load";
pub static CALL_DATA_SIZE: &str = "call_data_size";
pub static DELEGATE_CALL: &str = "delegate_call"; pub static DELEGATE_CALL: &str = "delegate_call";
pub static CALLER: &str = "caller"; pub static CALLER: &str = "caller";
@@ -44,8 +50,6 @@ pub static GET_STORAGE: &str = "get_storage";
pub static HASH_KECCAK_256: &str = "hash_keccak_256"; pub static HASH_KECCAK_256: &str = "hash_keccak_256";
pub static INPUT: &str = "input";
pub static INSTANTIATE: &str = "instantiate"; pub static INSTANTIATE: &str = "instantiate";
pub static NOW: &str = "now"; pub static NOW: &str = "now";
@@ -68,7 +72,7 @@ pub static WEIGHT_TO_FEE: &str = "weight_to_fee";
/// All imported runtime API symbols. /// All imported runtime API symbols.
/// Useful for configuring common attributes and linkage. /// Useful for configuring common attributes and linkage.
pub static IMPORTS: [&str; 28] = [ pub static IMPORTS: [&str; 30] = [
SBRK, SBRK,
MEMORY_SIZE, MEMORY_SIZE,
ADDRESS, ADDRESS,
@@ -77,6 +81,9 @@ pub static IMPORTS: [&str; 28] = [
BLOCK_HASH, BLOCK_HASH,
BLOCK_NUMBER, BLOCK_NUMBER,
CALL, CALL,
CALL_DATA_COPY,
CALL_DATA_LOAD,
CALL_DATA_SIZE,
DELEGATE_CALL, DELEGATE_CALL,
CALLER, CALLER,
CHAIN_ID, CHAIN_ID,
@@ -86,7 +93,6 @@ pub static IMPORTS: [&str; 28] = [
GET_IMMUTABLE_DATA, GET_IMMUTABLE_DATA,
GET_STORAGE, GET_STORAGE,
HASH_KECCAK_256, HASH_KECCAK_256,
INPUT,
INSTANTIATE, INSTANTIATE,
NOW, NOW,
ORIGIN, ORIGIN,