From 80f94b5c766ec9f1205dff56a6818d53e5769143 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 5 Apr 2025 12:25:52 +0200 Subject: [PATCH 1/2] Bump openssl from 0.10.71 to 0.10.72 (#278) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [openssl](https://github.com/sfackler/rust-openssl) from 0.10.71 to 0.10.72.
Release notes

Sourced from openssl's releases.

openssl-v0.10.72

What's Changed

New Contributors

Full Changelog: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.71...openssl-v0.10.72

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=openssl&package-manager=cargo&previous-version=0.10.71&new-version=0.10.72)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/paritytech/revive/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 87524ad..a96d0a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4965,9 +4965,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.71" +version = "0.10.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" +checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" dependencies = [ "bitflags 2.8.0", "cfg-if", @@ -4997,9 +4997,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.106" +version = "0.9.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" +checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" dependencies = [ "cc", "libc", From 7d8fa75a0f066e75b49dd00c7c4cbe6746ab09fa Mon Sep 17 00:00:00 2001 From: xermicus Date: Mon, 7 Apr 2025 10:34:44 +0200 Subject: [PATCH 2/2] storage keys and values should be big endian (#277) Storage keys and values are big endian. Keeping them LE was a pre-mature optimization because for the contract itself it this is a no-op and thus not observable. However we should consider the storage layout as part of the contract ABI. The endianness of transient storage values are still kept as-is. --------- Signed-off-by: Cyrill Leutwiler --- CHANGELOG.md | 1 + crates/integration/codesize.json | 6 +- crates/integration/contracts/flipper.sol | 2 +- crates/llvm-context/src/lib.rs | 2 + .../src/polkavm/context/pointer/storage.rs | 228 +++++++++++++----- .../llvm-context/src/polkavm/evm/storage.rs | 33 +-- crates/runner/src/specs.rs | 8 +- .../src/yul/parser/statement/object.rs | 4 + 8 files changed, 196 insertions(+), 88 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c124fd..15e3b58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ Supported `polkadot-sdk` rev:`c29e72a8628835e34deb6aa7db9a78a2e4eabcee` - Support for passing LLVM command line options via the prcoess input or providing one or more `--llvm-arg='..'` resolc CLI flag. This allows more fine-grained control over the LLVM backend configuration. ### Changed +- Storage keys and values are big endian. This was a pre-mature optimization because for the contract itself it this is a no-op and thus not observable. However we should consider the storage layout as part of the contract ABI. The endianness of transient storage values are still kept as-is. - Runner `resolc` using webkit is no longer supported. ### Fixed diff --git a/crates/integration/codesize.json b/crates/integration/codesize.json index 41368a5..d9eaafc 100644 --- a/crates/integration/codesize.json +++ b/crates/integration/codesize.json @@ -2,9 +2,9 @@ "Baseline": 1443, "Computation": 2788, "DivisionArithmetics": 9748, - "ERC20": 19200, + "ERC20": 19150, "Events": 2201, "FibonacciIterative": 2041, - "Flipper": 2632, - "SHA1": 8958 + "Flipper": 2691, + "SHA1": 8997 } \ No newline at end of file diff --git a/crates/integration/contracts/flipper.sol b/crates/integration/contracts/flipper.sol index 0c2ef61..bcb922d 100644 --- a/crates/integration/contracts/flipper.sol +++ b/crates/integration/contracts/flipper.sol @@ -15,7 +15,7 @@ pragma solidity ^0.8; "Instantiated": 0 }, "key": "0000000000000000000000000000000000000000000000000000000000000000", - "expected": "0100000000000000000000000000000000000000000000000000000000000000" + "expected": "0000000000000000000000000000000000000000000000000000000000000001" } }, { diff --git a/crates/llvm-context/src/lib.rs b/crates/llvm-context/src/lib.rs index 181c870..6fcd3a2 100644 --- a/crates/llvm-context/src/lib.rs +++ b/crates/llvm-context/src/lib.rs @@ -36,7 +36,9 @@ pub use self::polkavm::context::function::Function as PolkaVMFunction; pub use self::polkavm::context::global::Global as PolkaVMGlobal; pub use self::polkavm::context::pointer::heap::LoadWord as PolkaVMLoadHeapWordFunction; pub use self::polkavm::context::pointer::heap::StoreWord as PolkaVMStoreHeapWordFunction; +pub use self::polkavm::context::pointer::storage::LoadTransientWord as PolkaVMLoadTransientStorageWordFunction; pub use self::polkavm::context::pointer::storage::LoadWord as PolkaVMLoadStorageWordFunction; +pub use self::polkavm::context::pointer::storage::StoreTransientWord as PolkaVMStoreTransientStorageWordFunction; pub use self::polkavm::context::pointer::storage::StoreWord as PolkaVMStoreStorageWordFunction; pub use self::polkavm::context::pointer::Pointer as PolkaVMPointer; pub use self::polkavm::context::r#loop::Loop as PolkaVMLoop; diff --git a/crates/llvm-context/src/polkavm/context/pointer/storage.rs b/crates/llvm-context/src/polkavm/context/pointer/storage.rs index 0f9cdf6..a28c1cb 100644 --- a/crates/llvm-context/src/polkavm/context/pointer/storage.rs +++ b/crates/llvm-context/src/polkavm/context/pointer/storage.rs @@ -17,47 +17,20 @@ where const NAME: &'static str = "__revive_load_storage_word"; fn r#type<'ctx>(context: &Context<'ctx, D>) -> inkwell::types::FunctionType<'ctx> { - context.word_type().fn_type( - &[context.xlen_type().into(), context.word_type().into()], - false, - ) + context + .word_type() + .fn_type(&[context.word_type().into()], false) } fn emit_body<'ctx>( &self, context: &mut Context<'ctx, D>, ) -> anyhow::Result>> { - let is_transient = Self::paramater(context, 0); - let key_value = Self::paramater(context, 1); - - 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_value)?; - 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 arguments = [ - is_transient, - key_pointer.to_int(context).into(), - context.xlen_type().const_all_ones().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); - - // 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). - - Ok(Some(context.build_load(value_pointer, "storage_value")?)) + Ok(Some(emit_load( + context, + Self::paramater(context, 0), + false, + )?)) } } @@ -74,6 +47,42 @@ where } } +/// Load a word size value from a transient storage pointer. +pub struct LoadTransientWord; + +impl RuntimeFunction for LoadTransientWord +where + D: Dependency + Clone, +{ + const NAME: &'static str = "__revive_load_transient_storage_word"; + + fn r#type<'ctx>(context: &Context<'ctx, D>) -> inkwell::types::FunctionType<'ctx> { + context + .word_type() + .fn_type(&[context.word_type().into()], false) + } + + fn emit_body<'ctx>( + &self, + context: &mut Context<'ctx, D>, + ) -> anyhow::Result>> { + Ok(Some(emit_load(context, Self::paramater(context, 0), true)?)) + } +} + +impl WriteLLVM for LoadTransientWord +where + D: Dependency + Clone, +{ + fn declare(&mut self, context: &mut Context) -> anyhow::Result<()> { + >::declare(self, context) + } + + fn into_llvm(self, context: &mut Context) -> anyhow::Result<()> { + >::emit(&self, context) + } +} + /// Store a word size value through a storage pointer. pub struct StoreWord; @@ -85,11 +94,7 @@ where fn r#type<'ctx>(context: &Context<'ctx, D>) -> inkwell::types::FunctionType<'ctx> { context.void_type().fn_type( - &[ - context.xlen_type().into(), - context.word_type().into(), - context.word_type().into(), - ], + &[context.word_type().into(), context.word_type().into()], false, ) } @@ -98,24 +103,12 @@ where &self, context: &mut Context<'ctx, D>, ) -> anyhow::Result>> { - let is_transient = Self::paramater(context, 0); - let key = Self::paramater(context, 1); - let value = Self::paramater(context, 2); - - 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(value_pointer, value)?; - - let arguments = [ - is_transient, - key_pointer.to_int(context).into(), - context.xlen_type().const_all_ones().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); + emit_store( + context, + Self::paramater(context, 0), + Self::paramater(context, 1), + false, + )?; Ok(None) } @@ -133,3 +126,122 @@ where >::emit(&self, context) } } + +/// Store a word size value through a transient storage pointer. +pub struct StoreTransientWord; + +impl RuntimeFunction for StoreTransientWord +where + D: Dependency + Clone, +{ + const NAME: &'static str = "__revive_store_transient_storage_word"; + + fn r#type<'ctx>(context: &Context<'ctx, D>) -> inkwell::types::FunctionType<'ctx> { + context.void_type().fn_type( + &[context.word_type().into(), context.word_type().into()], + false, + ) + } + + fn emit_body<'ctx>( + &self, + context: &mut Context<'ctx, D>, + ) -> anyhow::Result>> { + emit_store( + context, + Self::paramater(context, 0), + Self::paramater(context, 1), + true, + )?; + + Ok(None) + } +} + +impl WriteLLVM for StoreTransientWord +where + D: Dependency + Clone, +{ + fn declare(&mut self, context: &mut Context) -> anyhow::Result<()> { + >::declare(self, context) + } + + fn into_llvm(self, context: &mut Context) -> anyhow::Result<()> { + >::emit(&self, context) + } +} + +fn emit_load<'ctx, D: Dependency + Clone>( + context: &mut Context<'ctx, D>, + mut key: BasicValueEnum<'ctx>, + transient: bool, +) -> anyhow::Result> { + if !transient { + 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.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 = [ + is_transient.into(), + key_pointer.to_int(context).into(), + context.xlen_type().const_all_ones().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); + + // 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). + + let value = context.build_load(value_pointer, "storage_value")?; + Ok(if transient { + value + } else { + context.build_byte_swap(value)? + }) +} + +fn emit_store<'ctx, D: Dependency + Clone>( + context: &mut Context<'ctx, D>, + mut key: BasicValueEnum<'ctx>, + mut value: BasicValueEnum<'ctx>, + transient: bool, +) -> anyhow::Result<()> { + if !transient { + key = context.build_byte_swap(key)?; + 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(value_pointer, value)?; + + let is_transient = context.xlen_type().const_int(transient as u64, false); + + let arguments = [ + is_transient.into(), + key_pointer.to_int(context).into(), + context.xlen_type().const_all_ones().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); + + Ok(()) +} diff --git a/crates/llvm-context/src/polkavm/evm/storage.rs b/crates/llvm-context/src/polkavm/evm/storage.rs index cf409da..09f795e 100644 --- a/crates/llvm-context/src/polkavm/evm/storage.rs +++ b/crates/llvm-context/src/polkavm/evm/storage.rs @@ -4,7 +4,9 @@ use crate::polkavm::context::runtime::RuntimeFunction; use crate::polkavm::context::Context; use crate::polkavm::Dependency; use crate::PolkaVMLoadStorageWordFunction; +use crate::PolkaVMLoadTransientStorageWordFunction; use crate::PolkaVMStoreStorageWordFunction; +use crate::PolkaVMStoreTransientStorageWordFunction; /// Translates the storage load. pub fn load<'ctx, D>( @@ -16,7 +18,7 @@ where { let name = >::NAME; let declaration = >::declaration(context); - let arguments = [context.xlen_type().const_zero().into(), position.into()]; + let arguments = [position.into()]; Ok(context .build_call(declaration, &arguments, "storage_load") .unwrap_or_else(|| panic!("runtime function {name} should return a value"))) @@ -32,11 +34,7 @@ where D: Dependency + Clone, { let declaration = >::declaration(context); - let arguments = [ - context.xlen_type().const_zero().into(), - position.into(), - value.into(), - ]; + let arguments = [position.into(), value.into()]; context.build_call(declaration, &arguments, "storage_store"); Ok(()) } @@ -49,14 +47,12 @@ pub fn transient_load<'ctx, D>( where D: Dependency + Clone, { - let name = >::NAME; - let declaration = >::declaration(context); - let arguments = [ - context.xlen_type().const_int(1, false).into(), - position.into(), - ]; + let name = >::NAME; + let arguments = [position.into()]; + let declaration = + >::declaration(context); Ok(context - .build_call(declaration, &arguments, "storage_load") + .build_call(declaration, &arguments, "transient_storage_load") .unwrap_or_else(|| panic!("runtime function {name} should return a value"))) } @@ -69,12 +65,9 @@ pub fn transient_store<'ctx, D>( where D: Dependency + Clone, { - let declaration = >::declaration(context); - let arguments = [ - context.xlen_type().const_int(1, false).into(), - position.into(), - value.into(), - ]; - context.build_call(declaration, &arguments, "storage_store"); + let declaration = + >::declaration(context); + let arguments = [position.into(), value.into()]; + context.build_call(declaration, &arguments, "transient_storage_store"); Ok(()) } diff --git a/crates/runner/src/specs.rs b/crates/runner/src/specs.rs index 403ead0..0cf4839 100644 --- a/crates/runner/src/specs.rs +++ b/crates/runner/src/specs.rs @@ -106,14 +106,10 @@ impl SpecsAction { }; for (key, expected) in storage { - let mut key = **key; - let mut expected = **expected; - key.reverse(); - expected.reverse(); actions.push(Self::VerifyStorage { contract: account_pvm.clone(), - key, - expected, + key: **key, + expected: **expected, }); } diff --git a/crates/solidity/src/yul/parser/statement/object.rs b/crates/solidity/src/yul/parser/statement/object.rs index 435a087..55b2284 100644 --- a/crates/solidity/src/yul/parser/statement/object.rs +++ b/crates/solidity/src/yul/parser/statement/object.rs @@ -192,6 +192,8 @@ where revive_llvm_context::PolkaVMStoreHeapWordFunction.declare(context)?; revive_llvm_context::PolkaVMLoadStorageWordFunction.declare(context)?; revive_llvm_context::PolkaVMStoreStorageWordFunction.declare(context)?; + revive_llvm_context::PolkaVMLoadTransientStorageWordFunction.declare(context)?; + revive_llvm_context::PolkaVMStoreTransientStorageWordFunction.declare(context)?; revive_llvm_context::PolkaVMWordToPointerFunction.declare(context)?; revive_llvm_context::PolkaVMExitFunction.declare(context)?; @@ -242,6 +244,8 @@ where revive_llvm_context::PolkaVMStoreHeapWordFunction.into_llvm(context)?; revive_llvm_context::PolkaVMLoadStorageWordFunction.into_llvm(context)?; revive_llvm_context::PolkaVMStoreStorageWordFunction.into_llvm(context)?; + revive_llvm_context::PolkaVMLoadTransientStorageWordFunction.into_llvm(context)?; + revive_llvm_context::PolkaVMStoreTransientStorageWordFunction.into_llvm(context)?; revive_llvm_context::PolkaVMWordToPointerFunction.into_llvm(context)?; revive_llvm_context::PolkaVMExitFunction.into_llvm(context)?;