Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update with stellar-xdr with split interface version #1453

Merged
merged 3 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "e08df01edac8830113869dccb296f64943e8f58e"
default-features = false

[workspace.dependencies.wasmi]
Expand Down
2 changes: 1 addition & 1 deletion soroban-env-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
}

Expand Down
30 changes: 9 additions & 21 deletions soroban-env-common/src/meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
}
2 changes: 1 addition & 1 deletion soroban-env-host/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "e08df01edac8830113869dccb296f64943e8f58e"
default-features = false
features = ["arbitrary"]

Expand Down
2 changes: 1 addition & 1 deletion soroban-env-host/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
14 changes: 8 additions & 6 deletions soroban-env-host/src/test/hostile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()?;
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion soroban-env-host/src/test/metering_benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand Down
4 changes: 2 additions & 2 deletions soroban-env-host/src/test/protocol_gate.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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()? {
Expand Down
11 changes: 6 additions & 5 deletions soroban-env-host/src/testutils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,11 @@ impl SnapshotSource for MockSnapshotSource {

#[cfg(test)]
pub(crate) fn interface_meta_with_custom_versions(proto: u32, pre: u32) -> Vec<u8> {
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::<u8>::new();
let mut w = Limited::new(bytes, Limits::none());
entry.write_xdr(&mut w).unwrap();
Expand All @@ -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");
Expand Down
26 changes: 16 additions & 10 deletions soroban-env-host/src/vm/parsed_module.rs
Original file line number Diff line number Diff line change
@@ -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,
};

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -321,15 +324,18 @@ impl ParsedModule {
Self::module_custom_section(&self.module, name)
}

fn check_meta_section(host: &Host, m: &Module) -> Result<u64, HostError> {
fn check_meta_section(
host: &Host,
m: &Module,
) -> Result<ScEnvMetaEntryInterfaceVersion, HostError> {
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();
let mut cursor = Limited::new(Cursor::new(env_meta), limits);
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(
Expand Down
27 changes: 16 additions & 11 deletions soroban-env-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand All @@ -38,16 +38,17 @@ impl Parse for MetaInput {
interface_version: {
assert_eq!(input.parse::<Ident>()?, "ledger_protocol_version");
input.parse::<Token![:]>()?;
let proto: u64 = input.parse::<LitInt>()?.base10_parse()?;
let proto: u32 = input.parse::<LitInt>()?.base10_parse()?;
input.parse::<Token![,]>()?;
assert_eq!(input.parse::<Ident>()?, "pre_release_version");
input.parse::<Token![:]>()?;
let pre: u64 = input.parse::<LitInt>()?.base10_parse()?;
let pre: u32 = input.parse::<LitInt>()?.base10_parse()?;
input.parse::<Token![,]>()?;
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,
}
},
})
}
Expand All @@ -60,15 +61,16 @@ struct MetaConstsOutput {
impl MetaConstsOutput {
pub fn to_meta_entries(&self) -> Vec<ScEnvMetaEntry> {
vec![ScEnvMetaEntry::ScEnvMetaKindInterfaceVersion(
self.input.interface_version,
self.input.interface_version.clone(),
)]
}
}

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
Expand All @@ -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;
});
}
Expand Down
13 changes: 6 additions & 7 deletions soroban-synth-wasm/src/mod_emitter.rs
Original file line number Diff line number Diff line change
@@ -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")]
Expand Down Expand Up @@ -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(),
Expand All @@ -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)
}

Expand Down
Loading