From bb2f829361900dca4c0bfdca6a84f055251fac7d Mon Sep 17 00:00:00 2001 From: xermicus Date: Tue, 13 May 2025 15:19:00 +0200 Subject: [PATCH] expose custom PVM settings in the standard json interface (#318) Exposes the following PolkaVM specific options via the standard json interface: - Heap size - Stack size - Whether to emit source level debug information Additionally it is now forbidden to specify those as CLI option in standard JSON mode. They are bytecode altering options and having multiple ways to specify them creates unnecessary room for confusion: The standard JSON input description should be sufficient and succint for reproducible builds. Closes #290 --------- Signed-off-by: xermicus --- CHANGELOG.md | 2 ++ crates/llvm-context/src/lib.rs | 2 -- .../llvm-context/src/polkavm/context/mod.rs | 6 ++--- crates/llvm-context/src/polkavm/mod.rs | 6 ++--- crates/solc-json-interface/src/lib.rs | 2 ++ .../src/standard_json/input/mod.rs | 5 ++++ .../src/standard_json/input/settings/mod.rs | 7 +++++ .../input/settings/polkavm}/memory.rs | 0 .../input/settings/polkavm/mod.rs | 26 +++++++++++++++++++ crates/solidity/src/lib.rs | 22 +++++++++++----- crates/solidity/src/process/input.rs | 5 ++-- crates/solidity/src/project/contract/mod.rs | 3 ++- crates/solidity/src/project/mod.rs | 4 +-- crates/solidity/src/resolc/arguments.rs | 24 ++++++++++++++--- crates/solidity/src/resolc/main.rs | 13 ++++++---- crates/solidity/src/test_utils.rs | 4 +++ 16 files changed, 102 insertions(+), 29 deletions(-) rename crates/{llvm-context/src => solc-json-interface/src/standard_json/input/settings/polkavm}/memory.rs (100%) create mode 100644 crates/solc-json-interface/src/standard_json/input/settings/polkavm/mod.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fc8eb7..9f1491f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ Supported `polkadot-sdk` rev: `2503.0.1` ### Added +- Add the PolkaVM heap size, stack size and debug info CLI compiler options to the standard JSON settings. This makes the standard JSON input succint for reproducible builds. + ### Changed - Supported `polkadot-sdk` version is now `2503.0.1` diff --git a/crates/llvm-context/src/lib.rs b/crates/llvm-context/src/lib.rs index 55148d8..c7a9ae7 100644 --- a/crates/llvm-context/src/lib.rs +++ b/crates/llvm-context/src/lib.rs @@ -5,7 +5,6 @@ use std::sync::OnceLock; pub use self::debug_config::ir_type::IRType as DebugConfigIR; pub use self::debug_config::DebugConfig; -pub use self::memory::MemoryConfig; pub use self::optimizer::settings::size_level::SizeLevel as OptimizerSettingsSizeLevel; pub use self::optimizer::settings::Settings as OptimizerSettings; pub use self::optimizer::Optimizer; @@ -76,7 +75,6 @@ pub use self::target_machine::target::Target; pub use self::target_machine::TargetMachine; pub(crate) mod debug_config; -pub(crate) mod memory; pub(crate) mod optimizer; pub(crate) mod polkavm; pub(crate) mod target_machine; diff --git a/crates/llvm-context/src/polkavm/context/mod.rs b/crates/llvm-context/src/polkavm/context/mod.rs index bcebee0..be05a66 100644 --- a/crates/llvm-context/src/polkavm/context/mod.rs +++ b/crates/llvm-context/src/polkavm/context/mod.rs @@ -25,8 +25,8 @@ use inkwell::debug_info::AsDIScope; use inkwell::debug_info::DIScope; use inkwell::types::BasicType; use inkwell::values::BasicValue; +use revive_solc_json_interface::SolcStandardJsonInputSettingsPolkaVMMemory; -use crate::memory::MemoryConfig; use crate::optimizer::settings::Settings as OptimizerSettings; use crate::optimizer::Optimizer; use crate::polkavm::DebugConfig; @@ -88,7 +88,7 @@ where /// The extra LLVM arguments that were used during target initialization. llvm_arguments: &'ctx [String], /// The PVM memory configuration. - memory_config: MemoryConfig, + memory_config: SolcStandardJsonInputSettingsPolkaVMMemory, /// The project dependency manager. It can be any entity implementing the trait. /// The manager is used to get information about contracts and their dependencies during @@ -228,7 +228,7 @@ where include_metadata_hash: bool, debug_config: DebugConfig, llvm_arguments: &'ctx [String], - memory_config: MemoryConfig, + memory_config: SolcStandardJsonInputSettingsPolkaVMMemory, ) -> Self { Self::set_data_layout(llvm, &module); Self::link_stdlib_module(llvm, &module); diff --git a/crates/llvm-context/src/polkavm/mod.rs b/crates/llvm-context/src/polkavm/mod.rs index 68d32d9..de24171 100644 --- a/crates/llvm-context/src/polkavm/mod.rs +++ b/crates/llvm-context/src/polkavm/mod.rs @@ -7,12 +7,12 @@ pub mod evm; pub use self::r#const::*; use crate::debug_config::DebugConfig; -use crate::memory::MemoryConfig; use crate::optimizer::settings::Settings as OptimizerSettings; use anyhow::Context as AnyhowContext; use polkavm_common::program::ProgramBlob; use polkavm_disassembler::{Disassembler, DisassemblyFormat}; +use revive_solc_json_interface::SolcStandardJsonInputSettingsPolkaVMMemory; use sha3::Digest; use self::context::build::Build; @@ -91,7 +91,7 @@ pub trait Dependency { include_metadata_hash: bool, debug_config: DebugConfig, llvm_arguments: &[String], - memory_config: MemoryConfig, + memory_config: SolcStandardJsonInputSettingsPolkaVMMemory, ) -> anyhow::Result; /// Resolves a full contract path. @@ -113,7 +113,7 @@ impl Dependency for DummyDependency { _include_metadata_hash: bool, _debug_config: DebugConfig, _llvm_arguments: &[String], - _memory_config: MemoryConfig, + _memory_config: SolcStandardJsonInputSettingsPolkaVMMemory, ) -> anyhow::Result { Ok(String::new()) } diff --git a/crates/solc-json-interface/src/lib.rs b/crates/solc-json-interface/src/lib.rs index 3141fba..c34f887 100644 --- a/crates/solc-json-interface/src/lib.rs +++ b/crates/solc-json-interface/src/lib.rs @@ -8,6 +8,8 @@ pub use self::standard_json::input::language::Language as SolcStandardJsonInputL pub use self::standard_json::input::settings::metadata::Metadata as SolcStandardJsonInputSettingsMetadata; pub use self::standard_json::input::settings::metadata_hash::MetadataHash as SolcStandardJsonInputSettingsMetadataHash; pub use self::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer; +pub use self::standard_json::input::settings::polkavm::memory::MemoryConfig as SolcStandardJsonInputSettingsPolkaVMMemory; +pub use self::standard_json::input::settings::polkavm::PolkaVM as SolcStandardJsonInputSettingsPolkaVM; pub use self::standard_json::input::settings::selection::file::flag::Flag as SolcStandardJsonInputSettingsSelectionFileFlag; pub use self::standard_json::input::settings::selection::file::File as SolcStandardJsonInputSettingsSelectionFile; pub use self::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection; diff --git a/crates/solc-json-interface/src/standard_json/input/mod.rs b/crates/solc-json-interface/src/standard_json/input/mod.rs index 5c7d4d2..7fafe04 100644 --- a/crates/solc-json-interface/src/standard_json/input/mod.rs +++ b/crates/solc-json-interface/src/standard_json/input/mod.rs @@ -18,6 +18,7 @@ use crate::standard_json::input::settings::optimizer::Optimizer as SolcStandardJ use crate::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection; #[cfg(feature = "resolc")] use crate::warning::Warning; +use crate::SolcStandardJsonInputSettingsPolkaVM; use self::language::Language; use self::settings::Settings; @@ -63,6 +64,7 @@ impl Input { optimizer: SolcStandardJsonInputSettingsOptimizer, metadata: Option, #[cfg(feature = "resolc")] suppressed_warnings: Option>, + polkavm: Option, ) -> anyhow::Result { let mut paths: BTreeSet = paths.iter().cloned().collect(); let libraries = Settings::parse_libraries(library_map)?; @@ -90,6 +92,7 @@ impl Input { output_selection, optimizer, metadata, + polkavm, ), #[cfg(feature = "resolc")] suppressed_warnings, @@ -109,6 +112,7 @@ impl Input { optimizer: SolcStandardJsonInputSettingsOptimizer, metadata: Option, suppressed_warnings: Option>, + polkavm: Option, ) -> anyhow::Result { #[cfg(feature = "parallel")] let iter = sources.into_par_iter(); // Parallel iterator @@ -129,6 +133,7 @@ impl Input { output_selection, optimizer, metadata, + polkavm, ), suppressed_warnings, }) diff --git a/crates/solc-json-interface/src/standard_json/input/settings/mod.rs b/crates/solc-json-interface/src/standard_json/input/settings/mod.rs index 250d928..b8c5f8d 100644 --- a/crates/solc-json-interface/src/standard_json/input/settings/mod.rs +++ b/crates/solc-json-interface/src/standard_json/input/settings/mod.rs @@ -3,6 +3,7 @@ pub mod metadata; pub mod metadata_hash; pub mod optimizer; +pub mod polkavm; pub mod selection; use std::collections::BTreeMap; @@ -13,6 +14,7 @@ use serde::Serialize; use self::metadata::Metadata; use self::optimizer::Optimizer; +use self::polkavm::PolkaVM; use self::selection::Selection; /// The `solc --standard-json` input settings. @@ -43,6 +45,9 @@ pub struct Settings { /// The metadata settings. #[serde(skip_serializing_if = "Option::is_none")] pub metadata: Option, + /// The resolc custom PolkaVM settings. + #[serde(skip_serializing)] + pub polkavm: Option, } impl Settings { @@ -54,6 +59,7 @@ impl Settings { output_selection: Selection, optimizer: Optimizer, metadata: Option, + polkavm: Option, ) -> Self { Self { evm_version, @@ -63,6 +69,7 @@ impl Settings { optimizer, metadata, via_ir: Some(true), + polkavm, } } diff --git a/crates/llvm-context/src/memory.rs b/crates/solc-json-interface/src/standard_json/input/settings/polkavm/memory.rs similarity index 100% rename from crates/llvm-context/src/memory.rs rename to crates/solc-json-interface/src/standard_json/input/settings/polkavm/memory.rs diff --git a/crates/solc-json-interface/src/standard_json/input/settings/polkavm/mod.rs b/crates/solc-json-interface/src/standard_json/input/settings/polkavm/mod.rs new file mode 100644 index 0000000..2ed7f16 --- /dev/null +++ b/crates/solc-json-interface/src/standard_json/input/settings/polkavm/mod.rs @@ -0,0 +1,26 @@ +//! The `resolc --standard-json` polkavm settings. +//! +//! Used for options specific to PolkaVM which therefor don't exist in solc. + +use memory::MemoryConfig; +use serde::{Deserialize, Serialize}; + +pub mod memory; + +/// PVM specific compiler settings. +#[derive(Clone, Copy, Default, Debug, Serialize, Deserialize)] +pub struct PolkaVM { + /// The PolkaVM target machine memory configuration settings. + pub memory_config: MemoryConfig, + /// Instruct LLVM to emit debug information. + pub debug_information: bool, +} + +impl PolkaVM { + pub fn new(memory_config: Option, debug_information: bool) -> Self { + Self { + memory_config: memory_config.unwrap_or_default(), + debug_information, + } + } +} diff --git a/crates/solidity/src/lib.rs b/crates/solidity/src/lib.rs index 608c992..5d6102b 100644 --- a/crates/solidity/src/lib.rs +++ b/crates/solidity/src/lib.rs @@ -45,6 +45,8 @@ use revive_solc_json_interface::ResolcWarning; use revive_solc_json_interface::SolcStandardJsonInput; use revive_solc_json_interface::SolcStandardJsonInputLanguage; use revive_solc_json_interface::SolcStandardJsonInputSettingsOptimizer; +use revive_solc_json_interface::SolcStandardJsonInputSettingsPolkaVM; +use revive_solc_json_interface::SolcStandardJsonInputSettingsPolkaVMMemory; use revive_solc_json_interface::SolcStandardJsonInputSettingsSelection; /// Runs the Yul mode. @@ -55,7 +57,7 @@ pub fn yul( include_metadata_hash: bool, debug_config: revive_llvm_context::DebugConfig, llvm_arguments: &[String], - memory_config: revive_llvm_context::MemoryConfig, + memory_config: SolcStandardJsonInputSettingsPolkaVMMemory, ) -> anyhow::Result { let path = match input_files.len() { 1 => input_files.first().expect("Always exists"), @@ -94,7 +96,7 @@ pub fn llvm_ir( include_metadata_hash: bool, debug_config: revive_llvm_context::DebugConfig, llvm_arguments: &[String], - memory_config: revive_llvm_context::MemoryConfig, + memory_config: SolcStandardJsonInputSettingsPolkaVMMemory, ) -> anyhow::Result { let path = match input_files.len() { 1 => input_files.first().expect("Always exists"), @@ -135,7 +137,7 @@ pub fn standard_output( suppressed_warnings: Option>, debug_config: revive_llvm_context::DebugConfig, llvm_arguments: &[String], - memory_config: revive_llvm_context::MemoryConfig, + memory_config: SolcStandardJsonInputSettingsPolkaVMMemory, ) -> anyhow::Result { let solc_version = solc.version()?; @@ -154,6 +156,10 @@ pub fn standard_output( ), None, suppressed_warnings, + Some(SolcStandardJsonInputSettingsPolkaVM::new( + Some(memory_config), + debug_config.emit_debug_info, + )), )?; let source_code_files = solc_input @@ -208,9 +214,8 @@ pub fn standard_json( base_path: Option, include_paths: Vec, allow_paths: Option, - debug_config: revive_llvm_context::DebugConfig, + mut debug_config: revive_llvm_context::DebugConfig, llvm_arguments: &[String], - memory_config: revive_llvm_context::MemoryConfig, ) -> anyhow::Result<()> { let solc_version = solc.version()?; @@ -224,6 +229,9 @@ pub fn standard_json( let optimizer_settings = revive_llvm_context::OptimizerSettings::try_from(&solc_input.settings.optimizer)?; + let polkavm_settings = solc_input.settings.polkavm.unwrap_or_default(); + debug_config.emit_debug_info = polkavm_settings.debug_information; + let include_metadata_hash = match solc_input.settings.metadata { Some(ref metadata) => metadata.bytecode_hash != Some(MetadataHash::None), None => true, @@ -258,7 +266,7 @@ pub fn standard_json( include_metadata_hash, debug_config, llvm_arguments, - memory_config, + polkavm_settings.memory_config, )?; build.write_to_standard_json(&mut solc_output, &solc_version)?; } @@ -286,7 +294,7 @@ pub fn combined_json( output_directory: Option, overwrite: bool, llvm_arguments: &[String], - memory_config: revive_llvm_context::MemoryConfig, + memory_config: SolcStandardJsonInputSettingsPolkaVMMemory, ) -> anyhow::Result<()> { let build = standard_output( input_files, diff --git a/crates/solidity/src/process/input.rs b/crates/solidity/src/process/input.rs index a1e2b6d..fc91296 100644 --- a/crates/solidity/src/process/input.rs +++ b/crates/solidity/src/process/input.rs @@ -1,6 +1,7 @@ //! Process for compiling a single compilation unit. //! The input data. +use revive_solc_json_interface::SolcStandardJsonInputSettingsPolkaVMMemory; use serde::Deserialize; use serde::Serialize; @@ -23,7 +24,7 @@ pub struct Input { /// The extra LLVM arguments give used for manual control. pub llvm_arguments: Vec, /// The PVM memory configuration. - pub memory_config: revive_llvm_context::MemoryConfig, + pub memory_config: SolcStandardJsonInputSettingsPolkaVMMemory, } impl Input { @@ -35,7 +36,7 @@ impl Input { optimizer_settings: revive_llvm_context::OptimizerSettings, debug_config: revive_llvm_context::DebugConfig, llvm_arguments: Vec, - memory_config: revive_llvm_context::MemoryConfig, + memory_config: SolcStandardJsonInputSettingsPolkaVMMemory, ) -> Self { Self { contract, diff --git a/crates/solidity/src/project/contract/mod.rs b/crates/solidity/src/project/contract/mod.rs index 9af062d..334e0ad 100644 --- a/crates/solidity/src/project/contract/mod.rs +++ b/crates/solidity/src/project/contract/mod.rs @@ -5,6 +5,7 @@ pub mod metadata; use std::collections::HashSet; +use revive_solc_json_interface::SolcStandardJsonInputSettingsPolkaVMMemory; use serde::Deserialize; use serde::Serialize; use sha3::Digest; @@ -78,7 +79,7 @@ impl Contract { include_metadata_hash: bool, debug_config: revive_llvm_context::DebugConfig, llvm_arguments: &[String], - memory_config: revive_llvm_context::MemoryConfig, + memory_config: SolcStandardJsonInputSettingsPolkaVMMemory, ) -> anyhow::Result { let llvm = inkwell::context::Context::create(); let optimizer = revive_llvm_context::Optimizer::new(optimizer_settings); diff --git a/crates/solidity/src/project/mod.rs b/crates/solidity/src/project/mod.rs index 40e6861..dc5d9a9 100644 --- a/crates/solidity/src/project/mod.rs +++ b/crates/solidity/src/project/mod.rs @@ -67,7 +67,7 @@ impl Project { include_metadata_hash: bool, debug_config: revive_llvm_context::DebugConfig, llvm_arguments: &[String], - memory_config: revive_llvm_context::MemoryConfig, + memory_config: revive_solc_json_interface::SolcStandardJsonInputSettingsPolkaVMMemory, ) -> anyhow::Result { let project = self.clone(); #[cfg(feature = "parallel")] @@ -321,7 +321,7 @@ impl revive_llvm_context::PolkaVMDependency for Project { include_metadata_hash: bool, debug_config: revive_llvm_context::DebugConfig, llvm_arguments: &[String], - memory_config: revive_llvm_context::MemoryConfig, + memory_config: revive_solc_json_interface::SolcStandardJsonInputSettingsPolkaVMMemory, ) -> anyhow::Result { let contract_path = project.resolve_path(identifier)?; let contract = project diff --git a/crates/solidity/src/resolc/arguments.rs b/crates/solidity/src/resolc/arguments.rs index e9c8424..0f4670f 100644 --- a/crates/solidity/src/resolc/arguments.rs +++ b/crates/solidity/src/resolc/arguments.rs @@ -185,8 +185,8 @@ pub struct Arguments { /// 1.Increasing the heap size will increase startup costs. /// 2.The heap size contributes to the total memory size a contract can use, /// which includes the contracts code size - #[arg(long = "heap-size", default_value = "65536")] - pub heap_size: u32, + #[arg(long = "heap-size")] + pub heap_size: Option, /// The contracts total stack size in bytes. /// @@ -200,8 +200,8 @@ pub struct Arguments { /// 1.Increasing the heap size will increase startup costs. /// 2.The stack size contributes to the total memory size a contract can use, /// which includes the contracts code size - #[arg(long = "stack-size", default_value = "32768")] - pub stack_size: u32, + #[arg(long = "stack-size")] + pub stack_size: Option, } impl Arguments { @@ -330,6 +330,22 @@ impl Arguments { if self.metadata_hash.is_some() { anyhow::bail!("Metadata hash mode must specified in standard JSON input settings."); } + + if self.heap_size.is_some() { + anyhow::bail!( + "Heap size must be specified in standard JSON input polkavm memory settings." + ); + } + if self.stack_size.is_some() { + anyhow::bail!( + "Stack size must be specified in standard JSON input polkavm memory settings." + ); + } + if self.emit_source_debug_info { + anyhow::bail!( + "Debug info must be requested in standard JSON input polkavm settings." + ); + } } Ok(()) diff --git a/crates/solidity/src/resolc/main.rs b/crates/solidity/src/resolc/main.rs index ec5b8d5..7a68874 100644 --- a/crates/solidity/src/resolc/main.rs +++ b/crates/solidity/src/resolc/main.rs @@ -148,10 +148,14 @@ fn main_inner() -> anyhow::Result<()> { None => true, }; - let memory_config = revive_llvm_context::MemoryConfig { - heap_size: arguments.heap_size, - stack_size: arguments.stack_size, - }; + let mut memory_config = + revive_solc_json_interface::SolcStandardJsonInputSettingsPolkaVMMemory::default(); + if let Some(heap_size) = arguments.heap_size { + memory_config.heap_size = heap_size + } + if let Some(stack_size) = arguments.stack_size { + memory_config.stack_size = stack_size + } let build = if arguments.yul { revive_solidity::yul( @@ -181,7 +185,6 @@ fn main_inner() -> anyhow::Result<()> { arguments.allow_paths, debug_config, &arguments.llvm_arguments, - memory_config, )?; return Ok(()); } else if let Some(format) = arguments.combined_json { diff --git a/crates/solidity/src/test_utils.rs b/crates/solidity/src/test_utils.rs index 875ed27..8c227fb 100644 --- a/crates/solidity/src/test_utils.rs +++ b/crates/solidity/src/test_utils.rs @@ -98,6 +98,7 @@ pub fn build_solidity_with_options( ), None, None, + None, )?; let mut output = solc.standard_json(input, None, vec![], None)?; @@ -162,6 +163,7 @@ pub fn build_solidity_with_options_evm( ), None, None, + None, )?; let mut output = solc.standard_json(input, None, vec![], None)?; @@ -213,6 +215,7 @@ pub fn build_solidity_and_detect_missing_libraries( SolcStandardJsonInputSettingsOptimizer::new(true, None, &solc_version.default, false), None, None, + None, )?; let mut output = solc.standard_json(input, None, vec![], None)?; @@ -286,6 +289,7 @@ pub fn check_solidity_warning( SolcStandardJsonInputSettingsOptimizer::new(true, None, &solc_version.default, false), None, suppressed_warnings, + None, )?; let output = solc.standard_json(input, None, vec![], None)?;