diff --git a/Cargo.lock b/Cargo.lock index 1404b618f..2715ced0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1575,7 +1575,7 @@ dependencies = [ [[package]] name = "stellar-xdr" version = "22.0.0" -source = "git+https://github.com/stellar/rs-stellar-xdr?rev=550743b50cd3ca5a63f03f9d7175b4cfdfd9c4ac#550743b50cd3ca5a63f03f9d7175b4cfdfd9c4ac" +source = "git+https://github.com/stellar/rs-stellar-xdr?rev=39d7dbb0c12bd422ee43a6e2e3277789da4eaac8#39d7dbb0c12bd422ee43a6e2e3277789da4eaac8" dependencies = [ "arbitrary", "base64 0.13.1", diff --git a/Cargo.toml b/Cargo.toml index 4d8449e34..82ab4d2b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ wasmparser = "=0.116.1" [workspace.dependencies.stellar-xdr] version = "=22.0.0" git = "https://github.com/stellar/rs-stellar-xdr" -rev = "550743b50cd3ca5a63f03f9d7175b4cfdfd9c4ac" +rev = "39d7dbb0c12bd422ee43a6e2e3277789da4eaac8" default-features = false [workspace.dependencies.wasmi] diff --git a/soroban-env-common/src/lib.rs b/soroban-env-common/src/lib.rs index 937ee9fee..9ff21e563 100644 --- a/soroban-env-common/src/lib.rs +++ b/soroban-env-common/src/lib.rs @@ -45,7 +45,7 @@ macro_rules! tracy_span { pub struct Version<'a> { pub pkg: &'a str, pub rev: &'a str, - pub interface: u64, + pub interface: xdr::ScEnvMetaEntryInterfaceVersion, pub xdr: stellar_xdr::Version<'a>, } diff --git a/soroban-env-common/src/meta.rs b/soroban-env-common/src/meta.rs index 9a0783ea1..f79d53854 100644 --- a/soroban-env-common/src/meta.rs +++ b/soroban-env-common/src/meta.rs @@ -5,13 +5,13 @@ //! [Env](crate::Env) interface provided by the host, rather than a cryptic failure //! due to a runtime host function signature mismatch. -// Currently the only constant is `INTERFACE_VERSION` which is a u64 with a low -// and high component. The low component is a pre-release version which should -// be zero any time you make a real release, and the high component is the -// ledger version / protocol version (the two terms are used interchangably in -// the stellar codebase), which should both match the major release version of -// soroban and the major release version of stellar-core that it's embedded -// within. +// Currently the only constant is `INTERFACE_VERSION` which is a struct +// containing a 32-bit protocol version and 32-bit pre-release version. The +// pre-release version should be zero any time you make a real release, and the +// protocol version is the ledger version / protocol version (the two terms are +// used interchangably in the stellar codebase), which should both match the +// major release version of soroban and the major release version of +// stellar-core that it's embedded within. // // Protocol numbers will be checked for ordered compatibility (a host will only // run contracts built for same-or-older protocol versions than its own) whereas @@ -38,6 +38,8 @@ // nonzero pre-release number can be used to force recompiles on interface // changes. +use crate::xdr::ScEnvMetaEntryInterfaceVersion; + pub const ENV_META_V0_SECTION_NAME: &str = "contractenvmetav0"; // If the "next" feature is enabled, we're building from the "next" xdr @@ -60,17 +62,3 @@ soroban_env_macros::generate_env_meta_consts!( ledger_protocol_version: 22, pre_release_version: 0, ); - -pub const fn make_interface_version(protocol_version: u32, pre_release_version: u32) -> u64 { - ((protocol_version as u64) << 32) | (pre_release_version as u64) -} - -pub const fn get_ledger_protocol_version(interface_version: u64) -> u32 { - // The ledger protocol version is the high 32 bits of INTERFACE_VERSION - (interface_version >> 32) as u32 -} - -pub const fn get_pre_release_version(interface_version: u64) -> u32 { - // The pre-release version is the low 32 bits of INTERFACE_VERSION - interface_version as u32 -} diff --git a/soroban-env-host/Cargo.toml b/soroban-env-host/Cargo.toml index dee66a826..da1db8f61 100644 --- a/soroban-env-host/Cargo.toml +++ b/soroban-env-host/Cargo.toml @@ -100,7 +100,7 @@ p256 = {version = "0.13.2", default-features = false, features = ["alloc"]} [dev-dependencies.stellar-xdr] version = "=22.0.0" git = "https://github.com/stellar/rs-stellar-xdr" -rev = "550743b50cd3ca5a63f03f9d7175b4cfdfd9c4ac" +rev = "39d7dbb0c12bd422ee43a6e2e3277789da4eaac8" default-features = false features = ["arbitrary"] diff --git a/soroban-env-host/src/host.rs b/soroban-env-host/src/host.rs index 0a015e0cc..549c0aeb3 100644 --- a/soroban-env-host/src/host.rs +++ b/soroban-env-host/src/host.rs @@ -548,7 +548,7 @@ impl Host { &[proto.into()], )); } - if proto > meta::get_ledger_protocol_version(meta::INTERFACE_VERSION) { + if proto > meta::INTERFACE_VERSION.protocol { return Err(self.err( ScErrorType::Context, ScErrorCode::InternalError, diff --git a/soroban-env-host/src/test/hostile.rs b/soroban-env-host/src/test/hostile.rs index 3552b2d5d..0981db11d 100644 --- a/soroban-env-host/src/test/hostile.rs +++ b/soroban-env-host/src/test/hostile.rs @@ -751,8 +751,7 @@ fn test_integer_overflow() -> Result<(), HostError> { #[test] fn test_corrupt_custom_section() -> Result<(), HostError> { - use crate::meta::make_interface_version; - use crate::xdr::{Limits, ScEnvMetaEntry, WriteXdr}; + use crate::xdr::{Limits, ScEnvMetaEntry, ScEnvMetaEntryInterfaceVersion, WriteXdr}; let host = observe_host!(Host::test_host_with_recording_footprint()); host.enable_debug()?; @@ -781,9 +780,12 @@ fn test_corrupt_custom_section() -> Result<(), HostError> { )); // invalid section name - let xdr = ScEnvMetaEntry::ScEnvMetaKindInterfaceVersion(make_interface_version(20, 0)) - .to_xdr(Limits::none()) - .unwrap(); + let xdr = ScEnvMetaEntry::ScEnvMetaKindInterfaceVersion(ScEnvMetaEntryInterfaceVersion { + protocol: 20, + pre_release: 0, + }) + .to_xdr(Limits::none()) + .unwrap(); let res = host.register_test_contract_wasm_from_source_account( wasm_util::wasm_module_with_custom_section("contractenvmetav1", &xdr).as_slice(), generate_account_id(&host), @@ -828,7 +830,7 @@ fn test_corrupt_custom_section() -> Result<(), HostError> { )); // invalid: protocol is current but pre-release version doesn't match env's - let env_pre = meta::get_pre_release_version(meta::INTERFACE_VERSION); + let env_pre = meta::INTERFACE_VERSION.pre_release; let res = host.register_test_contract_wasm_from_source_account( wasm_util::wasm_module_with_custom_section( "contractenvmetav0", diff --git a/soroban-env-host/src/test/metering_benchmark.rs b/soroban-env-host/src/test/metering_benchmark.rs index cf481df09..30d077371 100644 --- a/soroban-env-host/src/test/metering_benchmark.rs +++ b/soroban-env-host/src/test/metering_benchmark.rs @@ -21,7 +21,7 @@ use crate::testutils::{generate_account_id, generate_bytes_array}; // RUST_TEST_THREADS=1 cargo test --release --package soroban-env-host --lib --features testutils -- test::metering_benchmark --nocapture --ignored const LEDGER_INFO: LedgerInfo = LedgerInfo { - protocol_version: crate::meta::get_ledger_protocol_version(crate::meta::INTERFACE_VERSION), + protocol_version: crate::meta::INTERFACE_VERSION.protocol, sequence_number: 1234, timestamp: 1234, network_id: [7; 32], diff --git a/soroban-env-host/src/test/protocol_gate.rs b/soroban-env-host/src/test/protocol_gate.rs index 282a874b7..418398e1d 100644 --- a/soroban-env-host/src/test/protocol_gate.rs +++ b/soroban-env-host/src/test/protocol_gate.rs @@ -1,5 +1,5 @@ use crate::{ - meta::{get_ledger_protocol_version, INTERFACE_VERSION}, + meta::INTERFACE_VERSION, testutils::{generate_account_id, generate_bytes_array, wasm as wasm_util}, xdr::{ScErrorCode, ScErrorType}, AddressObject, Env, Host, HostError, LedgerInfo, Symbol, Val, WasmiMarshal, @@ -9,7 +9,7 @@ use crate::{ fn ledger_protocol_greater_than_env_protocol_should_fail() -> Result<(), HostError> { let host = Host::test_host_with_recording_footprint(); host.enable_debug()?; - let env_proto = get_ledger_protocol_version(INTERFACE_VERSION); + let env_proto = INTERFACE_VERSION.protocol; // This test only makes sense if TEST_PROTOCOL is equal to the env version if env_proto != host.get_ledger_protocol_version()? { diff --git a/soroban-env-host/src/testutils.rs b/soroban-env-host/src/testutils.rs index c3e4b2019..18f9792ab 100644 --- a/soroban-env-host/src/testutils.rs +++ b/soroban-env-host/src/testutils.rs @@ -146,9 +146,11 @@ impl SnapshotSource for MockSnapshotSource { #[cfg(test)] pub(crate) fn interface_meta_with_custom_versions(proto: u32, pre: u32) -> Vec { - use crate::xdr::{Limited, Limits, ScEnvMetaEntry, WriteXdr}; - let iv = crate::meta::make_interface_version(proto, pre); - let entry = ScEnvMetaEntry::ScEnvMetaKindInterfaceVersion(iv); + use crate::xdr::{Limited, Limits, ScEnvMetaEntry, ScEnvMetaEntryInterfaceVersion, WriteXdr}; + let entry = ScEnvMetaEntry::ScEnvMetaKindInterfaceVersion(ScEnvMetaEntryInterfaceVersion { + protocol: proto, + pre_release: pre, + }); let bytes = Vec::::new(); let mut w = Limited::new(bytes, Limits::none()); entry.write_xdr(&mut w).unwrap(); @@ -163,8 +165,7 @@ impl Host { } pub fn current_test_protocol() -> u32 { - use crate::meta::{get_ledger_protocol_version, INTERFACE_VERSION}; - let max_supported_protocol = get_ledger_protocol_version(INTERFACE_VERSION); + let max_supported_protocol = crate::meta::INTERFACE_VERSION.protocol; let min_supported_protocol = crate::host::MIN_LEDGER_PROTOCOL_VERSION; if let Ok(vers) = std::env::var("TEST_PROTOCOL") { let test_protocol = vers.parse().expect("parsing TEST_PROTOCOL"); diff --git a/soroban-env-host/src/vm/parsed_module.rs b/soroban-env-host/src/vm/parsed_module.rs index 08d6ac906..096653cf8 100644 --- a/soroban-env-host/src/vm/parsed_module.rs +++ b/soroban-env-host/src/vm/parsed_module.rs @@ -1,8 +1,11 @@ use crate::{ err, host::metered_clone::MeteredContainer, - meta::{self, get_ledger_protocol_version}, - xdr::{ContractCostType, Limited, ReadXdr, ScEnvMetaEntry, ScErrorCode, ScErrorType}, + meta, + xdr::{ + ContractCostType, Limited, ReadXdr, ScEnvMetaEntry, ScEnvMetaEntryInterfaceVersion, + ScErrorCode, ScErrorType, + }, Host, HostError, DEFAULT_XDR_RW_LIMITS, }; @@ -219,18 +222,18 @@ impl ParsedModule { Self::check_max_args(host, &module)?; let interface_version = Self::check_meta_section(host, &module)?; - let contract_proto = get_ledger_protocol_version(interface_version); + let contract_proto = interface_version.protocol; Ok((module, contract_proto)) } fn check_contract_interface_version( host: &Host, - interface_version: u64, + interface_version: &ScEnvMetaEntryInterfaceVersion, ) -> Result<(), HostError> { let want_proto = { let ledger_proto = host.get_ledger_protocol_version()?; - let env_proto = get_ledger_protocol_version(meta::INTERFACE_VERSION); + let env_proto = meta::INTERFACE_VERSION.protocol; if ledger_proto <= env_proto { // ledger proto should be before or equal to env proto ledger_proto @@ -247,9 +250,9 @@ impl ParsedModule { // Not used when "next" is enabled #[cfg(not(feature = "next"))] - let got_pre = meta::get_pre_release_version(interface_version); + let got_pre = interface_version.pre_release; - let got_proto = get_ledger_protocol_version(interface_version); + let got_proto = interface_version.protocol; if got_proto < want_proto { // Old protocols are finalized, we only support contracts @@ -277,7 +280,7 @@ impl ParsedModule { { // Current protocol might have a nonzero prerelease number; we will // allow it only if it matches the current prerelease exactly. - let want_pre = meta::get_pre_release_version(meta::INTERFACE_VERSION); + let want_pre = meta::INTERFACE_VERSION.pre_release; if want_pre != got_pre { return Err(err!( host, @@ -321,7 +324,10 @@ impl ParsedModule { Self::module_custom_section(&self.module, name) } - fn check_meta_section(host: &Host, m: &Module) -> Result { + fn check_meta_section( + host: &Host, + m: &Module, + ) -> Result { if let Some(env_meta) = Self::module_custom_section(m, meta::ENV_META_V0_SECTION_NAME) { let mut limits = DEFAULT_XDR_RW_LIMITS; limits.len = env_meta.len(); @@ -329,7 +335,7 @@ impl ParsedModule { if let Some(env_meta_entry) = ScEnvMetaEntry::read_xdr_iter(&mut cursor).next() { let ScEnvMetaEntry::ScEnvMetaKindInterfaceVersion(v) = host.map_err(env_meta_entry)?; - Self::check_contract_interface_version(host, v)?; + Self::check_contract_interface_version(host, &v)?; Ok(v) } else { Err(host.err( diff --git a/soroban-env-macros/src/lib.rs b/soroban-env-macros/src/lib.rs index 6d7c2751a..7d2aff15b 100644 --- a/soroban-env-macros/src/lib.rs +++ b/soroban-env-macros/src/lib.rs @@ -17,7 +17,7 @@ use stellar_xdr::curr as xdr; #[cfg(feature = "next")] use stellar_xdr::next as xdr; -use crate::xdr::{Limits, ScEnvMetaEntry, WriteXdr}; +use crate::xdr::{Limits, ScEnvMetaEntry, ScEnvMetaEntryInterfaceVersion, WriteXdr}; // We need the protocol version for some tests generated by this crate. // Unfortunately it is not available at this layer and can't read from @@ -29,7 +29,7 @@ pub(crate) const LEDGER_PROTOCOL_VERSION: u32 = 22; pub(crate) const LEDGER_PROTOCOL_VERSION: u32 = 23; struct MetaInput { - pub interface_version: u64, + pub interface_version: ScEnvMetaEntryInterfaceVersion, } impl Parse for MetaInput { @@ -38,16 +38,17 @@ impl Parse for MetaInput { interface_version: { assert_eq!(input.parse::()?, "ledger_protocol_version"); input.parse::()?; - let proto: u64 = input.parse::()?.base10_parse()?; + let proto: u32 = input.parse::()?.base10_parse()?; input.parse::()?; assert_eq!(input.parse::()?, "pre_release_version"); input.parse::()?; - let pre: u64 = input.parse::()?.base10_parse()?; + let pre: u32 = input.parse::()?.base10_parse()?; input.parse::()?; - assert!(pre <= 0xffff_ffff); - assert!(proto <= 0xffff_ffff); - assert_eq!(proto, LEDGER_PROTOCOL_VERSION as u64); - proto << 32 | pre + assert_eq!(proto, LEDGER_PROTOCOL_VERSION); + ScEnvMetaEntryInterfaceVersion { + protocol: proto, + pre_release: pre, + } }, }) } @@ -60,7 +61,7 @@ struct MetaConstsOutput { impl MetaConstsOutput { pub fn to_meta_entries(&self) -> Vec { vec![ScEnvMetaEntry::ScEnvMetaKindInterfaceVersion( - self.input.interface_version, + self.input.interface_version.clone(), )] } } @@ -68,7 +69,8 @@ impl MetaConstsOutput { impl ToTokens for MetaConstsOutput { fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { // Build params for expressing the interface version. - let interface_version = self.input.interface_version; + let proto = &self.input.interface_version.protocol; + let pre = &self.input.interface_version.pre_release; // Build params for expressing the meta xdr. let meta_xdr = self @@ -84,7 +86,10 @@ impl ToTokens for MetaConstsOutput { // Output. tokens.extend(quote! { - pub const INTERFACE_VERSION: u64 = #interface_version; + pub const INTERFACE_VERSION: ScEnvMetaEntryInterfaceVersion = ScEnvMetaEntryInterfaceVersion{ + protocol: #proto, + pre_release: #pre, + }; pub const XDR: [u8; #meta_xdr_len] = *#meta_xdr_lit; }); } diff --git a/soroban-synth-wasm/src/mod_emitter.rs b/soroban-synth-wasm/src/mod_emitter.rs index 42a6aae1b..c0518ab47 100644 --- a/soroban-synth-wasm/src/mod_emitter.rs +++ b/soroban-synth-wasm/src/mod_emitter.rs @@ -1,5 +1,5 @@ use crate::FuncEmitter; -use soroban_env_common::xdr::{Limits, ScEnvMetaEntry, WriteXdr}; +use soroban_env_common::xdr::{Limits, ScEnvMetaEntry, ScEnvMetaEntryInterfaceVersion, WriteXdr}; use std::str::FromStr; use std::{borrow::Cow, collections::BTreeMap, env}; #[cfg(feature = "adversarial")] @@ -117,9 +117,10 @@ impl ModEmitter { /// Add a metadata section marking the module as belonging to the specified /// protocol version. pub fn add_protocol_version_meta(&mut self, protocol_version: u32) -> &mut Self { - let meta = ScEnvMetaEntry::ScEnvMetaKindInterfaceVersion( - soroban_env_common::meta::make_interface_version(protocol_version, 0), - ); + let meta = ScEnvMetaEntry::ScEnvMetaKindInterfaceVersion(ScEnvMetaEntryInterfaceVersion { + protocol: protocol_version, + pre_release: 0, + }); self.custom_section( soroban_env_common::meta::ENV_META_V0_SECTION_NAME, &meta.to_xdr(Limits::none()).unwrap(), @@ -133,9 +134,7 @@ impl ModEmitter { pub fn add_test_protocol_version_meta(&mut self) -> &mut Self { let protocol_version = env::var("TEST_PROTOCOL") .map(|v| u32::from_str(&v).unwrap()) - .unwrap_or(soroban_env_common::meta::get_ledger_protocol_version( - soroban_env_common::meta::INTERFACE_VERSION, - )); + .unwrap_or(soroban_env_common::meta::INTERFACE_VERSION.protocol); self.add_protocol_version_meta(protocol_version) }