Skip to content

Commit

Permalink
Update with stellar-xdr with split interface version (#1453)
Browse files Browse the repository at this point in the history
### What
Update with stellar-xdr with split interface version.

### Why
See:
- stellar/stellar-xdr#212

Dependent on:
- stellar/stellar-xdr#212
- stellar/stellar-xdr#213
- stellar/rs-stellar-xdr#389
  • Loading branch information
leighmcculloch authored Sep 3, 2024
1 parent 4b366a3 commit df18803
Show file tree
Hide file tree
Showing 13 changed files with 69 additions and 68 deletions.
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 = "39d7dbb0c12bd422ee43a6e2e3277789da4eaac8"
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 = "39d7dbb0c12bd422ee43a6e2e3277789da4eaac8"
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

0 comments on commit df18803

Please sign in to comment.