From 968538dcea5b0ba4d5a0acc7c55d0ad4d82e3da1 Mon Sep 17 00:00:00 2001 From: Edgars Date: Fri, 14 Aug 2026 13:49:24 +0100 Subject: [PATCH] refactor: name decided contract state explicitly --- executor/codegen/data/public-abi.json | 8 +++-- executor/crates/sdk-rs/src/abi/consts.rs | 24 +++++++++----- executor/crates/sdk-rs/src/abi/mod.rs | 32 +++++++++++++++++++ executor/src/host/mod.rs | 6 ++-- executor/src/lib.rs | 10 +++--- executor/src/runners/mod.rs | 9 +++--- executor/src/wasi/genlayer_sdk/run.rs | 6 ++-- .../src/genlayer/contract/__init__.py | 4 +-- .../src/genlayer/vm/public_abi.py | 6 ++-- .../genlayer-py-std/tests/test_public_abi.py | 16 ++++++++++ 10 files changed, 92 insertions(+), 29 deletions(-) create mode 100644 runners/genlayer-py-std/tests/test_public_abi.py diff --git a/executor/codegen/data/public-abi.json b/executor/codegen/data/public-abi.json index 54b38ceb1..29bf141da 100644 --- a/executor/codegen/data/public-abi.json +++ b/executor/codegen/data/public-abi.json @@ -16,8 +16,12 @@ "repr": "u8", "values": { "default": 0, - "latest_final": 1, - "latest_non_final": 2 + "latest_finalized": 1, + "latest_decided": 2 + }, + "aliases": { + "latest_final": "latest_finalized", + "latest_non_final": "latest_decided" } }, { diff --git a/executor/crates/sdk-rs/src/abi/consts.rs b/executor/crates/sdk-rs/src/abi/consts.rs index 6c70baa9a..ee838c861 100644 --- a/executor/crates/sdk-rs/src/abi/consts.rs +++ b/executor/crates/sdk-rs/src/abi/consts.rs @@ -70,24 +70,32 @@ impl TryFrom for ResultCode { #[repr(u8)] pub enum StorageType { Default = 0, - LatestFinal = 1, - LatestNonFinal = 2, + #[serde(alias = "LatestFinal")] + LatestFinalized = 1, + #[serde(alias = "LatestNonFinal")] + LatestDecided = 2, } impl StorageType { pub const SIZE: usize = 3; + #[deprecated(note = "use `StorageType::LatestFinalized`")] + #[allow(non_upper_case_globals)] + pub const LatestFinal: Self = Self::LatestFinalized; + #[deprecated(note = "use `StorageType::LatestDecided`")] + #[allow(non_upper_case_globals)] + pub const LatestNonFinal: Self = Self::LatestDecided; pub fn value(self) -> u8 { match self { StorageType::Default => 0, - StorageType::LatestFinal => 1, - StorageType::LatestNonFinal => 2, + StorageType::LatestFinalized => 1, + StorageType::LatestDecided => 2, } } pub fn str_snake_case(self) -> &'static str { match self { StorageType::Default => "default", - StorageType::LatestFinal => "latest_final", - StorageType::LatestNonFinal => "latest_non_final", + StorageType::LatestFinalized => "latest_finalized", + StorageType::LatestDecided => "latest_decided", } } } @@ -98,8 +106,8 @@ impl TryFrom for StorageType { fn try_from(value: u8) -> Result { match value { 0 => Ok(StorageType::Default), - 1 => Ok(StorageType::LatestFinal), - 2 => Ok(StorageType::LatestNonFinal), + 1 => Ok(StorageType::LatestFinalized), + 2 => Ok(StorageType::LatestDecided), _ => Err(()), } } diff --git a/executor/crates/sdk-rs/src/abi/mod.rs b/executor/crates/sdk-rs/src/abi/mod.rs index 0bd2e3e08..536beb8c0 100644 --- a/executor/crates/sdk-rs/src/abi/mod.rs +++ b/executor/crates/sdk-rs/src/abi/mod.rs @@ -40,6 +40,38 @@ pub struct CallKey( pub [u8; 32], ); +#[cfg(test)] +mod storage_type_tests { + use super::consts::StorageType; + use serde::Deserialize; + + #[test] + #[allow(deprecated)] + fn decided_names_preserve_wire_values_and_legacy_aliases() { + fn legacy_match(value: StorageType) -> u8 { + match value { + StorageType::Default => 0, + StorageType::LatestFinal => 1, + StorageType::LatestNonFinal => 2, + } + } + + assert_eq!(StorageType::LatestFinalized.value(), 1); + assert_eq!(StorageType::LatestDecided.value(), 2); + assert_eq!(StorageType::try_from(1), Ok(StorageType::LatestFinalized)); + assert_eq!(StorageType::try_from(2), Ok(StorageType::LatestDecided)); + assert_eq!(StorageType::LatestFinal, StorageType::LatestFinalized); + assert_eq!(StorageType::LatestNonFinal, StorageType::LatestDecided); + assert_eq!(legacy_match(StorageType::LatestDecided), 2); + let legacy_name = + serde::de::value::StrDeserializer::::new("LatestNonFinal"); + assert_eq!( + StorageType::deserialize(legacy_name).unwrap(), + StorageType::LatestDecided + ); + } +} + impl CallKey { pub const DEPLOY: CallKey = CallKey([0u8; 32]); pub const UNNAMED: CallKey = CallKey([0u8; 32]); diff --git a/executor/src/host/mod.rs b/executor/src/host/mod.rs index 5dfb40daa..0ce7457bb 100644 --- a/executor/src/host/mod.rs +++ b/executor/src/host/mod.rs @@ -866,7 +866,7 @@ mod tests { host_fns::Methods::ResolveCallcontractExecutor as u8 ); assert_eq!(&request[1..21], &[7; 20]); - assert_eq!(request[21], StorageType::LatestFinal as u8); + assert_eq!(request[21], StorageType::LatestFinalized as u8); assert_eq!(request[22], 3); let encoded = calldata::encode_obj(&reply); @@ -883,7 +883,7 @@ mod tests { let result = host .resolve_callcontract_executor( calldata::Address::from([7; 20]), - StorageType::LatestFinal, + StorageType::LatestFinalized, 3, ) .expect("resolve executor"); @@ -954,7 +954,7 @@ mod tests { }, stack: Vec::new(), permissions: genvm_modules_interfaces::NestedPermissions::DETERMINISTIC, - state_mode: genvm_modules_interfaces::NestedStorageType::LatestNonFinal, + state_mode: genvm_modules_interfaces::NestedStorageType::LatestDecided, topmost_runner_id: genvm_modules_interfaces::NestedRunnerId("contract".to_owned()), remaining_recursion: 4, remaining_det_fuel: primitive_types::U256::from(10), diff --git a/executor/src/lib.rs b/executor/src/lib.rs index ff794ea82..c45ed5328 100644 --- a/executor/src/lib.rs +++ b/executor/src/lib.rs @@ -188,11 +188,11 @@ fn convert_nested_storage_type( ) -> public_abi::StorageType { match state_mode { genvm_modules_interfaces::NestedStorageType::Default => public_abi::StorageType::Default, - genvm_modules_interfaces::NestedStorageType::LatestFinal => { - public_abi::StorageType::LatestFinal + genvm_modules_interfaces::NestedStorageType::LatestFinalized => { + public_abi::StorageType::LatestFinalized } - genvm_modules_interfaces::NestedStorageType::LatestNonFinal => { - public_abi::StorageType::LatestNonFinal + genvm_modules_interfaces::NestedStorageType::LatestDecided => { + public_abi::StorageType::LatestDecided } } } @@ -257,7 +257,7 @@ pub async fn run_with_impl( ), None => (None, None, None, Vec::new()), }; - let storage_read_mode = imported_state_mode.unwrap_or(public_abi::StorageType::LatestNonFinal); + let storage_read_mode = imported_state_mode.unwrap_or(public_abi::StorageType::LatestDecided); let mut topmost_storage = rt::vm::storage::Storage::new( entry_data.message.contract_address, diff --git a/executor/src/runners/mod.rs b/executor/src/runners/mod.rs index b3cfe7497..0a0a12809 100644 --- a/executor/src/runners/mod.rs +++ b/executor/src/runners/mod.rs @@ -36,7 +36,7 @@ impl ChainState { ChainState::Deploy } else { match state { - crate::public_abi::StorageType::LatestFinal => ChainState::Finalized, + crate::public_abi::StorageType::LatestFinalized => ChainState::Finalized, _ => ChainState::Accepted, } } @@ -44,8 +44,8 @@ impl ChainState { pub fn host_storage_type(self) -> Option { match self { - ChainState::Accepted => Some(crate::public_abi::StorageType::LatestNonFinal), - ChainState::Finalized => Some(crate::public_abi::StorageType::LatestFinal), + ChainState::Accepted => Some(crate::public_abi::StorageType::LatestDecided), + ChainState::Finalized => Some(crate::public_abi::StorageType::LatestFinalized), ChainState::Deploy => None, } } @@ -66,7 +66,8 @@ impl ChainState { /// - `contract` -- the runner of the contract that is currently being executed. /// - `chain:
::` -- read the runner code blob from a storage /// slot of an arbitrary contract. `address` is a `0x`-prefixed 20 byte hex -/// address, `a`/`f` selects accepted (latest non final) / finalized state and +/// address, `a`/`f` selects the latest decided / finalized state. The legacy +/// `a` spelling is retained in runner IDs for wire compatibility. /// `slot` is a 32 byte slot id encoded with GVM32 (Crockford Base32). /// Both `` and `` are optional: `` defaults to `a` and /// `` defaults to reading the target contract's root slot during diff --git a/executor/src/wasi/genlayer_sdk/run.rs b/executor/src/wasi/genlayer_sdk/run.rs index e942cf406..1b1640b28 100644 --- a/executor/src/wasi/genlayer_sdk/run.rs +++ b/executor/src/wasi/genlayer_sdk/run.rs @@ -308,7 +308,7 @@ impl ContextVFS<'_> { state_mode: state, topmost_runner_id: runners::Id::Chain { address, - on: if state == public_abi::StorageType::LatestFinal { + on: if state == public_abi::StorageType::LatestFinalized { runners::ChainState::Finalized } else { runners::ChainState::Accepted @@ -395,8 +395,8 @@ impl ContextVFS<'_> { let state_mode = match vm_data.conf.execution.state_mode { public_abi::StorageType::Default => NestedStorageType::Default, - public_abi::StorageType::LatestFinal => NestedStorageType::LatestFinal, - public_abi::StorageType::LatestNonFinal => NestedStorageType::LatestNonFinal, + public_abi::StorageType::LatestFinalized => NestedStorageType::LatestFinalized, + public_abi::StorageType::LatestDecided => NestedStorageType::LatestDecided, }; let message = &vm_data.message_data.message; let envelope = NestedRunEnvelope { diff --git a/runners/genlayer-py-std/src/genlayer/contract/__init__.py b/runners/genlayer-py-std/src/genlayer/contract/__init__.py index 0efc5c413..15bb0d315 100644 --- a/runners/genlayer-py-std/src/genlayer/contract/__init__.py +++ b/runners/genlayer-py-std/src/genlayer/contract/__init__.py @@ -122,7 +122,7 @@ class Proxy[TView, TSend](IAccount, typing.Protocol): :param TSend: Type representing available write methods """ - def view(self, *, state: StorageType = StorageType.LATEST_NON_FINAL) -> TView: + def view(self, *, state: StorageType = StorageType.LATEST_DECIDED) -> TView: """ Get a namespace for calling view methods. @@ -209,7 +209,7 @@ def __init__(self, addr: Address): def address(self) -> Address: return self._address - def view(self, *, state: StorageType = StorageType.LATEST_NON_FINAL) -> ErasedMethods: + def view(self, *, state: StorageType = StorageType.LATEST_DECIDED) -> ErasedMethods: return _ContractAtGetter(_ContractAtViewMethod, self._address, state) def emit( diff --git a/runners/genlayer-py-std/src/genlayer/vm/public_abi.py b/runners/genlayer-py-std/src/genlayer/vm/public_abi.py index cc3445bb2..c5dee787f 100644 --- a/runners/genlayer-py-std/src/genlayer/vm/public_abi.py +++ b/runners/genlayer-py-std/src/genlayer/vm/public_abi.py @@ -16,8 +16,10 @@ class ResultCode(IntEnum): class StorageType(IntEnum): DEFAULT = 0 - LATEST_FINAL = 1 - LATEST_NON_FINAL = 2 + LATEST_FINALIZED = 1 + LATEST_DECIDED = 2 + LATEST_FINAL = LATEST_FINALIZED # Deprecated alias + LATEST_NON_FINAL = LATEST_DECIDED # Deprecated alias class EntryKind(IntEnum): diff --git a/runners/genlayer-py-std/tests/test_public_abi.py b/runners/genlayer-py-std/tests/test_public_abi.py new file mode 100644 index 000000000..bcd6d3ff7 --- /dev/null +++ b/runners/genlayer-py-std/tests/test_public_abi.py @@ -0,0 +1,16 @@ +import inspect + +from genlayer.contract import Proxy, _ContractAt +from genlayer.vm.public_abi import StorageType + + +def test_storage_type_decided_names_preserve_wire_values_and_legacy_aliases(): + assert StorageType.LATEST_FINALIZED.value == 1 + assert StorageType.LATEST_DECIDED.value == 2 + assert StorageType.LATEST_FINAL is StorageType.LATEST_FINALIZED + assert StorageType.LATEST_NON_FINAL is StorageType.LATEST_DECIDED + + +def test_contract_views_default_to_latest_decided(): + assert inspect.signature(Proxy.view).parameters['state'].default is StorageType.LATEST_DECIDED + assert inspect.signature(_ContractAt.view).parameters['state'].default is StorageType.LATEST_DECIDED